From 60b7ce4785f62bc6d4daf91f88416faf6028476b Mon Sep 17 00:00:00 2001 From: Tom Hunkapiller Date: Wed, 26 May 2021 08:36:05 +0300 Subject: [PATCH] clean up settings; BREAKING: TableOfContents requires Document features.updateFields = true setting --- demo/28-table-of-contents.ts | 3 + demo/60-track-revisions.ts | 6 +- docs/usage/table-of-contents.md | 29 ++- src/export/packer/next-compiler.ts | 127 +++++++++++-- src/file/core-properties/properties.ts | 1 + src/file/file.spec.ts | 14 -- src/file/file.ts | 14 +- .../compatibility-setting.ts | 12 ++ src/file/settings/compatibility.ts | 83 ++++++++- .../settings/display-background-shape.spec.ts | 17 -- src/file/settings/display-background-shape.ts | 9 - src/file/settings/even-odd-headers.ts | 9 - src/file/settings/index.ts | 1 - src/file/settings/settings.spec.ts | 174 ++++-------------- src/file/settings/settings.ts | 157 +++++++++++++--- src/file/settings/track-revisions.spec.ts | 16 -- src/file/settings/track-revisions.ts | 7 - src/file/settings/update-fields.spec.ts | 39 ---- src/file/settings/update-fields.ts | 19 -- src/file/values.ts | 2 +- 20 files changed, 389 insertions(+), 350 deletions(-) delete mode 100644 src/file/settings/display-background-shape.spec.ts delete mode 100644 src/file/settings/display-background-shape.ts delete mode 100644 src/file/settings/even-odd-headers.ts delete mode 100644 src/file/settings/track-revisions.spec.ts delete mode 100644 src/file/settings/track-revisions.ts delete mode 100644 src/file/settings/update-fields.spec.ts delete mode 100644 src/file/settings/update-fields.ts diff --git a/demo/28-table-of-contents.ts b/demo/28-table-of-contents.ts index 472ade8f67..aa5abd3986 100644 --- a/demo/28-table-of-contents.ts +++ b/demo/28-table-of-contents.ts @@ -9,6 +9,9 @@ import { File, HeadingLevel, Packer, Paragraph, StyleLevel, TableOfContents } fr // Let's define the properties for generate a TOC for heading 1-5 and MySpectacularStyle, // making the entries be hyperlinks for the paragraph const doc = new File({ + features: { + updateFields: true, + }, styles: { paragraphStyles: [ { diff --git a/demo/60-track-revisions.ts b/demo/60-track-revisions.ts index 8b6f1883d5..11c7aee524 100644 --- a/demo/60-track-revisions.ts +++ b/demo/60-track-revisions.ts @@ -20,10 +20,12 @@ import { - https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.insertedrun - https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.deletedrun - The method `addTrackRevisions()` adds an element `` to the `settings.xml` file. This specifies that the application shall track *new* revisions made to the existing document. + The setting `features: { trackRevisions: true }` adds an element `` to the `settings.xml` file. + This specifies that the application shall track *new* revisions made to the existing document. See also https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.trackrevisions - Note that this setting enables to track *new changes* after teh file is generated, so this example will still show inserted and deleted text runs when you remove it. + Note that this setting enables to track *new changes* after teh file is generated, so this example will still + show inserted and deleted text runs when you remove it. */ const paragraph = new Paragraph({ diff --git a/docs/usage/table-of-contents.md b/docs/usage/table-of-contents.md index db2a6b321f..4a88508bc8 100644 --- a/docs/usage/table-of-contents.md +++ b/docs/usage/table-of-contents.md @@ -12,14 +12,29 @@ The complete documentation can be found [here](https://www.ecma-international.or All you need to do is create a `TableOfContents` object and assign it to the document. -```ts -const toc = new TableOfContents("Summary", { - hyperlink: true, - headingStyleRange: "1-5", - stylesWithLevels: [new StyleLevel("MySpectacularStyle", 1)], -}); +**Note**: updateFields feature must be enabled for TableOfContents to update correctly. -doc.addTableOfContents(toc); +```ts +const doc = new Document({ + features: { + updateFields: true, + }, + sections: [ + { + children: [ + new TableOfContents("Summary", { + hyperlink: true, + headingStyleRange: "1-5", + }), + new Paragraph({ + text: "Header #1", + heading: HeadingLevel.HEADING_1, + pageBreakBefore: true, + }), + ] + } + ] +}); ``` ## Table of Contents Options diff --git a/src/export/packer/next-compiler.ts b/src/export/packer/next-compiler.ts index 3d99f93c64..3311301a61 100644 --- a/src/export/packer/next-compiler.ts +++ b/src/export/packer/next-compiler.ts @@ -70,7 +70,6 @@ export class Compiler { } private xmlifyFile(file: File, prettify?: boolean): IXmlifyedFileMapping { - file.verifyUpdateFields(); const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1; const documentXmlData = xml( @@ -78,7 +77,13 @@ export class Compiler { viewWrapper: file.Document, file, }), - prettify, + { + indent: prettify, + declaration: { + standalone: "yes", + encoding: "UTF-8", + }, + }, ); const documentMediaDatas = this.imageReplacer.getMediaData(documentXmlData, file.Media); @@ -98,7 +103,12 @@ export class Compiler { viewWrapper: file.Document, file, }), - prettify, + { + indent: prettify, + declaration: { + encoding: "UTF-8", + }, + }, ); })(), path: "word/_rels/document.xml.rels", @@ -118,7 +128,13 @@ export class Compiler { viewWrapper: file.Document, file, }), - prettify, + { + indent: prettify, + declaration: { + standalone: "yes", + encoding: "UTF-8", + }, + }, ), path: "word/styles.xml", }, @@ -129,6 +145,7 @@ export class Compiler { file, }), { + indent: prettify, declaration: { standalone: "yes", encoding: "UTF-8", @@ -143,7 +160,13 @@ export class Compiler { viewWrapper: file.Document, file, }), - prettify, + { + indent: prettify, + declaration: { + standalone: "yes", + encoding: "UTF-8", + }, + }, ), path: "word/numbering.xml", }, @@ -153,7 +176,12 @@ export class Compiler { viewWrapper: file.Document, file, }), - prettify, + { + indent: prettify, + declaration: { + encoding: "UTF-8", + }, + }, ), path: "_rels/.rels", }, @@ -163,7 +191,12 @@ export class Compiler { viewWrapper: headerWrapper, file, }), - prettify, + { + indent: prettify, + declaration: { + encoding: "UTF-8", + }, + }, ); const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media); @@ -181,7 +214,12 @@ export class Compiler { viewWrapper: headerWrapper, file, }), - prettify, + { + indent: prettify, + declaration: { + encoding: "UTF-8", + }, + }, ), path: `word/_rels/header${index + 1}.xml.rels`, }; @@ -192,7 +230,12 @@ export class Compiler { viewWrapper: footerWrapper, file, }), - prettify, + { + indent: prettify, + declaration: { + encoding: "UTF-8", + }, + }, ); const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media); @@ -210,7 +253,12 @@ export class Compiler { viewWrapper: footerWrapper, file, }), - prettify, + { + indent: prettify, + declaration: { + encoding: "UTF-8", + }, + }, ), path: `word/_rels/footer${index + 1}.xml.rels`, }; @@ -221,7 +269,12 @@ export class Compiler { viewWrapper: headerWrapper, file, }), - prettify, + { + indent: prettify, + declaration: { + encoding: "UTF-8", + }, + }, ); const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media); // TODO: 0 needs to be changed when headers get relationships of their own @@ -238,7 +291,12 @@ export class Compiler { viewWrapper: footerWrapper, file, }), - prettify, + { + indent: prettify, + declaration: { + encoding: "UTF-8", + }, + }, ); const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media); // TODO: 0 needs to be changed when headers get relationships of their own @@ -255,7 +313,12 @@ export class Compiler { viewWrapper: file.Document, file, }), - prettify, + { + indent: prettify, + declaration: { + encoding: "UTF-8", + }, + }, ), path: "[Content_Types].xml", }, @@ -265,7 +328,13 @@ export class Compiler { viewWrapper: file.Document, file, }), - prettify, + { + indent: prettify, + declaration: { + standalone: "yes", + encoding: "UTF-8", + }, + }, ), path: "docProps/custom.xml", }, @@ -275,7 +344,13 @@ export class Compiler { viewWrapper: file.Document, file, }), - prettify, + { + indent: prettify, + declaration: { + standalone: "yes", + encoding: "UTF-8", + }, + }, ), path: "docProps/app.xml", }, @@ -285,7 +360,12 @@ export class Compiler { viewWrapper: file.FootNotes, file: file, }), - prettify, + { + indent: prettify, + declaration: { + encoding: "UTF-8", + }, + }, ), path: "word/footnotes.xml", }, @@ -295,7 +375,12 @@ export class Compiler { viewWrapper: file.FootNotes, file: file, }), - prettify, + { + indent: prettify, + declaration: { + encoding: "UTF-8", + }, + }, ), path: "word/_rels/footnotes.xml.rels", }, @@ -305,7 +390,13 @@ export class Compiler { viewWrapper: file.Document, file, }), - prettify, + { + indent: prettify, + declaration: { + standalone: "yes", + encoding: "UTF-8", + }, + }, ), path: "word/settings.xml", }, diff --git a/src/file/core-properties/properties.ts b/src/file/core-properties/properties.ts index 3128b08517..8a3012fe07 100644 --- a/src/file/core-properties/properties.ts +++ b/src/file/core-properties/properties.ts @@ -29,6 +29,7 @@ export interface IPropertiesOptions { readonly background?: IDocumentBackgroundOptions; readonly features?: { readonly trackRevisions?: boolean; + readonly updateFields?: boolean; }; readonly compatabilityModeVersion?: number; readonly customProperties?: ICustomPropertyOptions[]; diff --git a/src/file/file.spec.ts b/src/file/file.spec.ts index 81e2f461a2..321a03dc41 100644 --- a/src/file/file.spec.ts +++ b/src/file/file.spec.ts @@ -165,20 +165,6 @@ describe("File", () => { }); }); - describe("#addTrackRevisionsFeature", () => { - it("should call the underlying document's add", () => { - const file = new File({ - features: { - trackRevisions: true, - }, - sections: [], - }); - - // tslint:disable-next-line: no-unused-expression no-string-literal - expect(file.Settings["trackRevisions"]).to.exist; - }); - }); - describe("#createFootnote", () => { it("should create footnote", () => { const wrapper = new File({ diff --git a/src/file/file.ts b/src/file/file.ts index 38230bdeb1..0e6c9fc352 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -78,6 +78,8 @@ export class File { this.settings = new Settings({ compatabilityModeVersion: options.compatabilityModeVersion, evenAndOddHeaders: options.evenAndOddHeaderAndFooters ? true : false, + trackRevisions: options.features?.trackRevisions, + updateFields: options.features?.updateFields, }); this.media = fileProperties.template && fileProperties.template.media ? fileProperties.template.media : new Media(); @@ -132,18 +134,6 @@ export class File { this.footnotesWrapper.View.createFootNote(parseFloat(key), options.footnotes[key].children); } } - - if (options.features) { - if (options.features.trackRevisions) { - this.settings.addTrackRevisions(); - } - } - } - - public verifyUpdateFields(): void { - if (this.documentWrapper.View.getTablesOfContents().length) { - this.settings.addUpdateFields(); - } } private addSection({ headers = {}, footers = {}, children, properties }: ISectionOptions): void { diff --git a/src/file/settings/compatibility-setting/compatibility-setting.ts b/src/file/settings/compatibility-setting/compatibility-setting.ts index 9f2a0b4982..43a7c5d71a 100644 --- a/src/file/settings/compatibility-setting/compatibility-setting.ts +++ b/src/file/settings/compatibility-setting/compatibility-setting.ts @@ -1,5 +1,15 @@ import { XmlAttributeComponent, XmlComponent } from "file/xml-components"; +// Currently, this is hard-coded for Microsoft word compatSettings. +// Theoretically, we could add compatSettings for other programs, but +// currently there isn't a need. + +// +// +// +// +// + export class CompatibilitySettingAttributes extends XmlAttributeComponent<{ readonly version: number; readonly name: string; @@ -12,6 +22,8 @@ export class CompatibilitySettingAttributes extends XmlAttributeComponent<{ }; } +// https://docs.microsoft.com/en-us/openspecs/office_standards/ms-docx/90138c4d-eb18-4edc-aa6c-dfb799cb1d0d + export class CompatibilitySetting extends XmlComponent { constructor(version: number) { super("w:compatSetting"); diff --git a/src/file/settings/compatibility.ts b/src/file/settings/compatibility.ts index fe63da92c5..1405697bca 100644 --- a/src/file/settings/compatibility.ts +++ b/src/file/settings/compatibility.ts @@ -1,11 +1,77 @@ -import { XmlComponent } from "file/xml-components"; +import { OnOffElement, XmlComponent } from "file/xml-components"; import { CompatibilitySetting } from "./compatibility-setting/compatibility-setting"; -class DoNotExpandShiftReturn extends XmlComponent { - constructor() { - super("w:doNotExpandShiftReturn"); - } -} +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// export interface ICompatibilityOptions { readonly doNotExpandShiftReturn?: boolean; @@ -16,8 +82,9 @@ export class Compatibility extends XmlComponent { constructor(options: ICompatibilityOptions) { super("w:compat"); - if (options.doNotExpandShiftReturn) { - this.root.push(new DoNotExpandShiftReturn()); + // Don't justify lines ending in soft line break setting + if (options.doNotExpandShiftReturn !== undefined) { + this.root.push(new OnOffElement("w:doNotExpandShiftReturn", options.doNotExpandShiftReturn)); } if (options.version) { diff --git a/src/file/settings/display-background-shape.spec.ts b/src/file/settings/display-background-shape.spec.ts deleted file mode 100644 index 34c23b65db..0000000000 --- a/src/file/settings/display-background-shape.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { expect } from "chai"; - -import { Formatter } from "export/formatter"; - -import { DisplayBackgroundShape } from "./display-background-shape"; - -describe("DisplayBackgroundShape", () => { - describe("#constructor()", () => { - it("should create", () => { - const displayBackgroundShape = new DisplayBackgroundShape(); - const tree = new Formatter().format(displayBackgroundShape); - expect(tree).to.deep.equal({ - "w:displayBackgroundShape": {}, - }); - }); - }); -}); diff --git a/src/file/settings/display-background-shape.ts b/src/file/settings/display-background-shape.ts deleted file mode 100644 index bd0cd15675..0000000000 --- a/src/file/settings/display-background-shape.ts +++ /dev/null @@ -1,9 +0,0 @@ -// http://officeopenxml.com/WPdocument.php -// http://www.datypic.com/sc/ooxml/e-w_background-1.html -import { XmlComponent } from "file/xml-components"; - -export class DisplayBackgroundShape extends XmlComponent { - constructor() { - super("w:displayBackgroundShape"); - } -} diff --git a/src/file/settings/even-odd-headers.ts b/src/file/settings/even-odd-headers.ts deleted file mode 100644 index c6f85a7aca..0000000000 --- a/src/file/settings/even-odd-headers.ts +++ /dev/null @@ -1,9 +0,0 @@ -// http://officeopenxml.com/WPSectionFooterReference.php -// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_evenAndOddHeaders_topic_ID0ET1WU.html -import { XmlComponent } from "file/xml-components"; - -export class EvenAndOddHeadersAndFooters extends XmlComponent { - constructor() { - super("w:evenAndOddHeaders"); - } -} diff --git a/src/file/settings/index.ts b/src/file/settings/index.ts index d750485a16..dcf101b0c6 100644 --- a/src/file/settings/index.ts +++ b/src/file/settings/index.ts @@ -1,2 +1 @@ export * from "./settings"; -export * from "./update-fields"; diff --git a/src/file/settings/settings.spec.ts b/src/file/settings/settings.spec.ts index 03a3612a0b..b12f340f43 100644 --- a/src/file/settings/settings.spec.ts +++ b/src/file/settings/settings.spec.ts @@ -7,83 +7,37 @@ import { Settings } from "./settings"; describe("Settings", () => { describe("#constructor", () => { it("should create a empty Settings with correct rootKey", () => { - const settings = new Settings({ - evenAndOddHeaders: false, - }); + 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"); - keys = Object.keys(tree["w:settings"]); - expect(keys).is.an.instanceof(Array); - expect(keys).has.length(3); + + expect(Object.keys(tree)).has.length(1); + expect(tree["w:settings"]).to.be.an("array"); }); - }); - 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(4); - 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[3]); - expect(keys).is.an.instanceof(Array); - expect(keys).has.length(1); - expect(keys[0]).to.be.equal("w:updateFields"); - const updateFields = rootArray[3]["w:updateFields"]; - keys = Object.keys(updateFields); - expect(keys).is.an.instanceof(Array); - expect(keys).has.length(1); - expect(keys[0]).to.be.equal("_attr"); - const updateFieldsAttr = updateFields._attr; - expect(updateFieldsAttr["w:val"]).to.be.equal(true); - }; - it("should add a UpdateFields with value true", () => { + + it("should add updateFields setting", () => { const settings = new Settings({ - evenAndOddHeaders: false, - }); - settings.addUpdateFields(); - assertSettingsWithUpdateFields(settings); - }); - it("should add a UpdateFields with value true only once", () => { - const settings = new Settings({ - evenAndOddHeaders: false, - }); - settings.addUpdateFields(); - assertSettingsWithUpdateFields(settings); - settings.addUpdateFields(); - assertSettingsWithUpdateFields(settings); - }); - }); - describe("#addCompatibility", () => { - it("should add an empty Compatibility by default", () => { - const settings = new Settings({ - evenAndOddHeaders: false, + updateFields: true, }); const tree = new Formatter().format(settings); - let keys: string[] = Object.keys(tree); - expect(keys[0]).to.be.equal("w:settings"); - const rootArray = tree["w:settings"]; - expect(rootArray).is.an.instanceof(Array); - expect(rootArray).has.length(3); - 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:compat"); - expect(rootArray[1]["w:compat"][0]).to.deep.equal({ + expect(Object.keys(tree)).has.length(1); + expect(tree["w:settings"]).to.be.an("array"); + + expect(tree["w:settings"]).to.deep.include({ + "w:updateFields": {}, + }); + }); + + it("should indicate modern word compatibility by default", () => { + const settings = new Settings({}); + + const tree = new Formatter().format(settings); + expect(Object.keys(tree)).has.length(1); + expect(tree["w:settings"]).to.be.an("array"); + + const compat = tree["w:settings"][2]; + expect(compat).to.be.an("object").with.keys("w:compat"); + expect(compat["w:compat"]).to.deep.include({ "w:compatSetting": { _attr: { "w:val": 15, @@ -93,81 +47,19 @@ describe("Settings", () => { }, }); }); - }); - describe("#addTrackRevisions", () => { - it("should add an empty Track Revisions", () => { + + it("should add trackRevisions setting", () => { const settings = new Settings({ - evenAndOddHeaders: false, + trackRevisions: true, }); - settings.addTrackRevisions(); const tree = new Formatter().format(settings); - let keys: string[] = Object.keys(tree); - expect(keys[0]).to.be.equal("w:settings"); - const rootArray = tree["w:settings"]; - expect(rootArray).is.an.instanceof(Array); - expect(rootArray).has.length(4); - 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[3]); - expect(keys).is.an.instanceof(Array); - expect(keys).has.length(1); - expect(keys[0]).to.be.equal("w:trackRevisions"); - }); - }); - describe("#addTrackRevisionsTwice", () => { - it("should add an empty Track Revisions if called twice", () => { - const settings = new Settings({ - evenAndOddHeaders: false, + expect(Object.keys(tree)).has.length(1); + expect(tree["w:settings"]).to.be.an("array"); + + expect(tree["w:settings"]).to.deep.include({ + "w:trackRevisions": {}, }); - settings.addTrackRevisions(); - settings.addTrackRevisions(); - - const tree = new Formatter().format(settings); - let keys: string[] = Object.keys(tree); - expect(keys[0]).to.be.equal("w:settings"); - const rootArray = tree["w:settings"]; - expect(rootArray).is.an.instanceof(Array); - expect(rootArray).has.length(4); - 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[3]); - expect(keys).is.an.instanceof(Array); - expect(keys).has.length(1); - expect(keys[0]).to.be.equal("w:trackRevisions"); - }); - }); - - describe("#addTrackRevisionsTwice", () => { - it("should add an empty Track Revisions if called twice", () => { - const settings = new Settings({ - evenAndOddHeaders: true, - }); - settings.addTrackRevisions(); - settings.addTrackRevisions(); - - const tree = new Formatter().format(settings); - let keys: string[] = Object.keys(tree); - expect(keys[0]).to.be.equal("w:settings"); - const rootArray = tree["w:settings"]; - expect(rootArray).is.an.instanceof(Array); - expect(rootArray).has.length(5); - 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[4]); - expect(keys).is.an.instanceof(Array); - expect(keys).has.length(1); - expect(keys[0]).to.be.equal("w:trackRevisions"); - keys = Object.keys(rootArray[2]); - expect(keys).is.an.instanceof(Array); - expect(keys).has.length(1); - expect(keys[0]).to.be.equal("w:evenAndOddHeaders"); }); }); }); diff --git a/src/file/settings/settings.ts b/src/file/settings/settings.ts index 30b26d8f04..4c57532a41 100644 --- a/src/file/settings/settings.ts +++ b/src/file/settings/settings.ts @@ -1,10 +1,6 @@ -import { XmlAttributeComponent, XmlComponent } from "file/xml-components"; +import { OnOffElement, XmlAttributeComponent, XmlComponent } from "file/xml-components"; import { Compatibility } from "./compatibility"; -import { DisplayBackgroundShape } from "./display-background-shape"; -import { EvenAndOddHeadersAndFooters } from "./even-odd-headers"; -import { TrackRevisions } from "./track-revisions"; -import { UpdateFields } from "./update-fields"; export class SettingsAttributes extends XmlAttributeComponent<{ readonly wpc?: string; @@ -46,14 +42,118 @@ export class SettingsAttributes extends XmlAttributeComponent<{ }; } +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// + export interface ISettingsOptions { readonly compatabilityModeVersion?: number; - readonly evenAndOddHeaders: boolean; + readonly evenAndOddHeaders?: boolean; + readonly trackRevisions?: boolean; + readonly updateFields?: boolean; } export class Settings extends XmlComponent { - private readonly trackRevisions: TrackRevisions; - constructor(options: ISettingsOptions) { super("w:settings"); this.root.push( @@ -78,32 +178,29 @@ export class Settings extends XmlComponent { }), ); + // http://officeopenxml.com/WPdocument.php + // https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_displayBackgroundSha_topic_ID0ET4SX.html + this.root.push(new OnOffElement("w:displayBackgroundShape", true)); + + // https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_trackRevisions_topic_ID0EKXKY.html + if (options.trackRevisions !== undefined) { + this.root.push(new OnOffElement("w:trackRevisions", options.trackRevisions)); + } + + // http://officeopenxml.com/WPSectionFooterReference.php + // https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_evenAndOddHeaders_topic_ID0ET1WU.html + if (options.evenAndOddHeaders !== undefined) { + this.root.push(new OnOffElement("w:evenAndOddHeaders", options.evenAndOddHeaders)); + } + + if (options.updateFields !== undefined) { + this.root.push(new OnOffElement("w:updateFields", options.updateFields)); + } + this.root.push( new Compatibility({ version: options.compatabilityModeVersion || 15, }), ); - - if (options.evenAndOddHeaders) { - this.root.push(new EvenAndOddHeadersAndFooters()); - } - - this.trackRevisions = new TrackRevisions(); - - this.root.push(new DisplayBackgroundShape()); - } - - public addUpdateFields(): void { - if (!this.root.find((child) => child instanceof UpdateFields)) { - this.addChildElement(new UpdateFields()); - } - } - - public addTrackRevisions(): TrackRevisions { - if (!this.root.find((child) => child instanceof TrackRevisions)) { - this.addChildElement(this.trackRevisions); - } - - return this.trackRevisions; } } diff --git a/src/file/settings/track-revisions.spec.ts b/src/file/settings/track-revisions.spec.ts deleted file mode 100644 index 3875d51f0a..0000000000 --- a/src/file/settings/track-revisions.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { expect } from "chai"; -import { Formatter } from "export/formatter"; -import { TrackRevisions } from "file/settings/track-revisions"; - -import { EMPTY_OBJECT } from "file/xml-components"; - -describe("TrackRevisions", () => { - describe("#constructor", () => { - it("creates an initially empty property object", () => { - const trackRevisions = new TrackRevisions(); - - const tree = new Formatter().format(trackRevisions); - expect(tree).to.deep.equal({ "w:trackRevisions": EMPTY_OBJECT }); - }); - }); -}); diff --git a/src/file/settings/track-revisions.ts b/src/file/settings/track-revisions.ts deleted file mode 100644 index 2da692827e..0000000000 --- a/src/file/settings/track-revisions.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { XmlComponent } from "file/xml-components"; - -export class TrackRevisions extends XmlComponent { - constructor() { - super("w:trackRevisions"); - } -} diff --git a/src/file/settings/update-fields.spec.ts b/src/file/settings/update-fields.spec.ts deleted file mode 100644 index 2ccc9df8c4..0000000000 --- a/src/file/settings/update-fields.spec.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { expect } from "chai"; - -import { Formatter } from "export/formatter"; - -import { UpdateFields } from "./update-fields"; - -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); - }); - }); -}); diff --git a/src/file/settings/update-fields.ts b/src/file/settings/update-fields.ts deleted file mode 100644 index 47a2ec6e18..0000000000 --- a/src/file/settings/update-fields.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { XmlAttributeComponent, XmlComponent } from "file/xml-components"; - -export class UpdateFieldsAttributes extends XmlAttributeComponent<{ - readonly enabled: boolean; -}> { - protected readonly xmlKeys = { - enabled: "w:val", - }; -} -export class UpdateFields extends XmlComponent { - constructor(enabled: boolean = true) { - super("w:updateFields"); - this.root.push( - new UpdateFieldsAttributes({ - enabled, - }), - ); - } -} diff --git a/src/file/values.ts b/src/file/values.ts index 6fb33e24c2..8634d47de4 100644 --- a/src/file/values.ts +++ b/src/file/values.ts @@ -186,7 +186,7 @@ export function measurementOrPercentValue(val: number | string): number | string if (typeof val === "number") { return decimalNumber(val); } - if (val.slice(-1) === '%') { + if (val.slice(-1) === "%") { return percentageValue(val); } return universalMeasureValue(val);