diff --git a/.nycrc b/.nycrc index 872d9c30a8..24dc1f5d43 100644 --- a/.nycrc +++ b/.nycrc @@ -1,9 +1,9 @@ { "check-coverage": true, - "statements": 99.72, - "branches": 98.08, + "statements": 99.73, + "branches": 98.32, "functions": 99.83, - "lines": 99.72, + "lines": 99.73, "include": [ "src/**/*.ts" ], diff --git a/demo/10-my-cv.ts b/demo/10-my-cv.ts index ef766d6656..ad36f4ef08 100644 --- a/demo/10-my-cv.ts +++ b/demo/10-my-cv.ts @@ -1,7 +1,7 @@ // Generate a CV // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { AlignmentType, Document, HeadingLevel, Packer, Paragraph, TabStopPosition, TabStopType, TextRun } from "../build"; +import { AlignmentType, Document, HeadingLevel, Packer, Paragraph, Tab, TabStopPosition, TabStopType, TextRun } from "../build"; // tslint:disable:no-shadowed-variable @@ -284,7 +284,7 @@ class DocumentCreator { bold: true, }), new TextRun({ - text: `\t${dateText}`, + children: [new Tab(), dateText], bold: true, }), ], diff --git a/demo/19-export-to-base64.ts b/demo/19-export-to-base64.ts index f9e871353e..3d54e9ee38 100644 --- a/demo/19-export-to-base64.ts +++ b/demo/19-export-to-base64.ts @@ -1,7 +1,7 @@ // Export to base64 string - Useful in a browser environment. // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph, TextRun } from "../build"; +import { Document, Packer, Paragraph, Tab, TextRun } from "../build"; const doc = new Document({ sections: [ @@ -15,7 +15,7 @@ const doc = new Document({ bold: true, }), new TextRun({ - text: "\tBar", + children: [new Tab(), "Bar"], bold: true, }), ], diff --git a/demo/48-vertical-align.ts b/demo/48-vertical-align.ts index 36400de154..6e9aba0438 100644 --- a/demo/48-vertical-align.ts +++ b/demo/48-vertical-align.ts @@ -1,7 +1,7 @@ // Example of making content of section vertically aligned // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph, VerticalAlign, TextRun } from "../build"; +import { Document, Packer, Paragraph, VerticalAlign, TextRun, Tab } from "../build"; const doc = new Document({ sections: [ @@ -18,7 +18,7 @@ const doc = new Document({ bold: true, }), new TextRun({ - text: "\tGithub is the best", + children: [new Tab(), "Github is the best"], bold: true, }), ], diff --git a/demo/56-background-color.ts b/demo/56-background-color.ts index 23eb077cfd..3f290f6170 100644 --- a/demo/56-background-color.ts +++ b/demo/56-background-color.ts @@ -1,7 +1,7 @@ // Change background colour of whole document // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph, TextRun } from "../build"; +import { Document, Packer, Paragraph, Tab, TextRun } from "../build"; const doc = new Document({ background: { @@ -19,7 +19,7 @@ const doc = new Document({ bold: true, }), new TextRun({ - text: "\tGithub is the best", + children: [new Tab(), "Github is the best"], bold: true, }), ], diff --git a/demo/6-page-borders.ts b/demo/6-page-borders.ts index 999c5011e5..79758e88e8 100644 --- a/demo/6-page-borders.ts +++ b/demo/6-page-borders.ts @@ -1,7 +1,7 @@ // Example of how to change page borders // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, HeadingLevel, Packer, Paragraph, TextRun } from "../build"; +import { Document, HeadingLevel, Packer, Paragraph, Tab, TextRun } from "../build"; const doc = new Document({ sections: [ @@ -25,7 +25,7 @@ const doc = new Document({ bold: true, }), new TextRun({ - text: "\tGithub is the best", + children: [new Tab(), "Github is the best"], bold: true, }), ], diff --git a/demo/60-track-revisions.ts b/demo/60-track-revisions.ts index e4cdd15575..d6b2e3a36c 100644 --- a/demo/60-track-revisions.ts +++ b/demo/60-track-revisions.ts @@ -12,6 +12,7 @@ import { PageNumber, Paragraph, ShadingType, + Tab, TextRun, } from "../build"; @@ -111,7 +112,7 @@ const doc = new Document({ }), new TextRun({ bold: true, - children: ["\tuse Inserted and Deleted TextRuns.", new FootnoteReferenceRun(1)], + children: [new Tab(), "use Inserted and Deleted TextRuns.", new FootnoteReferenceRun(1)], }), new TextRun({ bold: true, diff --git a/demo/61-text-frame.ts b/demo/61-text-frame.ts index d6563418cf..e36ac3e4ab 100644 --- a/demo/61-text-frame.ts +++ b/demo/61-text-frame.ts @@ -8,6 +8,7 @@ import { HorizontalPositionAlign, Packer, Paragraph, + Tab, TextRun, VerticalPositionAlign, } from "../build"; @@ -67,7 +68,7 @@ const doc = new Document({ bold: true, }), new TextRun({ - text: "\tGithub is the best", + children: [new Tab(), "Github is the best"], bold: true, }), ], diff --git a/demo/74-nodejs-stream.ts b/demo/74-nodejs-stream.ts index 0a73bd0508..fc4eae605b 100644 --- a/demo/74-nodejs-stream.ts +++ b/demo/74-nodejs-stream.ts @@ -1,7 +1,7 @@ // Exporting the document as a stream // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph, TextRun } from "../build"; +import { Document, Packer, Paragraph, Tab, TextRun } from "../build"; const doc = new Document({ sections: [ @@ -16,7 +16,7 @@ const doc = new Document({ bold: true, }), new TextRun({ - text: "\tGithub is the best", + children: [new Tab(), "Github is the best"], bold: true, }), ], diff --git a/demo/76-compatibility.ts b/demo/76-compatibility.ts new file mode 100644 index 0000000000..69916ba484 --- /dev/null +++ b/demo/76-compatibility.ts @@ -0,0 +1,87 @@ +// Add compatibility options +// Import from 'docx' rather than '../build' if you install from npm +import * as fs from "fs"; +import { Document, Packer, Paragraph, TextRun } from "../build"; + +const doc = new Document({ + compatibility: { + useSingleBorderforContiguousCells: true, + wordPerfectJustification: true, + noTabStopForHangingIndent: true, + noLeading: true, + spaceForUnderline: true, + noColumnBalance: true, + balanceSingleByteDoubleByteWidth: true, + noExtraLineSpacing: true, + doNotLeaveBackslashAlone: true, + underlineTrailingSpaces: true, + doNotExpandShiftReturn: true, + spacingInWholePoints: true, + lineWrapLikeWord6: true, + printBodyTextBeforeHeader: true, + printColorsBlack: true, + spaceWidth: true, + showBreaksInFrames: true, + subFontBySize: true, + suppressBottomSpacing: true, + suppressTopSpacing: true, + suppressSpacingAtTopOfPage: true, + suppressTopSpacingWP: true, + suppressSpBfAfterPgBrk: true, + swapBordersFacingPages: true, + convertMailMergeEsc: true, + truncateFontHeightsLikeWP6: true, + macWordSmallCaps: true, + usePrinterMetrics: true, + doNotSuppressParagraphBorders: true, + wrapTrailSpaces: true, + footnoteLayoutLikeWW8: true, + shapeLayoutLikeWW8: true, + alignTablesRowByRow: true, + forgetLastTabAlignment: true, + adjustLineHeightInTable: true, + autoSpaceLikeWord95: true, + noSpaceRaiseLower: true, + doNotUseHTMLParagraphAutoSpacing: true, + layoutRawTableWidth: true, + layoutTableRowsApart: true, + useWord97LineBreakRules: true, + doNotBreakWrappedTables: true, + doNotSnapToGridInCell: true, + selectFieldWithFirstOrLastCharacter: true, + applyBreakingRules: true, + doNotWrapTextWithPunctuation: true, + doNotUseEastAsianBreakRules: true, + useWord2002TableStyleRules: true, + growAutofit: true, + useFELayout: true, + useNormalStyleForList: true, + doNotUseIndentAsNumberingTabStop: true, + useAlternateEastAsianLineBreakRules: true, + allowSpaceOfSameStyleInTable: true, + doNotSuppressIndentation: true, + doNotAutofitConstrainedTables: true, + autofitToFirstFixedWidthCell: true, + underlineTabInNumberingList: true, + displayHangulFixedWidth: true, + splitPgBreakAndParaMark: true, + doNotVerticallyAlignCellWithSp: true, + doNotBreakConstrainedForcedTable: true, + ignoreVerticalAlignmentInTextboxes: true, + useAnsiKerningPairs: true, + cachedColumnBalance: true, + }, + sections: [ + { + children: [ + new Paragraph({ + children: [new TextRun("Hello World")], + }), + ], + }, + ], +}); + +Packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/browser-demo.html b/demo/browser-demo.html index cb3c2484ba..d73bdc0b84 100644 --- a/demo/browser-demo.html +++ b/demo/browser-demo.html @@ -24,7 +24,7 @@ bold: true, }), new docx.TextRun({ - text: "\tGithub is the best", + children: [new docx.Tab(), "Github is the best"], bold: true, }), ], diff --git a/docs/usage/document.md b/docs/usage/document.md index 0f1a12486a..818930e00e 100644 --- a/docs/usage/document.md +++ b/docs/usage/document.md @@ -22,20 +22,19 @@ const doc = new docx.Document({ ### Full list of options: - -* creator -* description -* title -* subject -* keywords -* lastModifiedBy -* revision -* externalStyles -* styles -* numbering -* footnotes -* hyperlinks -* background +- creator +- description +- title +- subject +- keywords +- lastModifiedBy +- revision +- externalStyles +- styles +- numbering +- footnotes +- hyperlinks +- background ### Change background color of Document @@ -55,3 +54,87 @@ You can mix and match whatever properties you want, or provide no properties. Various parts of the API require positioning arguments. The units are "20ths of a point" from the [OOXML](http://officeopenxml.com/index.php) specification. See [Lars Corneliussen's blog post](https://startbigthinksmall.wordpress.com/2010/01/04/points-inches-and-emus-measuring-units-in-office-open-xml/) for more information and how to convert units. + +## Compatibility + +Compatibility Settings are optional settings used to preserve visual fidelity of documents created in earlier word processing applications. Some of these settings provide ability for specific behaviors, described in detail below; and others simply instruct applications to mimic the behavior of an existing word processing application. + +```ts +const doc = new docx.Document({ + compatibility: { + version: 15, + doNotExpandShiftReturn: true, + }, +}); +``` + +### Compatibility Options + +| Property | Type | Notes | Possible Values | +| ----------------------------------- | --------- | -------- | ---------------------------- | +| version | `number` | Optional | `15`, `16`, `17` | +| useSingleBorderforContiguousCells | `boolean` | Optional | `true`, `false`, `undefined` | +| wordPerfectJustification | `boolean` | Optional | `true`, `false`, `undefined` | +| noTabStopForHangingIndent | `boolean` | Optional | `true`, `false`, `undefined` | +| noLeading | `boolean` | Optional | `true`, `false`, `undefined` | +| spaceForUnderline | `boolean` | Optional | `true`, `false`, `undefined` | +| noColumnBalance | `boolean` | Optional | `true`, `false`, `undefined` | +| balanceSingleByteDoubleByteWidth | `boolean` | Optional | `true`, `false`, `undefined` | +| noExtraLineSpacing | `boolean` | Optional | `true`, `false`, `undefined` | +| doNotLeaveBackslashAlone | `boolean` | Optional | `true`, `false`, `undefined` | +| underlineTrailingSpaces | `boolean` | Optional | `true`, `false`, `undefined` | +| doNotExpandShiftReturn | `boolean` | Optional | `true`, `false`, `undefined` | +| spacingInWholePoints | `boolean` | Optional | `true`, `false`, `undefined` | +| lineWrapLikeWord6 | `boolean` | Optional | `true`, `false`, `undefined` | +| printBodyTextBeforeHeader | `boolean` | Optional | `true`, `false`, `undefined` | +| printColorsBlack | `boolean` | Optional | `true`, `false`, `undefined` | +| spaceWidth | `boolean` | Optional | `true`, `false`, `undefined` | +| showBreaksInFrames | `boolean` | Optional | `true`, `false`, `undefined` | +| subFontBySize | `boolean` | Optional | `true`, `false`, `undefined` | +| suppressBottomSpacing | `boolean` | Optional | `true`, `false`, `undefined` | +| suppressTopSpacing | `boolean` | Optional | `true`, `false`, `undefined` | +| suppressSpacingAtTopOfPage | `boolean` | Optional | `true`, `false`, `undefined` | +| suppressTopSpacingWP | `boolean` | Optional | `true`, `false`, `undefined` | +| suppressSpBfAfterPgBrk | `boolean` | Optional | `true`, `false`, `undefined` | +| swapBordersFacingPages | `boolean` | Optional | `true`, `false`, `undefined` | +| convertMailMergeEsc | `boolean` | Optional | `true`, `false`, `undefined` | +| truncateFontHeightsLikeWP6 | `boolean` | Optional | `true`, `false`, `undefined` | +| macWordSmallCaps | `boolean` | Optional | `true`, `false`, `undefined` | +| usePrinterMetrics | `boolean` | Optional | `true`, `false`, `undefined` | +| doNotSuppressParagraphBorders | `boolean` | Optional | `true`, `false`, `undefined` | +| wrapTrailSpaces | `boolean` | Optional | `true`, `false`, `undefined` | +| footnoteLayoutLikeWW8 | `boolean` | Optional | `true`, `false`, `undefined` | +| shapeLayoutLikeWW8 | `boolean` | Optional | `true`, `false`, `undefined` | +| alignTablesRowByRow | `boolean` | Optional | `true`, `false`, `undefined` | +| forgetLastTabAlignment | `boolean` | Optional | `true`, `false`, `undefined` | +| adjustLineHeightInTable | `boolean` | Optional | `true`, `false`, `undefined` | +| autoSpaceLikeWord95 | `boolean` | Optional | `true`, `false`, `undefined` | +| noSpaceRaiseLower | `boolean` | Optional | `true`, `false`, `undefined` | +| doNotUseHTMLParagraphAutoSpacing | `boolean` | Optional | `true`, `false`, `undefined` | +| layoutRawTableWidth | `boolean` | Optional | `true`, `false`, `undefined` | +| layoutTableRowsApart | `boolean` | Optional | `true`, `false`, `undefined` | +| useWord97LineBreakRules | `boolean` | Optional | `true`, `false`, `undefined` | +| doNotBreakWrappedTables | `boolean` | Optional | `true`, `false`, `undefined` | +| doNotSnapToGridInCell | `boolean` | Optional | `true`, `false`, `undefined` | +| selectFieldWithFirstOrLastCharacter | `boolean` | Optional | `true`, `false`, `undefined` | +| applyBreakingRules | `boolean` | Optional | `true`, `false`, `undefined` | +| doNotWrapTextWithPunctuation | `boolean` | Optional | `true`, `false`, `undefined` | +| doNotUseEastAsianBreakRules | `boolean` | Optional | `true`, `false`, `undefined` | +| useWord2002TableStyleRules | `boolean` | Optional | `true`, `false`, `undefined` | +| growAutofit | `boolean` | Optional | `true`, `false`, `undefined` | +| useFELayout | `boolean` | Optional | `true`, `false`, `undefined` | +| useNormalStyleForList | `boolean` | Optional | `true`, `false`, `undefined` | +| doNotUseIndentAsNumberingTabStop | `boolean` | Optional | `true`, `false`, `undefined` | +| useAlternateEastAsianLineBreakRules | `boolean` | Optional | `true`, `false`, `undefined` | +| allowSpaceOfSameStyleInTable | `boolean` | Optional | `true`, `false`, `undefined` | +| doNotSuppressIndentation | `boolean` | Optional | `true`, `false`, `undefined` | +| doNotAutofitConstrainedTables | `boolean` | Optional | `true`, `false`, `undefined` | +| autofitToFirstFixedWidthCell | `boolean` | Optional | `true`, `false`, `undefined` | +| underlineTabInNumberingList | `boolean` | Optional | `true`, `false`, `undefined` | +| displayHangulFixedWidth | `boolean` | Optional | `true`, `false`, `undefined` | +| splitPgBreakAndParaMark | `boolean` | Optional | `true`, `false`, `undefined` | +| doNotVerticallyAlignCellWithSp | `boolean` | Optional | `true`, `false`, `undefined` | +| doNotBreakConstrainedForcedTable | `boolean` | Optional | `true`, `false`, `undefined` | +| ignoreVerticalAlignmentInTextboxes | `boolean` | Optional | `true`, `false`, `undefined` | +| useAnsiKerningPairs | `boolean` | Optional | `true`, `false`, `undefined` | +| cachedColumnBalance | `boolean` | Optional | `true`, `false`, `undefined` | diff --git a/src/file/core-properties/properties.ts b/src/file/core-properties/properties.ts index 264203f753..b09b2d97d0 100644 --- a/src/file/core-properties/properties.ts +++ b/src/file/core-properties/properties.ts @@ -1,4 +1,5 @@ import { ICommentsOptions } from "@file/paragraph/run/comment-run"; +import { ICompatibilityOptions } from "@file/settings/compatibility"; import { StringContainer, XmlComponent } from "@file/xml-components"; import { dateTimeValue } from "@util/values"; @@ -35,6 +36,7 @@ export interface IPropertiesOptions { readonly updateFields?: boolean; }; readonly compatabilityModeVersion?: number; + readonly compatibility?: ICompatibilityOptions; readonly customProperties?: readonly ICustomPropertyOptions[]; readonly evenAndOddHeaderAndFooters?: boolean; } diff --git a/src/file/file.ts b/src/file/file.ts index 0f170d7d7f..383babc378 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -75,7 +75,8 @@ export class File { this.contentTypes = new ContentTypes(); this.documentWrapper = new DocumentWrapper({ background: options.background || {} }); this.settings = new Settings({ - compatabilityModeVersion: options.compatabilityModeVersion, + compatibilityModeVersion: options.compatabilityModeVersion, + compatibility: options.compatibility, evenAndOddHeaders: options.evenAndOddHeaderAndFooters ? true : false, trackRevisions: options.features?.trackRevisions, updateFields: options.features?.updateFields, diff --git a/src/file/settings/compatibility.spec.ts b/src/file/settings/compatibility.spec.ts index c264ad70bf..102f7375d0 100644 --- a/src/file/settings/compatibility.spec.ts +++ b/src/file/settings/compatibility.spec.ts @@ -1,7 +1,6 @@ import { expect } from "chai"; import { Formatter } from "@export/formatter"; -import { EMPTY_OBJECT } from "@file/xml-components"; import { Compatibility } from "./compatibility"; @@ -11,7 +10,140 @@ describe("Compatibility", () => { const compatibility = new Compatibility({}); const tree = new Formatter().format(compatibility); - expect(tree).to.deep.equal({ "w:compat": EMPTY_OBJECT }); + expect(tree).to.deep.equal({ "w:compat": {} }); + }); + }); + + describe("#version", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + version: 10, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ + "w:compat": [ + { + "w:compatSetting": { + _attr: { + "w:name": "compatibilityMode", + "w:uri": "http://schemas.microsoft.com/office/word", + "w:val": 10, + }, + }, + }, + ], + }); + }); + }); + + describe("#useSingleBorderforContiguousCells", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + useSingleBorderforContiguousCells: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:useSingleBorderforContiguousCells": {} }] }); + }); + }); + + describe("#wordPerfectJustification", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + wordPerfectJustification: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:wpJustification": {} }] }); + }); + }); + + describe("#noTabStopForHangingIndent", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + noTabStopForHangingIndent: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:noTabHangInd": {} }] }); + }); + }); + + describe("#noLeading", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + noLeading: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:noLeading": {} }] }); + }); + }); + + describe("#spaceForUnderline", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + spaceForUnderline: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:spaceForUL": {} }] }); + }); + }); + + describe("#noColumnBalance", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + noColumnBalance: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:noColumnBalance": {} }] }); + }); + }); + + describe("#balanceSingleByteDoubleByteWidth", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + balanceSingleByteDoubleByteWidth: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:balanceSingleByteDoubleByteWidth": {} }] }); + }); + }); + + describe("#noExtraLineSpacing", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + noExtraLineSpacing: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:noExtraLineSpacing": {} }] }); + }); + }); + + describe("#doNotLeaveBackslashAlone", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + doNotLeaveBackslashAlone: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotLeaveBackslashAlone": {} }] }); + }); + }); + + describe("#underlineTrailingSpaces", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + underlineTrailingSpaces: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:ulTrailSpace": {} }] }); }); }); @@ -22,7 +154,601 @@ describe("Compatibility", () => { }); const tree = new Formatter().format(compatibility); - expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotExpandShiftReturn": EMPTY_OBJECT }] }); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotExpandShiftReturn": {} }] }); + }); + }); + + describe("#spacingInWholePoints", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + spacingInWholePoints: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:spacingInWholePoints": {} }] }); + }); + }); + + describe("#lineWrapLikeWord6", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + lineWrapLikeWord6: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:lineWrapLikeWord6": {} }] }); + }); + }); + + describe("#printBodyTextBeforeHeader", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + printBodyTextBeforeHeader: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:printBodyTextBeforeHeader": {} }] }); + }); + }); + + describe("#printColorsBlack", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + printColorsBlack: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:printColBlack": {} }] }); + }); + }); + + describe("#spaceWidth", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + spaceWidth: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:wpSpaceWidth": {} }] }); + }); + }); + + describe("#showBreaksInFrames", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + showBreaksInFrames: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:showBreaksInFrames": {} }] }); + }); + }); + + describe("#subFontBySize", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + subFontBySize: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:subFontBySize": {} }] }); + }); + }); + + describe("#suppressBottomSpacing", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + suppressBottomSpacing: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:suppressBottomSpacing": {} }] }); + }); + }); + + describe("#suppressTopSpacing", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + suppressTopSpacing: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:suppressTopSpacing": {} }] }); + }); + }); + + describe("#suppressSpacingAtTopOfPage", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + suppressSpacingAtTopOfPage: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:suppressSpacingAtTopOfPage": {} }] }); + }); + }); + + describe("#suppressTopSpacingWP", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + suppressTopSpacingWP: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:suppressTopSpacingWP": {} }] }); + }); + }); + + describe("#suppressSpBfAfterPgBrk", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + suppressSpBfAfterPgBrk: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:suppressSpBfAfterPgBrk": {} }] }); + }); + }); + + describe("#swapBordersFacingPages", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + swapBordersFacingPages: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:swapBordersFacingPages": {} }] }); + }); + }); + + describe("#convertMailMergeEsc", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + convertMailMergeEsc: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:convMailMergeEsc": {} }] }); + }); + }); + + describe("#truncateFontHeightsLikeWP6", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + truncateFontHeightsLikeWP6: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:truncateFontHeightsLikeWP6": {} }] }); + }); + }); + + describe("#macWordSmallCaps", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + macWordSmallCaps: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:mwSmallCaps": {} }] }); + }); + }); + + describe("#usePrinterMetrics", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + usePrinterMetrics: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:usePrinterMetrics": {} }] }); + }); + }); + + describe("#doNotSuppressParagraphBorders", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + doNotSuppressParagraphBorders: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotSuppressParagraphBorders": {} }] }); + }); + }); + + describe("#wrapTrailSpaces", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + wrapTrailSpaces: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:wrapTrailSpaces": {} }] }); + }); + }); + + describe("#footnoteLayoutLikeWW8", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + footnoteLayoutLikeWW8: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:footnoteLayoutLikeWW8": {} }] }); + }); + }); + + describe("#shapeLayoutLikeWW8", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + shapeLayoutLikeWW8: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:shapeLayoutLikeWW8": {} }] }); + }); + }); + + describe("#alignTablesRowByRow", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + alignTablesRowByRow: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:alignTablesRowByRow": {} }] }); + }); + }); + + describe("#forgetLastTabAlignment", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + forgetLastTabAlignment: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:forgetLastTabAlignment": {} }] }); + }); + }); + + describe("#adjustLineHeightInTable", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + adjustLineHeightInTable: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:adjustLineHeightInTable": {} }] }); + }); + }); + + describe("#autoSpaceLikeWord95", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + autoSpaceLikeWord95: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:autoSpaceLikeWord95": {} }] }); + }); + }); + + describe("#noSpaceRaiseLower", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + noSpaceRaiseLower: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:noSpaceRaiseLower": {} }] }); + }); + }); + + describe("#doNotUseHTMLParagraphAutoSpacing", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + doNotUseHTMLParagraphAutoSpacing: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotUseHTMLParagraphAutoSpacing": {} }] }); + }); + }); + + describe("#layoutRawTableWidth", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + layoutRawTableWidth: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:layoutRawTableWidth": {} }] }); + }); + }); + + describe("#layoutTableRowsApart", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + layoutTableRowsApart: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:layoutTableRowsApart": {} }] }); + }); + }); + + describe("#useWord97LineBreakRules", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + useWord97LineBreakRules: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:useWord97LineBreakRules": {} }] }); + }); + }); + + describe("#doNotBreakWrappedTables", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + doNotBreakWrappedTables: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotBreakWrappedTables": {} }] }); + }); + }); + + describe("#doNotSnapToGridInCell", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + doNotSnapToGridInCell: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotSnapToGridInCell": {} }] }); + }); + }); + + describe("#selectFieldWithFirstOrLastCharacter", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + selectFieldWithFirstOrLastCharacter: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:selectFldWithFirstOrLastChar": {} }] }); + }); + }); + + describe("#applyBreakingRules", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + applyBreakingRules: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:applyBreakingRules": {} }] }); + }); + }); + + describe("#doNotWrapTextWithPunctuation", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + doNotWrapTextWithPunctuation: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotWrapTextWithPunct": {} }] }); + }); + }); + + describe("#doNotUseEastAsianBreakRules", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + doNotUseEastAsianBreakRules: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotUseEastAsianBreakRules": {} }] }); + }); + }); + + describe("#useWord2002TableStyleRules", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + useWord2002TableStyleRules: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:useWord2002TableStyleRules": {} }] }); + }); + }); + + describe("#growAutofit", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + growAutofit: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:growAutofit": {} }] }); + }); + }); + + describe("#useFELayout", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + useFELayout: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:useFELayout": {} }] }); + }); + }); + + describe("#useNormalStyleForList", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + useNormalStyleForList: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:useNormalStyleForList": {} }] }); + }); + }); + + describe("#doNotUseIndentAsNumberingTabStop", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + doNotUseIndentAsNumberingTabStop: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotUseIndentAsNumberingTabStop": {} }] }); + }); + }); + + describe("#useAlternateEastAsianLineBreakRules", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + useAlternateEastAsianLineBreakRules: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:useAltKinsokuLineBreakRules": {} }] }); + }); + }); + + describe("#allowSpaceOfSameStyleInTable", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + allowSpaceOfSameStyleInTable: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:allowSpaceOfSameStyleInTable": {} }] }); + }); + }); + + describe("#doNotSuppressIndentation", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + doNotSuppressIndentation: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotSuppressIndentation": {} }] }); + }); + }); + + describe("#doNotAutofitConstrainedTables", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + doNotAutofitConstrainedTables: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotAutofitConstrainedTables": {} }] }); + }); + }); + + describe("#autofitToFirstFixedWidthCell", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + autofitToFirstFixedWidthCell: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:autofitToFirstFixedWidthCell": {} }] }); + }); + }); + + describe("#underlineTabInNumberingList", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + underlineTabInNumberingList: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:underlineTabInNumList": {} }] }); + }); + }); + + describe("#displayHangulFixedWidth", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + displayHangulFixedWidth: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:displayHangulFixedWidth": {} }] }); + }); + }); + + describe("#splitPgBreakAndParaMark", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + splitPgBreakAndParaMark: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:splitPgBreakAndParaMark": {} }] }); + }); + }); + + describe("#doNotVerticallyAlignCellWithSp", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + doNotVerticallyAlignCellWithSp: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotVertAlignCellWithSp": {} }] }); + }); + }); + + describe("#doNotBreakConstrainedForcedTable", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + doNotBreakConstrainedForcedTable: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotBreakConstrainedForcedTable": {} }] }); + }); + }); + + describe("#ignoreVerticalAlignmentInTextboxes", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + ignoreVerticalAlignmentInTextboxes: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotVertAlignInTxbx": {} }] }); + }); + }); + + describe("#useAnsiKerningPairs", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + useAnsiKerningPairs: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:useAnsiKerningPairs": {} }] }); + }); + }); + + describe("#cachedColumnBalance", () => { + it("should create a setting for not justifying lines ending in soft line break", () => { + const compatibility = new Compatibility({ + cachedColumnBalance: true, + }); + + const tree = new Formatter().format(compatibility); + expect(tree).to.deep.equal({ "w:compat": [{ "w:cachedColBalance": {} }] }); }); }); }); diff --git a/src/file/settings/compatibility.ts b/src/file/settings/compatibility.ts index 713a8b8777..1f2160c91a 100644 --- a/src/file/settings/compatibility.ts +++ b/src/file/settings/compatibility.ts @@ -1,3 +1,4 @@ +// http://www.datypic.com/sc/ooxml/e-w_compat-1.html import { OnOffElement, XmlComponent } from "@file/xml-components"; import { CompatibilitySetting } from "./compatibility-setting/compatibility-setting"; @@ -74,21 +75,405 @@ import { CompatibilitySetting } from "./compatibility-setting/compatibility-sett // export interface ICompatibilityOptions { - readonly doNotExpandShiftReturn?: boolean; readonly version?: number; + /** Use Simplified Rules For Table Border Conflicts */ + readonly useSingleBorderforContiguousCells?: boolean; + /** Emulate WordPerfect 6.x Paragraph Justification */ + readonly wordPerfectJustification?: boolean; + /** Do Not Create Custom Tab Stop for Hanging Indent */ + readonly noTabStopForHangingIndent?: boolean; + /** Do Not Add Leading Between Lines of Text */ + readonly noLeading?: boolean; + /** Add Additional Space Below Baseline For Underlined East Asian Text */ + readonly spaceForUnderline?: boolean; + /** Do Not Balance Text Columns within a Section */ + readonly noColumnBalance?: boolean; + /** Balance Single Byte and Double Byte Characters */ + readonly balanceSingleByteDoubleByteWidth?: boolean; + /** Do Not Center Content on Lines With Exact Line Height */ + readonly noExtraLineSpacing?: boolean; + /** Convert Backslash To Yen Sign When Entered */ + readonly doNotLeaveBackslashAlone?: boolean; + /** Underline All Trailing Spaces */ + readonly underlineTrailingSpaces?: boolean; + /** Don't Justify Lines Ending in Soft Line Break */ + readonly doNotExpandShiftReturn?: boolean; + /** Only Expand/Condense Text By Whole Points */ + readonly spacingInWholePoints?: boolean; + /** Emulate Word 6.0 Line Wrapping for East Asian Text */ + readonly lineWrapLikeWord6?: boolean; + /** Print Body Text before Header/Footer Contents */ + readonly printBodyTextBeforeHeader?: boolean; + /** Print Colors as Black And White without Dithering */ + readonly printColorsBlack?: boolean; + /** Space width */ + readonly spaceWidth?: boolean; + /** Display Page/Column Breaks Present in Frames */ + readonly showBreaksInFrames?: boolean; + /** Increase Priority Of Font Size During Font Substitution */ + readonly subFontBySize?: boolean; + /** Ignore Exact Line Height for Last Line on Page */ + readonly suppressBottomSpacing?: boolean; + /** Ignore Minimum and Exact Line Height for First Line on Page */ + readonly suppressTopSpacing?: boolean; + /** Ignore Minimum Line Height for First Line on Page */ + readonly suppressSpacingAtTopOfPage?: boolean; + /** Emulate WordPerfect 5.x Line Spacing */ + readonly suppressTopSpacingWP?: boolean; + /** Do Not Use Space Before On First Line After a Page Break */ + readonly suppressSpBfAfterPgBrk?: boolean; + /** Swap Paragraph Borders on Odd Numbered Pages */ + readonly swapBordersFacingPages?: boolean; + /** Treat Backslash Quotation Delimiter as Two Quotation Marks */ + readonly convertMailMergeEsc?: boolean; + /** Emulate WordPerfect 6.x Font Height Calculation */ + readonly truncateFontHeightsLikeWP6?: boolean; + /** Emulate Word 5.x for the Macintosh Small Caps Formatting */ + readonly macWordSmallCaps?: boolean; + /** Use Printer Metrics To Display Documents */ + readonly usePrinterMetrics?: boolean; + /** Do Not Suppress Paragraph Borders Next To Frames */ + readonly doNotSuppressParagraphBorders?: boolean; + /** Line Wrap Trailing Spaces */ + readonly wrapTrailSpaces?: boolean; + /** Emulate Word 6.x/95/97 Footnote Placement */ + readonly footnoteLayoutLikeWW8?: boolean; + /** Emulate Word 97 Text Wrapping Around Floating Objects */ + readonly shapeLayoutLikeWW8?: boolean; + /** Align Table Rows Independently */ + readonly alignTablesRowByRow?: boolean; + /** Ignore Width of Last Tab Stop When Aligning Paragraph If It Is Not Left Aligned */ + readonly forgetLastTabAlignment?: boolean; + /** Add Document Grid Line Pitch To Lines in Table Cells */ + readonly adjustLineHeightInTable?: boolean; + /** Emulate Word 95 Full-Width Character Spacing */ + readonly autoSpaceLikeWord95?: boolean; + /** Do Not Increase Line Height for Raised/Lowered Text */ + readonly noSpaceRaiseLower?: boolean; + /** Use Fixed Paragraph Spacing for HTML Auto Setting */ + readonly doNotUseHTMLParagraphAutoSpacing?: boolean; + /** Ignore Space Before Table When Deciding If Table Should Wrap Floating Object */ + readonly layoutRawTableWidth?: boolean; + /** Allow Table Rows to Wrap Inline Objects Independently */ + readonly layoutTableRowsApart?: boolean; + /** Emulate Word 97 East Asian Line Breaking */ + readonly useWord97LineBreakRules?: boolean; + /** Do Not Allow Floating Tables To Break Across Pages */ + readonly doNotBreakWrappedTables?: boolean; + /** Do Not Snap to Document Grid in Table Cells with Objects */ + readonly doNotSnapToGridInCell?: boolean; + /** Select Field When First or Last Character Is Selected */ + readonly selectFieldWithFirstOrLastCharacter?: boolean; + /** Use Legacy Ethiopic and Amharic Line Breaking Rules */ + readonly applyBreakingRules?: boolean; + /** Do Not Allow Hanging Punctuation With Character Grid */ + readonly doNotWrapTextWithPunctuation?: boolean; + /** Do Not Compress Compressible Characters When Using Document Grid */ + readonly doNotUseEastAsianBreakRules?: boolean; + /** Emulate Word 2002 Table Style Rules */ + readonly useWord2002TableStyleRules?: boolean; + /** Allow Tables to AutoFit Into Page Margins */ + readonly growAutofit?: boolean; + /** Do Not Bypass East Asian/Complex Script Layout Code */ + readonly useFELayout?: boolean; + /** Do Not Automatically Apply List Paragraph Style To Bulleted/Numbered Text */ + readonly useNormalStyleForList?: boolean; + /** Ignore Hanging Indent When Creating Tab Stop After Numbering */ + readonly doNotUseIndentAsNumberingTabStop?: boolean; + /** Use Alternate Set of East Asian Line Breaking Rules */ + readonly useAlternateEastAsianLineBreakRules?: boolean; + /** Allow Contextual Spacing of Paragraphs in Tables */ + readonly allowSpaceOfSameStyleInTable?: boolean; + /** Do Not Ignore Floating Objects When Calculating Paragraph Indentation */ + readonly doNotSuppressIndentation?: boolean; + /** Do Not AutoFit Tables To Fit Next To Wrapped Objects */ + readonly doNotAutofitConstrainedTables?: boolean; + /** Allow Table Columns To Exceed Preferred Widths of Constituent Cells */ + readonly autofitToFirstFixedWidthCell?: boolean; + /** Underline Following Character Following Numbering */ + readonly underlineTabInNumberingList?: boolean; + /** Always Use Fixed Width for Hangul Characters */ + readonly displayHangulFixedWidth?: boolean; + /** Always Move Paragraph Mark to Page after a Page Break */ + readonly splitPgBreakAndParaMark?: boolean; + /** Don't Vertically Align Cells Containing Floating Objects */ + readonly doNotVerticallyAlignCellWithSp?: boolean; + /** Don't Break Table Rows Around Floating Tables */ + readonly doNotBreakConstrainedForcedTable?: boolean; + /** Ignore Vertical Alignment in Textboxes */ + readonly ignoreVerticalAlignmentInTextboxes?: boolean; + /** Use ANSI Kerning Pairs from Fonts */ + readonly useAnsiKerningPairs?: boolean; + /** Use Cached Paragraph Information for Column Balancing */ + readonly cachedColumnBalance?: boolean; } export class Compatibility extends XmlComponent { public constructor(options: ICompatibilityOptions) { super("w:compat"); - // 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) { this.root.push(new CompatibilitySetting(options.version)); } + + if (options.useSingleBorderforContiguousCells) { + this.root.push(new OnOffElement("w:useSingleBorderforContiguousCells", options.useSingleBorderforContiguousCells)); + } + + if (options.wordPerfectJustification) { + this.root.push(new OnOffElement("w:wpJustification", options.wordPerfectJustification)); + } + + if (options.noTabStopForHangingIndent) { + this.root.push(new OnOffElement("w:noTabHangInd", options.noTabStopForHangingIndent)); + } + + if (options.noLeading) { + this.root.push(new OnOffElement("w:noLeading", options.noLeading)); + } + + if (options.spaceForUnderline) { + this.root.push(new OnOffElement("w:spaceForUL", options.spaceForUnderline)); + } + + if (options.noColumnBalance) { + this.root.push(new OnOffElement("w:noColumnBalance", options.noColumnBalance)); + } + + if (options.balanceSingleByteDoubleByteWidth) { + this.root.push(new OnOffElement("w:balanceSingleByteDoubleByteWidth", options.balanceSingleByteDoubleByteWidth)); + } + + if (options.noExtraLineSpacing) { + this.root.push(new OnOffElement("w:noExtraLineSpacing", options.noExtraLineSpacing)); + } + + if (options.doNotLeaveBackslashAlone) { + this.root.push(new OnOffElement("w:doNotLeaveBackslashAlone", options.doNotLeaveBackslashAlone)); + } + + if (options.underlineTrailingSpaces) { + this.root.push(new OnOffElement("w:ulTrailSpace", options.underlineTrailingSpaces)); + } + + if (options.doNotExpandShiftReturn) { + this.root.push(new OnOffElement("w:doNotExpandShiftReturn", options.doNotExpandShiftReturn)); + } + + if (options.spacingInWholePoints) { + this.root.push(new OnOffElement("w:spacingInWholePoints", options.spacingInWholePoints)); + } + + if (options.lineWrapLikeWord6) { + this.root.push(new OnOffElement("w:lineWrapLikeWord6", options.lineWrapLikeWord6)); + } + + if (options.printBodyTextBeforeHeader) { + this.root.push(new OnOffElement("w:printBodyTextBeforeHeader", options.printBodyTextBeforeHeader)); + } + + if (options.printColorsBlack) { + this.root.push(new OnOffElement("w:printColBlack", options.printColorsBlack)); + } + + if (options.spaceWidth) { + this.root.push(new OnOffElement("w:wpSpaceWidth", options.spaceWidth)); + } + + if (options.showBreaksInFrames) { + this.root.push(new OnOffElement("w:showBreaksInFrames", options.showBreaksInFrames)); + } + + if (options.subFontBySize) { + this.root.push(new OnOffElement("w:subFontBySize", options.subFontBySize)); + } + + if (options.suppressBottomSpacing) { + this.root.push(new OnOffElement("w:suppressBottomSpacing", options.suppressBottomSpacing)); + } + + if (options.suppressTopSpacing) { + this.root.push(new OnOffElement("w:suppressTopSpacing", options.suppressTopSpacing)); + } + + if (options.suppressSpacingAtTopOfPage) { + this.root.push(new OnOffElement("w:suppressSpacingAtTopOfPage", options.suppressSpacingAtTopOfPage)); + } + + if (options.suppressTopSpacingWP) { + this.root.push(new OnOffElement("w:suppressTopSpacingWP", options.suppressTopSpacingWP)); + } + + if (options.suppressSpBfAfterPgBrk) { + this.root.push(new OnOffElement("w:suppressSpBfAfterPgBrk", options.suppressSpBfAfterPgBrk)); + } + + if (options.swapBordersFacingPages) { + this.root.push(new OnOffElement("w:swapBordersFacingPages", options.swapBordersFacingPages)); + } + + if (options.convertMailMergeEsc) { + this.root.push(new OnOffElement("w:convMailMergeEsc", options.convertMailMergeEsc)); + } + + if (options.truncateFontHeightsLikeWP6) { + this.root.push(new OnOffElement("w:truncateFontHeightsLikeWP6", options.truncateFontHeightsLikeWP6)); + } + + if (options.macWordSmallCaps) { + this.root.push(new OnOffElement("w:mwSmallCaps", options.macWordSmallCaps)); + } + + if (options.usePrinterMetrics) { + this.root.push(new OnOffElement("w:usePrinterMetrics", options.usePrinterMetrics)); + } + + if (options.doNotSuppressParagraphBorders) { + this.root.push(new OnOffElement("w:doNotSuppressParagraphBorders", options.doNotSuppressParagraphBorders)); + } + + if (options.wrapTrailSpaces) { + this.root.push(new OnOffElement("w:wrapTrailSpaces", options.wrapTrailSpaces)); + } + + if (options.footnoteLayoutLikeWW8) { + this.root.push(new OnOffElement("w:footnoteLayoutLikeWW8", options.footnoteLayoutLikeWW8)); + } + + if (options.shapeLayoutLikeWW8) { + this.root.push(new OnOffElement("w:shapeLayoutLikeWW8", options.shapeLayoutLikeWW8)); + } + + if (options.alignTablesRowByRow) { + this.root.push(new OnOffElement("w:alignTablesRowByRow", options.alignTablesRowByRow)); + } + + if (options.forgetLastTabAlignment) { + this.root.push(new OnOffElement("w:forgetLastTabAlignment", options.forgetLastTabAlignment)); + } + + if (options.adjustLineHeightInTable) { + this.root.push(new OnOffElement("w:adjustLineHeightInTable", options.adjustLineHeightInTable)); + } + + if (options.autoSpaceLikeWord95) { + this.root.push(new OnOffElement("w:autoSpaceLikeWord95", options.autoSpaceLikeWord95)); + } + + if (options.noSpaceRaiseLower) { + this.root.push(new OnOffElement("w:noSpaceRaiseLower", options.noSpaceRaiseLower)); + } + + if (options.doNotUseHTMLParagraphAutoSpacing) { + this.root.push(new OnOffElement("w:doNotUseHTMLParagraphAutoSpacing", options.doNotUseHTMLParagraphAutoSpacing)); + } + + if (options.layoutRawTableWidth) { + this.root.push(new OnOffElement("w:layoutRawTableWidth", options.layoutRawTableWidth)); + } + + if (options.layoutTableRowsApart) { + this.root.push(new OnOffElement("w:layoutTableRowsApart", options.layoutTableRowsApart)); + } + + if (options.useWord97LineBreakRules) { + this.root.push(new OnOffElement("w:useWord97LineBreakRules", options.useWord97LineBreakRules)); + } + + if (options.doNotBreakWrappedTables) { + this.root.push(new OnOffElement("w:doNotBreakWrappedTables", options.doNotBreakWrappedTables)); + } + + if (options.doNotSnapToGridInCell) { + this.root.push(new OnOffElement("w:doNotSnapToGridInCell", options.doNotSnapToGridInCell)); + } + + if (options.selectFieldWithFirstOrLastCharacter) { + this.root.push(new OnOffElement("w:selectFldWithFirstOrLastChar", options.selectFieldWithFirstOrLastCharacter)); + } + + if (options.applyBreakingRules) { + this.root.push(new OnOffElement("w:applyBreakingRules", options.applyBreakingRules)); + } + + if (options.doNotWrapTextWithPunctuation) { + this.root.push(new OnOffElement("w:doNotWrapTextWithPunct", options.doNotWrapTextWithPunctuation)); + } + + if (options.doNotUseEastAsianBreakRules) { + this.root.push(new OnOffElement("w:doNotUseEastAsianBreakRules", options.doNotUseEastAsianBreakRules)); + } + + if (options.useWord2002TableStyleRules) { + this.root.push(new OnOffElement("w:useWord2002TableStyleRules", options.useWord2002TableStyleRules)); + } + + if (options.growAutofit) { + this.root.push(new OnOffElement("w:growAutofit", options.growAutofit)); + } + + if (options.useFELayout) { + this.root.push(new OnOffElement("w:useFELayout", options.useFELayout)); + } + + if (options.useNormalStyleForList) { + this.root.push(new OnOffElement("w:useNormalStyleForList", options.useNormalStyleForList)); + } + + if (options.doNotUseIndentAsNumberingTabStop) { + this.root.push(new OnOffElement("w:doNotUseIndentAsNumberingTabStop", options.doNotUseIndentAsNumberingTabStop)); + } + + if (options.useAlternateEastAsianLineBreakRules) { + this.root.push(new OnOffElement("w:useAltKinsokuLineBreakRules", options.useAlternateEastAsianLineBreakRules)); + } + + if (options.allowSpaceOfSameStyleInTable) { + this.root.push(new OnOffElement("w:allowSpaceOfSameStyleInTable", options.allowSpaceOfSameStyleInTable)); + } + + if (options.doNotSuppressIndentation) { + this.root.push(new OnOffElement("w:doNotSuppressIndentation", options.doNotSuppressIndentation)); + } + + if (options.doNotAutofitConstrainedTables) { + this.root.push(new OnOffElement("w:doNotAutofitConstrainedTables", options.doNotAutofitConstrainedTables)); + } + + if (options.autofitToFirstFixedWidthCell) { + this.root.push(new OnOffElement("w:autofitToFirstFixedWidthCell", options.autofitToFirstFixedWidthCell)); + } + + if (options.underlineTabInNumberingList) { + this.root.push(new OnOffElement("w:underlineTabInNumList", options.underlineTabInNumberingList)); + } + + if (options.displayHangulFixedWidth) { + this.root.push(new OnOffElement("w:displayHangulFixedWidth", options.displayHangulFixedWidth)); + } + + if (options.splitPgBreakAndParaMark) { + this.root.push(new OnOffElement("w:splitPgBreakAndParaMark", options.splitPgBreakAndParaMark)); + } + + if (options.doNotVerticallyAlignCellWithSp) { + this.root.push(new OnOffElement("w:doNotVertAlignCellWithSp", options.doNotVerticallyAlignCellWithSp)); + } + + if (options.doNotBreakConstrainedForcedTable) { + this.root.push(new OnOffElement("w:doNotBreakConstrainedForcedTable", options.doNotBreakConstrainedForcedTable)); + } + + if (options.ignoreVerticalAlignmentInTextboxes) { + this.root.push(new OnOffElement("w:doNotVertAlignInTxbx", options.ignoreVerticalAlignmentInTextboxes)); + } + + if (options.useAnsiKerningPairs) { + this.root.push(new OnOffElement("w:useAnsiKerningPairs", options.useAnsiKerningPairs)); + } + + if (options.cachedColumnBalance) { + this.root.push(new OnOffElement("w:cachedColBalance", options.cachedColumnBalance)); + } } } diff --git a/src/file/settings/settings.spec.ts b/src/file/settings/settings.spec.ts index 7bd473bdbf..8ee5b728f2 100644 --- a/src/file/settings/settings.spec.ts +++ b/src/file/settings/settings.spec.ts @@ -61,5 +61,80 @@ describe("Settings", () => { "w:trackRevisions": {}, }); }); + + it("should add compatibility setting with default compatability version", () => { + const settings = new Settings({ + compatibility: {}, + }); + + const tree = new Formatter().format(settings); + expect(Object.keys(tree)).has.length(1); + expect(tree["w:settings"]).to.be.an("array"); + + expect(tree["w:settings"]).to.deep.include({ + "w:compat": [ + { + "w:compatSetting": { + _attr: { + "w:name": "compatibilityMode", + "w:uri": "http://schemas.microsoft.com/office/word", + "w:val": 15, + }, + }, + }, + ], + }); + }); + + it("should add compatibility setting with version", () => { + const settings = new Settings({ + compatibility: { + version: 99, + }, + }); + + const tree = new Formatter().format(settings); + expect(Object.keys(tree)).has.length(1); + expect(tree["w:settings"]).to.be.an("array"); + + expect(tree["w:settings"]).to.deep.include({ + "w:compat": [ + { + "w:compatSetting": { + _attr: { + "w:name": "compatibilityMode", + "w:uri": "http://schemas.microsoft.com/office/word", + "w:val": 99, + }, + }, + }, + ], + }); + }); + + // TODO: Remove when deprecating compatibilityModeVersion + it("should add compatibility setting with legacy version", () => { + const settings = new Settings({ + compatibilityModeVersion: 99, + }); + + const tree = new Formatter().format(settings); + expect(Object.keys(tree)).has.length(1); + expect(tree["w:settings"]).to.be.an("array"); + + expect(tree["w:settings"]).to.deep.include({ + "w:compat": [ + { + "w:compatSetting": { + _attr: { + "w:name": "compatibilityMode", + "w:uri": "http://schemas.microsoft.com/office/word", + "w:val": 99, + }, + }, + }, + ], + }); + }); }); }); diff --git a/src/file/settings/settings.ts b/src/file/settings/settings.ts index ceb0e11c4e..76fe4c51fb 100644 --- a/src/file/settings/settings.ts +++ b/src/file/settings/settings.ts @@ -1,6 +1,6 @@ import { OnOffElement, XmlAttributeComponent, XmlComponent } from "@file/xml-components"; -import { Compatibility } from "./compatibility"; +import { Compatibility, ICompatibilityOptions } from "./compatibility"; export class SettingsAttributes extends XmlAttributeComponent<{ readonly wpc?: string; @@ -147,10 +147,11 @@ export class SettingsAttributes extends XmlAttributeComponent<{ // export interface ISettingsOptions { - readonly compatabilityModeVersion?: number; + readonly compatibilityModeVersion?: number; readonly evenAndOddHeaders?: boolean; readonly trackRevisions?: boolean; readonly updateFields?: boolean; + readonly compatibility?: ICompatibilityOptions; } export class Settings extends XmlComponent { @@ -199,7 +200,8 @@ export class Settings extends XmlComponent { this.root.push( new Compatibility({ - version: options.compatabilityModeVersion || 15, + ...(options.compatibility ?? {}), + version: options.compatibility?.version ?? options.compatibilityModeVersion ?? 15, }), ); }