Compare commits

..

5 Commits
2.0.0 ... 2.0.1

Author SHA1 Message Date
a706455a7c Merge pull request #30 from felipeochoa/overrides
Add support for numbering level overrides
2017-04-12 18:34:07 +01:00
8c388a95c4 bump patch version 2017-04-12 16:01:26 +02:00
9a41d78ecb add an additional demo 2017-04-12 16:00:16 +02:00
6fc4ad782a add #overrideLevel method to concrete numberings 2017-04-12 16:00:16 +02:00
16b9057ac6 prepare Level to be extended for overrides 2017-04-12 15:57:26 +02:00
5 changed files with 193 additions and 8 deletions

70
demo/demo2.js Normal file
View File

@ -0,0 +1,70 @@
const docx = require('../build');
const styles = new docx.Styles();
styles.createParagraphStyle('Heading1', 'Heading 1')
.basedOn("Normal")
.next("Normal")
.quickFormat()
.size(28)
.bold()
.italics()
.spacing({after: 120});
styles.createParagraphStyle('Heading2', 'Heading 2')
.basedOn("Normal")
.next("Normal")
.quickFormat()
.size(26)
.bold()
.underline('double', 'FF0000')
.spacing({before: 240, after: 120});
styles.createParagraphStyle('aside', 'Aside')
.basedOn('Normal')
.next('Normal')
.color('999999')
.italics()
.indent(720)
.spacing({line: 276});
styles.createParagraphStyle('wellSpaced', 'Well Spaced')
.basedOn('Normal')
.spacing({line: 276, before: 20 * 72 * .1, after: 20 * 72 * .05});
styles.createParagraphStyle('ListParagraph', 'List Paragraph')
.quickFormat()
.basedOn('Normal');
const numbering = new docx.Numbering();
const numberedAbstract = numbering.createAbstractNumbering();
numberedAbstract.createLevel(0, "lowerLetter", "%1)", "left");
const doc = new docx.Document({
creator: 'Clippy',
title: 'Sample Document',
description: 'A brief example of using docx',
});
doc.createParagraph('Test heading1, bold and italicized').heading1();
doc.createParagraph('Some simple content');
doc.createParagraph('Test heading2 with double red underline').heading2();
const letterNumbering = numbering.createConcreteNumbering(numberedAbstract);
const letterNumbering5 = numbering.createConcreteNumbering(numberedAbstract);
letterNumbering5.overrideLevel(0, 5);
doc.createParagraph('Option1').setNumbering(letterNumbering, 0);
doc.createParagraph('Option5 -- override 2 to 5').setNumbering(letterNumbering5, 0);
doc.createParagraph('Option3').setNumbering(letterNumbering, 0);
doc.createParagraph()
.createTextRun('Some monospaced content')
.font('Monospace');
doc.createParagraph('An aside, in light gray italics and indented').style('aside');
doc.createParagraph('This is normal, but well-spaced text').style('wellSpaced');
doc.createParagraph('This is normal');
const exporter = new docx.LocalPacker(doc, styles, undefined, numbering);
exporter.pack('test.docx');

View File

@ -1,6 +1,6 @@
{ {
"name": "docx", "name": "docx",
"version": "2.0.0", "version": "2.0.1",
"description": "Generate .docx documents with JavaScript (formerly Office-Clippy)", "description": "Generate .docx documents with JavaScript (formerly Office-Clippy)",
"main": "build/index.js", "main": "build/index.js",
"scripts": { "scripts": {
@ -9,7 +9,8 @@
"prepublishOnly": "npm run build", "prepublishOnly": "npm run build",
"lint": "tslint --project ./ts", "lint": "tslint --project ./ts",
"build": "rimraf ./build && tsc -p ts", "build": "rimraf ./build && tsc -p ts",
"demo": "npm run build && node ./demo/demo.js" "demo": "npm run build && node ./demo/demo.js",
"demo2": "npm run build && node ./demo/demo2.js"
}, },
"files": [ "files": [
"ts", "ts",

View File

@ -56,21 +56,29 @@ class LevelJc extends XmlComponent {
} }
} }
export class Level extends XmlComponent { class LevelBase extends XmlComponent {
private paragraphProperties: ParagraphProperties; private paragraphProperties: ParagraphProperties;
private runProperties: RunProperties; private runProperties: RunProperties;
constructor(level: number, numberFormat: string, levelText: string, lvlJc: string) { constructor(level: number, start?: number, numberFormat?: string, levelText?: string, lvlJc?: string) {
super("w:lvl"); super("w:lvl");
this.root.push(new LevelAttributes({ this.root.push(new LevelAttributes({
ilvl: level, ilvl: level,
tentative: 1, tentative: 1,
})); }));
this.root.push(new Start(1)); if (start !== undefined) {
this.root.push(new NumberFormat(numberFormat)); this.root.push(new Start(start));
this.root.push(new LevelText(levelText)); }
this.root.push(new LevelJc(lvlJc)); if (numberFormat !== undefined) {
this.root.push(new NumberFormat(numberFormat));
}
if (levelText !== undefined) {
this.root.push(new LevelText(levelText));
}
if (lvlJc !== undefined) {
this.root.push(new LevelJc(lvlJc));
}
this.paragraphProperties = new ParagraphProperties(); this.paragraphProperties = new ParagraphProperties();
this.runProperties = new RunProperties(); this.runProperties = new RunProperties();
@ -198,3 +206,13 @@ export class Level extends XmlComponent {
return this; return this;
}; };
} }
export class Level extends LevelBase {
// This is the level that sits under abstractNum. We make a
// handful of properties required
constructor(level: number, numberFormat: string, levelText: string, lvlJc: string) {
super(level, 1, numberFormat, levelText, lvlJc);
}
}
export class LevelForOverride extends LevelBase {}

View File

@ -1,4 +1,5 @@
import { Attributes, XmlAttributeComponent, XmlComponent } from "../docx/xml-components"; import { Attributes, XmlAttributeComponent, XmlComponent } from "../docx/xml-components";
import { LevelForOverride } from "./level";
class AbstractNumId extends XmlComponent { class AbstractNumId extends XmlComponent {
@ -29,4 +30,51 @@ export class Num extends XmlComponent {
this.root.push(new AbstractNumId(abstractNumId)); this.root.push(new AbstractNumId(abstractNumId));
this.id = numId; 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}));
}
} }

View File

@ -2,6 +2,7 @@ import { expect } from "chai";
import { Formatter } from "../export/formatter"; import { Formatter } from "../export/formatter";
import { Numbering } from "../numbering"; import { Numbering } from "../numbering";
import { AbstractNumbering } from "../numbering/abstract-numbering"; import { AbstractNumbering } from "../numbering/abstract-numbering";
import { LevelForOverride } from "../numbering/level";
import { Num } from "../numbering/num"; import { Num } from "../numbering/num";
describe("Numbering", () => { 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": []},
]},
],
});
});
});
});