diff --git a/src/file/core-properties/properties.ts b/src/file/core-properties/properties.ts index d51b1f23b7..9a9325090d 100644 --- a/src/file/core-properties/properties.ts +++ b/src/file/core-properties/properties.ts @@ -3,6 +3,7 @@ import { ICompatibilityOptions } from "@file/settings/compatibility"; import { FontOptions } from "@file/fonts/font-table"; import { StringContainer, XmlComponent } from "@file/xml-components"; import { dateTimeValue } from "@util/values"; +import { IHyphenationOptions } from "@file/settings"; import { ICustomPropertyOptions } from "../custom-properties"; import { IDocumentBackgroundOptions } from "../document"; @@ -42,6 +43,7 @@ export interface IPropertiesOptions { readonly evenAndOddHeaderAndFooters?: boolean; readonly defaultTabStop?: number; readonly fonts?: readonly FontOptions[]; + readonly hyphenation?: IHyphenationOptions; } // diff --git a/src/file/file.ts b/src/file/file.ts index 47dd895166..e3222d1fdf 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -80,6 +80,12 @@ export class File { trackRevisions: options.features?.trackRevisions, updateFields: options.features?.updateFields, defaultTabStop: options.defaultTabStop, + hyphenation: { + autoHyphenation: options.hyphenation?.autoHyphenation, + hyphenationZone: options.hyphenation?.hyphenationZone, + consecutiveHyphenLimit: options.hyphenation?.consecutiveHyphenLimit, + doNotHyphenateCaps: options.hyphenation?.doNotHyphenateCaps, + } }); this.media = new Media(); diff --git a/src/file/paragraph/run/properties.ts b/src/file/paragraph/run/properties.ts index 25e63a0cc7..73a628d4f2 100644 --- a/src/file/paragraph/run/properties.ts +++ b/src/file/paragraph/run/properties.ts @@ -319,6 +319,8 @@ export class RunProperties extends IgnoreIfEmptyXmlComponent { if (options.math) { this.push(new OnOffElement("w:oMath", options.math)); } + + } public push(item: XmlComponent): void { diff --git a/src/file/settings/settings.spec.ts b/src/file/settings/settings.spec.ts index 4b647684f5..d5034db54c 100644 --- a/src/file/settings/settings.spec.ts +++ b/src/file/settings/settings.spec.ts @@ -129,6 +129,75 @@ describe("Settings", () => { }); }); + it("should add autoHyphenation setting", () => { + const options = { + hyphenation: { + autoHyphenation: true, + } + }; + + const tree = new Formatter().format(new Settings(options)); + expect(Object.keys(tree)).has.length(1); + expect(tree["w:settings"]).to.be.an("array"); + expect(tree["w:settings"]).to.deep.include({ + "w:autoHyphenation": {}, + }); + }); + + + it("should add doNotHyphenateCaps setting", () => { + const options = { + hyphenation: { + doNotHyphenateCaps: true, + } + }; + + const tree = new Formatter().format(new Settings(options)); + expect(Object.keys(tree)).has.length(1); + expect(tree["w:settings"]).to.be.an("array"); + expect(tree["w:settings"]).to.deep.include({ + "w:doNotHyphenateCaps": {}, + }); + }); + + it("should add hyphenationZone setting", () => { + const options = { + hyphenation: { + hyphenationZone: 200, + } + }; + + const tree = new Formatter().format(new Settings(options)); + expect(Object.keys(tree)).has.length(1); + expect(tree["w:settings"]).to.be.an("array"); + expect(tree["w:settings"]).to.deep.include({ + "w:hyphenationZone": { + _attr: { + "w:val": 200, + }, + }, + }); + }); + + it("should add consecutiveHyphenLimit setting", () => { + const options = { + hyphenation: { + consecutiveHyphenLimit: 3, + } + }; + + const tree = new Formatter().format(new Settings(options)); + expect(Object.keys(tree)).has.length(1); + expect(tree["w:settings"]).to.be.an("array"); + expect(tree["w:settings"]).to.deep.include({ + "w:consecutiveHyphenLimit": { + _attr: { + "w:val": 3, + }, + }, + }); + }); + // TODO: Remove when deprecating compatibilityModeVersion it("should add compatibility setting with legacy version", () => { const settings = new Settings({ diff --git a/src/file/settings/settings.ts b/src/file/settings/settings.ts index ad89de7b49..e7e6e93b14 100644 --- a/src/file/settings/settings.ts +++ b/src/file/settings/settings.ts @@ -153,6 +153,18 @@ export interface ISettingsOptions { readonly updateFields?: boolean; readonly compatibility?: ICompatibilityOptions; readonly defaultTabStop?: number; + readonly hyphenation?: IHyphenationOptions; +} + +export interface IHyphenationOptions { + /** Specifies whether the application automatically hyphenates words as they are typed in the document. */ + readonly autoHyphenation?: boolean; + /** Specifies the minimum number of characters at the beginning of a word before a hyphen can be inserted. */ + readonly hyphenationZone?: number; + /** Specifies the maximum number of consecutive lines that can end with a hyphenated word. */ + readonly consecutiveHyphenLimit?: number; + /** Specifies whether to hyphenate words in all capital letters. */ + readonly doNotHyphenateCaps?: boolean; } export class Settings extends XmlComponent { @@ -204,6 +216,26 @@ export class Settings extends XmlComponent { this.root.push(new NumberValueElement("w:defaultTabStop", options.defaultTabStop)); } + // https://c-rex.net/samples/ooxml/e1/Part4/OOXML_P4_DOCX_autoHyphenation_topic_ID0EFUMX.html + if (options.hyphenation?.autoHyphenation !== undefined) { + this.root.push(new OnOffElement("w:autoHyphenation", options.hyphenation.autoHyphenation)); + } + + // https://c-rex.net/samples/ooxml/e1/Part4/OOXML_P4_DOCX_hyphenationZone_topic_ID0ERI3X.html + if (options.hyphenation?.hyphenationZone !== undefined) { + this.root.push(new NumberValueElement("w:hyphenationZone", options.hyphenation.hyphenationZone)); + } + + // https://c-rex.net/samples/ooxml/e1/Part4/OOXML_P4_DOCX_consecutiveHyphenLim_topic_ID0EQ6RX.html + if (options.hyphenation?.consecutiveHyphenLimit !== undefined) { + this.root.push(new NumberValueElement("w:consecutiveHyphenLimit", options.hyphenation.consecutiveHyphenLimit)); + } + + // https://c-rex.net/samples/ooxml/e1/Part4/OOXML_P4_DOCX_doNotHyphenateCaps_topic_ID0EW4XX.html + if (options.hyphenation?.doNotHyphenateCaps !== undefined) { + this.root.push(new OnOffElement("w:doNotHyphenateCaps", options.hyphenation.doNotHyphenateCaps)); + } + this.root.push( new Compatibility({ ...(options.compatibility ?? {}),