diff --git a/ts/numbering/level.ts b/ts/numbering/level.ts index 8fd647e6fc..8f8cf7bce6 100644 --- a/ts/numbering/level.ts +++ b/ts/numbering/level.ts @@ -214,3 +214,5 @@ export class Level extends LevelBase { super(level, 1, numberFormat, levelText, lvlJc); } } + +export class LevelForOverride extends LevelBase {} diff --git a/ts/numbering/num.ts b/ts/numbering/num.ts index ef7281dc78..8bdd6e9adc 100644 --- a/ts/numbering/num.ts +++ b/ts/numbering/num.ts @@ -1,4 +1,5 @@ import { Attributes, XmlAttributeComponent, XmlComponent } from "../docx/xml-components"; +import { LevelForOverride } from "./level"; class AbstractNumId extends XmlComponent { @@ -29,4 +30,51 @@ export class Num extends XmlComponent { this.root.push(new AbstractNumId(abstractNumId)); this.id = numId; } + + public overrideLevel(num: number, start?: number): LevelOverride { + const olvl = new LevelOverride(num, start); + this.root.push(olvl); + return olvl; + } +} + +class LevelOverrideAttributes extends XmlAttributeComponent<{ilvl: number}> { + protected xmlKeys = {ilvl: "w:ilvl"}; +} + +class LevelOverride extends XmlComponent { + private levelNum: number; + private lvl?: LevelForOverride; + + constructor(levelNum: number, start?: number) { + super("w:lvlOverride"); + this.root.push(new LevelOverrideAttributes({ilvl: levelNum})); + if (start !== undefined) { + this.root.push(new StartOverride(start)); + } + this.levelNum = levelNum; + } + + get level(): LevelForOverride { + let lvl: LevelForOverride; + if (!this.lvl) { + lvl = new LevelForOverride(this.levelNum); + this.root.push(lvl); + this.lvl = lvl; + } else { + lvl = this.lvl; + } + return lvl; + } +} + +class StartOverrideAttributes extends XmlAttributeComponent<{val: number}> { + protected xmlKeys = {val: "w:val"}; +} + +class StartOverride extends XmlComponent { + constructor(start: number) { + super("w:startOverride"); + this.root.push(new StartOverrideAttributes({val: start})); + } } diff --git a/ts/tests/numberingTest.ts b/ts/tests/numberingTest.ts index 59a71e720e..f280a00dc4 100644 --- a/ts/tests/numberingTest.ts +++ b/ts/tests/numberingTest.ts @@ -2,6 +2,7 @@ import { expect } from "chai"; import { Formatter } from "../export/formatter"; import { Numbering } from "../numbering"; import { AbstractNumbering } from "../numbering/abstract-numbering"; +import { LevelForOverride } from "../numbering/level"; import { Num } from "../numbering/num"; describe("Numbering", () => { @@ -394,3 +395,50 @@ describe("AbstractNumbering", () => { }); }); }); + +describe("concrete numbering", () => { + describe("#overrideLevel", () => { + let numbering; + let abstractNumbering; + let concreteNumbering; + beforeEach(() => { + numbering = new Numbering(); + abstractNumbering = numbering.createAbstractNumbering(); + concreteNumbering = numbering.createConcreteNumbering(abstractNumbering); + + }); + + it("sets a new override level for the given level number", () => { + concreteNumbering.overrideLevel(3); + const tree = new Formatter().format(concreteNumbering); + expect(tree["w:num"]).to.include({"w:lvlOverride": [{_attr: {"w:ilvl": 3}}]}); + }); + + it("sets the startOverride element if start is given", () => { + concreteNumbering.overrideLevel(1, 9); + const tree = new Formatter().format(concreteNumbering); + expect(tree["w:num"]).to.include({ + "w:lvlOverride": [ + {_attr: {"w:ilvl": 1}}, + {"w:startOverride": [{_attr: {"w:val": 9}}]}, + ], + }); + }); + + it("sets the lvl element if overrideLevel.level is accessed", () => { + const ol = concreteNumbering.overrideLevel(1); + expect(ol.level).to.be.instanceof(LevelForOverride); + const tree = new Formatter().format(concreteNumbering); + expect(tree["w:num"]).to.include({ + "w:lvlOverride": [ + {_attr: {"w:ilvl": 1}}, + {"w:lvl": [ + {_attr: {"w15:tentative": 1, "w:ilvl": 1}}, + {"w:pPr": []}, + {"w:rPr": []}, + ]}, + ], + }); + }); + }); +});