Moved addTableOfContents to File and creating a settings.xml and applying updateFields=true when there is a table of contents
This commit is contained in:
@ -1,25 +1,25 @@
|
||||
// Creates two paragraphs, one with a border and one without
|
||||
// Import from 'docx' rather than '../build' if you install from npm
|
||||
import * as fs from "fs";
|
||||
import { Document, Packer, Paragraph, TableOfContents } from "../build";
|
||||
import { File, Packer, Paragraph, TableOfContents } from "../build";
|
||||
|
||||
const doc = new Document();
|
||||
const doc = new File();
|
||||
|
||||
// WordprocessingML docs for TableOfContents can be found here:
|
||||
// http://officeopenxml.com/WPtableOfContents.php
|
||||
// Creates an table of contents with default properties
|
||||
const toc = new TableOfContents();
|
||||
|
||||
// The class TableOfContents extends Paragraph and can be added as such.
|
||||
doc.addParagraph(toc)
|
||||
// A TableOfContents must be added via File class.
|
||||
doc.addTableOfContents(toc)
|
||||
|
||||
doc.addParagraph(new Paragraph("Header #1").heading1().pageBreakBefore());
|
||||
doc.addParagraph(new Paragraph("I'm a little text very nicely written.'"));
|
||||
|
||||
doc.addParagraph(new Paragraph("Header #2").heading1().pageBreakBefore());
|
||||
doc.addParagraph(new Paragraph("I'm a little text very nicely written.'"));
|
||||
doc.addParagraph(new Paragraph("I'm a other text very nicely written.'"));
|
||||
doc.addParagraph(new Paragraph("Header #2.1").heading2());
|
||||
doc.addParagraph(new Paragraph("I'm a little text very nicely written.'"));
|
||||
doc.addParagraph(new Paragraph("I'm a another text very nicely written.'"));
|
||||
|
||||
const packer = new Packer();
|
||||
|
||||
|
@ -19,7 +19,7 @@ describe("Compiler", () => {
|
||||
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
|
||||
|
||||
expect(fileNames).is.an.instanceof(Array);
|
||||
expect(fileNames).has.length(17);
|
||||
expect(fileNames).has.length(18);
|
||||
expect(fileNames).to.include("word/document.xml");
|
||||
expect(fileNames).to.include("word/styles.xml");
|
||||
expect(fileNames).to.include("docProps/core.xml");
|
||||
@ -31,6 +31,7 @@ describe("Compiler", () => {
|
||||
expect(fileNames).to.include("word/footnotes.xml");
|
||||
expect(fileNames).to.include("word/_rels/footer1.xml.rels");
|
||||
expect(fileNames).to.include("word/_rels/document.xml.rels");
|
||||
expect(fileNames).to.include("word/settings.xml");
|
||||
expect(fileNames).to.include("[Content_Types].xml");
|
||||
expect(fileNames).to.include("_rels/.rels");
|
||||
});
|
||||
@ -47,7 +48,7 @@ describe("Compiler", () => {
|
||||
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
|
||||
|
||||
expect(fileNames).is.an.instanceof(Array);
|
||||
expect(fileNames).has.length(25);
|
||||
expect(fileNames).has.length(26);
|
||||
|
||||
expect(fileNames).to.include("word/header1.xml");
|
||||
expect(fileNames).to.include("word/_rels/header1.xml.rels");
|
||||
|
@ -23,6 +23,7 @@ interface IXmlifyedFileMapping {
|
||||
ContentTypes: IXmlifyedFile;
|
||||
AppProperties: IXmlifyedFile;
|
||||
FootNotes: IXmlifyedFile;
|
||||
Settings: IXmlifyedFile;
|
||||
}
|
||||
|
||||
export class Compiler {
|
||||
@ -120,6 +121,10 @@ export class Compiler {
|
||||
data: xml(this.formatter.format(file.FootNotes)),
|
||||
path: "word/footnotes.xml",
|
||||
},
|
||||
Settings: {
|
||||
data: xml(this.formatter.format(file.Settings)),
|
||||
path: "word/settings.xml",
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { Paragraph } from "../paragraph";
|
||||
import { Table } from "../table";
|
||||
import { TableOfContents } from "../table-of-contents";
|
||||
import { Body } from "./body";
|
||||
import { SectionPropertiesOptions } from "./body/section-properties";
|
||||
import { DocumentAttributes } from "./document-attributes";
|
||||
@ -41,6 +42,11 @@ export class Document extends XmlComponent {
|
||||
return this;
|
||||
}
|
||||
|
||||
public addTableOfContents(toc: TableOfContents): Document {
|
||||
this.body.push(toc);
|
||||
return this;
|
||||
}
|
||||
|
||||
public createParagraph(text?: string): Paragraph {
|
||||
const para = new Paragraph(text);
|
||||
this.addParagraph(para);
|
||||
|
@ -10,10 +10,12 @@ import { Image, Media } from "./media";
|
||||
import { Numbering } from "./numbering";
|
||||
import { Bookmark, Hyperlink, Paragraph } from "./paragraph";
|
||||
import { Relationships } from "./relationships";
|
||||
import { Settings } from "./settings";
|
||||
import { Styles } from "./styles";
|
||||
import { ExternalStylesFactory } from "./styles/external-styles-factory";
|
||||
import { DefaultStylesFactory } from "./styles/factory";
|
||||
import { Table } from "./table";
|
||||
import { TableOfContents } from "./table-of-contents";
|
||||
|
||||
export class File {
|
||||
private readonly document: Document;
|
||||
@ -26,6 +28,7 @@ export class File {
|
||||
private readonly headerWrapper: HeaderWrapper[] = [];
|
||||
private readonly footerWrapper: FooterWrapper[] = [];
|
||||
private readonly footNotes: FootNotes;
|
||||
private readonly settings: Settings;
|
||||
|
||||
private readonly contentTypes: ContentTypes;
|
||||
private readonly appProperties: AppProperties;
|
||||
@ -105,6 +108,12 @@ export class File {
|
||||
sectionPropertiesOptions.footerId = footer.Footer.ReferenceId;
|
||||
}
|
||||
this.document = new Document(sectionPropertiesOptions);
|
||||
this.settings = new Settings();
|
||||
}
|
||||
|
||||
public addTableOfContents(toc: TableOfContents): void {
|
||||
this.document.addTableOfContents(toc);
|
||||
this.settings.addUpdateFields();
|
||||
}
|
||||
|
||||
public addParagraph(paragraph: Paragraph): void {
|
||||
@ -277,4 +286,8 @@ export class File {
|
||||
public get FootNotes(): FootNotes {
|
||||
return this.footNotes;
|
||||
}
|
||||
|
||||
public get Settings(): Settings {
|
||||
return this.settings;
|
||||
}
|
||||
}
|
||||
|
2
src/file/settings/index.ts
Normal file
2
src/file/settings/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from "./settings";
|
||||
export * from "./update-fields";
|
78
src/file/settings/settings.spec.ts
Normal file
78
src/file/settings/settings.spec.ts
Normal file
@ -0,0 +1,78 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "../../export/formatter";
|
||||
import { Settings } from "./";
|
||||
|
||||
describe("Settings", () => {
|
||||
describe("#constructor", () => {
|
||||
it("should create a empty Settings with correct rootKey", () => {
|
||||
const settings = new Settings();
|
||||
const tree = new Formatter().format(settings);
|
||||
let keys = Object.keys(tree);
|
||||
|
||||
expect(keys).is.an.instanceof(Array);
|
||||
expect(keys).has.length(1);
|
||||
expect(keys[0]).to.be.equal("w:settings");
|
||||
|
||||
expect(tree["w:settings"]).is.an.instanceof(Array);
|
||||
expect(tree["w:settings"]).has.length(1);
|
||||
|
||||
keys = Object.keys(tree["w:settings"][0]);
|
||||
expect(keys).is.an.instanceof(Array);
|
||||
expect(keys).has.length(1);
|
||||
expect(keys[0]).to.be.equal("_attr");
|
||||
});
|
||||
});
|
||||
|
||||
describe("#addUpdateFields", () => {
|
||||
const assertSettingsWithUpdateFields = (settings: Settings) => {
|
||||
const tree = new Formatter().format(settings);
|
||||
let keys = Object.keys(tree);
|
||||
|
||||
expect(keys).is.an.instanceof(Array);
|
||||
expect(keys).has.length(1);
|
||||
expect(keys[0]).to.be.equal("w:settings");
|
||||
|
||||
const rootArray = tree["w:settings"];
|
||||
expect(rootArray).is.an.instanceof(Array);
|
||||
expect(rootArray).has.length(2);
|
||||
|
||||
keys = Object.keys(rootArray[0]);
|
||||
expect(keys).is.an.instanceof(Array);
|
||||
expect(keys).has.length(1);
|
||||
expect(keys[0]).to.be.equal("_attr");
|
||||
|
||||
keys = Object.keys(rootArray[1]);
|
||||
expect(keys).is.an.instanceof(Array);
|
||||
expect(keys).has.length(1);
|
||||
expect(keys[0]).to.be.equal("w:updateFields");
|
||||
|
||||
const updateFieldsArray = rootArray[1]["w:updateFields"];
|
||||
keys = Object.keys(updateFieldsArray[0]);
|
||||
expect(keys).is.an.instanceof(Array);
|
||||
expect(keys).has.length(1);
|
||||
expect(keys[0]).to.be.equal("_attr");
|
||||
|
||||
const updateFieldsAttr = updateFieldsArray[0]._attr;
|
||||
expect(updateFieldsAttr["w:val"]).to.be.equal(true);
|
||||
};
|
||||
|
||||
it("should add a UpdateFields with value true", () => {
|
||||
const settings = new Settings();
|
||||
settings.addUpdateFields();
|
||||
|
||||
assertSettingsWithUpdateFields(settings);
|
||||
});
|
||||
|
||||
it("should add a UpdateFields with value true only once", () => {
|
||||
const settings = new Settings();
|
||||
settings.addUpdateFields();
|
||||
|
||||
assertSettingsWithUpdateFields(settings);
|
||||
|
||||
settings.addUpdateFields();
|
||||
|
||||
assertSettingsWithUpdateFields(settings);
|
||||
});
|
||||
});
|
||||
});
|
77
src/file/settings/settings.ts
Normal file
77
src/file/settings/settings.ts
Normal file
@ -0,0 +1,77 @@
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
import { UpdateFields } from "./update-fields";
|
||||
|
||||
export interface ISettingsAttributesProperties {
|
||||
wpc?: string;
|
||||
mc?: string;
|
||||
o?: string;
|
||||
r?: string;
|
||||
m?: string;
|
||||
v?: string;
|
||||
wp14?: string;
|
||||
wp?: string;
|
||||
w10?: string;
|
||||
w?: string;
|
||||
w14?: string;
|
||||
w15?: string;
|
||||
wpg?: string;
|
||||
wpi?: string;
|
||||
wne?: string;
|
||||
wps?: string;
|
||||
Ignorable?: string;
|
||||
}
|
||||
|
||||
export class SettingsAttributes extends XmlAttributeComponent<ISettingsAttributesProperties> {
|
||||
protected xmlKeys = {
|
||||
wpc: "xmlns:wpc",
|
||||
mc: "xmlns:mc",
|
||||
o: "xmlns:o",
|
||||
r: "xmlns:r",
|
||||
m: "xmlns:m",
|
||||
v: "xmlns:v",
|
||||
wp14: "xmlns:wp14",
|
||||
wp: "xmlns:wp",
|
||||
w10: "xmlns:w10",
|
||||
w: "xmlns:w",
|
||||
w14: "xmlns:w14",
|
||||
w15: "xmlns:w15",
|
||||
wpg: "xmlns:wpg",
|
||||
wpi: "xmlns:wpi",
|
||||
wne: "xmlns:wne",
|
||||
wps: "xmlns:wps",
|
||||
Ignorable: "mc:Ignorable",
|
||||
};
|
||||
}
|
||||
|
||||
export class Settings extends XmlComponent {
|
||||
constructor() {
|
||||
super("w:settings");
|
||||
this.root.push(
|
||||
new SettingsAttributes({
|
||||
wpc: "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas",
|
||||
mc: "http://schemas.openxmlformats.org/markup-compatibility/2006",
|
||||
o: "urn:schemas-microsoft-com:office:office",
|
||||
r: "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
|
||||
m: "http://schemas.openxmlformats.org/officeDocument/2006/math",
|
||||
v: "urn:schemas-microsoft-com:vml",
|
||||
wp14: "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing",
|
||||
wp: "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing",
|
||||
w10: "urn:schemas-microsoft-com:office:word",
|
||||
w: "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
|
||||
w14: "http://schemas.microsoft.com/office/word/2010/wordml",
|
||||
w15: "http://schemas.microsoft.com/office/word/2012/wordml",
|
||||
wpg: "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup",
|
||||
wpi: "http://schemas.microsoft.com/office/word/2010/wordprocessingInk",
|
||||
wne: "http://schemas.microsoft.com/office/word/2006/wordml",
|
||||
wps: "http://schemas.microsoft.com/office/word/2010/wordprocessingShape",
|
||||
Ignorable: "w14 w15 wp14",
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
public addUpdateFields(): void {
|
||||
if (!this.root.find((child) => child instanceof UpdateFields)) {
|
||||
this.addChildElement(new UpdateFields());
|
||||
}
|
||||
}
|
||||
}
|
46
src/file/settings/update-fields.spec.ts
Normal file
46
src/file/settings/update-fields.spec.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "../../export/formatter";
|
||||
import { UpdateFields } from "./";
|
||||
|
||||
const UF_TRUE = {
|
||||
"w:updateFields": [
|
||||
{
|
||||
_attr: {
|
||||
"w:val": true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const UF_FALSE = {
|
||||
"w:updateFields": [
|
||||
{
|
||||
_attr: {
|
||||
"w:val": false,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
describe("Update Fields", () => {
|
||||
describe("#constructor", () => {
|
||||
it("should construct a Update Fields with TRUE value by default", () => {
|
||||
const uf = new UpdateFields();
|
||||
const tree = new Formatter().format(uf);
|
||||
expect(tree).to.be.deep.equal(UF_TRUE);
|
||||
});
|
||||
|
||||
it("should construct a Update Fields with TRUE value", () => {
|
||||
const uf = new UpdateFields(true);
|
||||
const tree = new Formatter().format(uf);
|
||||
expect(tree).to.be.deep.equal(UF_TRUE);
|
||||
});
|
||||
|
||||
it("should construct a Update Fields with FALSE value", () => {
|
||||
const uf = new UpdateFields(false);
|
||||
const tree = new Formatter().format(uf);
|
||||
expect(tree).to.be.deep.equal(UF_FALSE);
|
||||
});
|
||||
});
|
||||
});
|
22
src/file/settings/update-fields.ts
Normal file
22
src/file/settings/update-fields.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
export interface IUpdateFieldsAttributesProperties {
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export class UpdateFieldsAttributes extends XmlAttributeComponent<IUpdateFieldsAttributesProperties> {
|
||||
protected xmlKeys = {
|
||||
enabled: "w:val",
|
||||
};
|
||||
}
|
||||
|
||||
export class UpdateFields extends XmlComponent {
|
||||
constructor(enabled: boolean = true) {
|
||||
super("w:updateFields");
|
||||
this.root.push(
|
||||
new UpdateFieldsAttributes({
|
||||
enabled,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -19,9 +19,9 @@ export class TableOfContentsInstructionProperties {
|
||||
// \h option
|
||||
public hiperlink: true;
|
||||
// \n option
|
||||
public entryLevelsRange = "1-6";
|
||||
public entryLevelsRange: string;
|
||||
// \o option
|
||||
public headerRange: string;
|
||||
public headerRange = "1-6";
|
||||
// \t option
|
||||
public styles: StyleLevel[];
|
||||
// \z option
|
||||
|
@ -29,7 +29,7 @@ const DEFAULT_TOC = {
|
||||
"xml:space": "preserve",
|
||||
},
|
||||
},
|
||||
'TOC \\n "1-6"',
|
||||
'TOC \\o "1-6"',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -1,14 +1,18 @@
|
||||
// import { TableOfContentsProperties } from "./properties";
|
||||
import { Paragraph } from "file/paragraph";
|
||||
import { ParagraphProperties } from "file/paragraph";
|
||||
import { Run } from "file/paragraph/run";
|
||||
import { Begin, End, Separate } from "file/paragraph/run/field";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { TableOfContentsInstruction } from "./instruction";
|
||||
|
||||
export class TableOfContents extends Paragraph {
|
||||
export class TableOfContents extends XmlComponent {
|
||||
// private readonly tocProperties: TableOfContentsProperties;
|
||||
private readonly properties: ParagraphProperties;
|
||||
|
||||
constructor(/*tocProperties?: TableOfContentsProperties*/) {
|
||||
super();
|
||||
super("w:p");
|
||||
this.properties = new ParagraphProperties();
|
||||
this.root.push(this.properties);
|
||||
// this.tocProperties = tocProperties || new TableOfContentsProperties();
|
||||
const firstRun = new Run();
|
||||
firstRun.addChildElement(new Begin());
|
||||
|
Reference in New Issue
Block a user