Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
7b2e8ede07 | |||
7da242ee9e | |||
d71203d2a6 | |||
064cee9921 |
@ -130,62 +130,6 @@ new Paragraph({
|
|||||||
}),
|
}),
|
||||||
```
|
```
|
||||||
|
|
||||||
## Disabling numbering inherited from paragraph style
|
|
||||||
|
|
||||||
If the numbering is set on a paragraph style, you may wish to disable it for a specific paragraph:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
const doc = new Document({
|
|
||||||
...
|
|
||||||
numbering: {
|
|
||||||
config: [
|
|
||||||
{
|
|
||||||
reference: "my-bullet-points",
|
|
||||||
levels: [
|
|
||||||
{
|
|
||||||
level: 0,
|
|
||||||
format: LevelFormat.BULLET,
|
|
||||||
text: "\u1F60",
|
|
||||||
alignment: AlignmentType.LEFT,
|
|
||||||
style: {
|
|
||||||
paragraph: {
|
|
||||||
indent: { left: convertInchesToTwip(0.5), hanging: convertInchesToTwip(0.25) },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
styles: {
|
|
||||||
paragraphStyles: [
|
|
||||||
{
|
|
||||||
id: 'bullet',
|
|
||||||
name: 'Bullet',
|
|
||||||
basedOn: 'Normal',
|
|
||||||
next: 'Normal',
|
|
||||||
run: {},
|
|
||||||
paragraph: {
|
|
||||||
numbering: {
|
|
||||||
reference: 'my-bullet-points',
|
|
||||||
level: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
...
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
```ts
|
|
||||||
new Paragraph({
|
|
||||||
text: "No bullet points!",
|
|
||||||
style: "Bullet",
|
|
||||||
numbering: false,
|
|
||||||
}),
|
|
||||||
```
|
|
||||||
|
|
||||||
## Full Example
|
## Full Example
|
||||||
|
|
||||||
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/3-numbering-and-bullet-points.ts ":include")
|
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/3-numbering-and-bullet-points.ts ":include")
|
||||||
|
@ -35,9 +35,6 @@ interface Patch {
|
|||||||
| type | `PatchType` | Required | `DOCUMENT`, `PARAGRAPH` |
|
| type | `PatchType` | Required | `DOCUMENT`, `PARAGRAPH` |
|
||||||
| children | `FileChild[] or ParagraphChild[]` | Required | The contents to replace with. A `FileChild` is a `Paragraph` or `Table`, whereas a `ParagraphChild` is typical `Paragraph` children. |
|
| children | `FileChild[] or ParagraphChild[]` | Required | The contents to replace with. A `FileChild` is a `Paragraph` or `Table`, whereas a `ParagraphChild` is typical `Paragraph` children. |
|
||||||
|
|
||||||
|
|
||||||
The patcher also takes in a `keepOriginalStyles` boolean, which will preserve the styles of the patched text when set to true.
|
|
||||||
|
|
||||||
### How to patch existing document
|
### How to patch existing document
|
||||||
|
|
||||||
1. Open your existing word document in your favorite Word Processor
|
1. Open your existing word document in your favorite Word Processor
|
||||||
|
@ -22,7 +22,7 @@ Then add the table in the `section`
|
|||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
sections: [{
|
sections: [{
|
||||||
children: [table],
|
children: [table],
|
||||||
}],
|
}];
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
1866
package-lock.json
generated
1866
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "docx",
|
"name": "docx",
|
||||||
"version": "8.6.0",
|
"version": "8.5.0",
|
||||||
"description": "Easily generate .docx files with JS/TS with a nice declarative API. Works for Node and on the Browser.",
|
"description": "Easily generate .docx files with JS/TS with a nice declarative API. Works for Node and on the Browser.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "build/index.umd.js",
|
"main": "build/index.umd.js",
|
||||||
@ -71,7 +71,7 @@
|
|||||||
"@types/prompt": "^1.1.1",
|
"@types/prompt": "^1.1.1",
|
||||||
"@types/unzipper": "^0.10.4",
|
"@types/unzipper": "^0.10.4",
|
||||||
"@types/xml": "^1.0.8",
|
"@types/xml": "^1.0.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
"@typescript-eslint/eslint-plugin": "^6.9.1",
|
||||||
"@typescript-eslint/parser": "^6.9.1",
|
"@typescript-eslint/parser": "^6.9.1",
|
||||||
"@vitest/coverage-v8": "^1.1.0",
|
"@vitest/coverage-v8": "^1.1.0",
|
||||||
"@vitest/ui": "^1.1.0",
|
"@vitest/ui": "^1.1.0",
|
||||||
@ -87,7 +87,7 @@
|
|||||||
"execa": "^8.0.1",
|
"execa": "^8.0.1",
|
||||||
"glob": "^10.2.7",
|
"glob": "^10.2.7",
|
||||||
"inquirer": "^9.2.7",
|
"inquirer": "^9.2.7",
|
||||||
"jsdom": "^24.0.0",
|
"jsdom": "^23.0.1",
|
||||||
"pre-commit": "^1.2.2",
|
"pre-commit": "^1.2.2",
|
||||||
"prettier": "^3.1.1",
|
"prettier": "^3.1.1",
|
||||||
"tsconfig-paths": "^4.0.0",
|
"tsconfig-paths": "^4.0.0",
|
||||||
|
@ -3,6 +3,8 @@ import { ICompatibilityOptions } from "@file/settings/compatibility";
|
|||||||
import { FontOptions } from "@file/fonts/font-table";
|
import { FontOptions } from "@file/fonts/font-table";
|
||||||
import { StringContainer, XmlComponent } from "@file/xml-components";
|
import { StringContainer, XmlComponent } from "@file/xml-components";
|
||||||
import { dateTimeValue } from "@util/values";
|
import { dateTimeValue } from "@util/values";
|
||||||
|
import { IHyphenationOptions } from "@file/settings";
|
||||||
|
import { IFootnoteProperties } from "@file/settings/footnote-properties";
|
||||||
|
|
||||||
import { ICustomPropertyOptions } from "../custom-properties";
|
import { ICustomPropertyOptions } from "../custom-properties";
|
||||||
import { IDocumentBackgroundOptions } from "../document";
|
import { IDocumentBackgroundOptions } from "../document";
|
||||||
@ -42,6 +44,8 @@ export interface IPropertiesOptions {
|
|||||||
readonly evenAndOddHeaderAndFooters?: boolean;
|
readonly evenAndOddHeaderAndFooters?: boolean;
|
||||||
readonly defaultTabStop?: number;
|
readonly defaultTabStop?: number;
|
||||||
readonly fonts?: readonly FontOptions[];
|
readonly fonts?: readonly FontOptions[];
|
||||||
|
readonly hyphenation?: IHyphenationOptions;
|
||||||
|
readonly footnoteProperties?: IFootnoteProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <xs:element name="coreProperties" type="CT_CoreProperties"/>
|
// <xs:element name="coreProperties" type="CT_CoreProperties"/>
|
||||||
|
@ -5,6 +5,7 @@ import { FooterWrapper } from "@file/footer-wrapper";
|
|||||||
import { HeaderWrapper } from "@file/header-wrapper";
|
import { HeaderWrapper } from "@file/header-wrapper";
|
||||||
import { VerticalAlign, VerticalAlignElement } from "@file/vertical-align";
|
import { VerticalAlign, VerticalAlignElement } from "@file/vertical-align";
|
||||||
import { OnOffElement, XmlComponent } from "@file/xml-components";
|
import { OnOffElement, XmlComponent } from "@file/xml-components";
|
||||||
|
import { FootnoteProperties, IFootnoteProperties } from "@file/settings/footnote-properties";
|
||||||
|
|
||||||
import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./properties/header-footer-reference";
|
import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./properties/header-footer-reference";
|
||||||
import { Columns, IColumnsAttributes } from "./properties/columns";
|
import { Columns, IColumnsAttributes } from "./properties/columns";
|
||||||
@ -39,6 +40,7 @@ export interface ISectionPropertiesOptions {
|
|||||||
readonly verticalAlign?: (typeof VerticalAlign)[keyof typeof VerticalAlign];
|
readonly verticalAlign?: (typeof VerticalAlign)[keyof typeof VerticalAlign];
|
||||||
readonly column?: IColumnsAttributes;
|
readonly column?: IColumnsAttributes;
|
||||||
readonly type?: (typeof SectionType)[keyof typeof SectionType];
|
readonly type?: (typeof SectionType)[keyof typeof SectionType];
|
||||||
|
readonly footnoteProperties?: IFootnoteProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <xsd:complexType name="CT_SectPr">
|
// <xsd:complexType name="CT_SectPr">
|
||||||
@ -119,6 +121,7 @@ export class SectionProperties extends XmlComponent {
|
|||||||
verticalAlign,
|
verticalAlign,
|
||||||
column,
|
column,
|
||||||
type,
|
type,
|
||||||
|
footnoteProperties,
|
||||||
}: ISectionPropertiesOptions = {}) {
|
}: ISectionPropertiesOptions = {}) {
|
||||||
super("w:sectPr");
|
super("w:sectPr");
|
||||||
|
|
||||||
@ -158,6 +161,10 @@ export class SectionProperties extends XmlComponent {
|
|||||||
this.root.push(new PageTextDirection(textDirection));
|
this.root.push(new PageTextDirection(textDirection));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (footnoteProperties) {
|
||||||
|
this.root.push(new FootnoteProperties(footnoteProperties));
|
||||||
|
}
|
||||||
|
|
||||||
this.root.push(new DocumentGrid(linePitch, charSpace, gridType));
|
this.root.push(new DocumentGrid(linePitch, charSpace, gridType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,12 +7,6 @@ export type EffectExtentAttributes = {
|
|||||||
readonly left: number;
|
readonly left: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
// <xsd:complexType name="CT_EffectExtent">
|
|
||||||
// <xsd:attribute name="l" type="a:ST_Coordinate" use="required"/>
|
|
||||||
// <xsd:attribute name="t" type="a:ST_Coordinate" use="required"/>
|
|
||||||
// <xsd:attribute name="r" type="a:ST_Coordinate" use="required"/>
|
|
||||||
// <xsd:attribute name="b" type="a:ST_Coordinate" use="required"/>
|
|
||||||
// </xsd:complexType>
|
|
||||||
export const createEffectExtent = ({ top, right, bottom, left }: EffectExtentAttributes): XmlComponent =>
|
export const createEffectExtent = ({ top, right, bottom, left }: EffectExtentAttributes): XmlComponent =>
|
||||||
new BuilderElement<EffectExtentAttributes>({
|
new BuilderElement<EffectExtentAttributes>({
|
||||||
name: "wp:effectExtent",
|
name: "wp:effectExtent",
|
||||||
|
@ -80,6 +80,12 @@ export class File {
|
|||||||
trackRevisions: options.features?.trackRevisions,
|
trackRevisions: options.features?.trackRevisions,
|
||||||
updateFields: options.features?.updateFields,
|
updateFields: options.features?.updateFields,
|
||||||
defaultTabStop: options.defaultTabStop,
|
defaultTabStop: options.defaultTabStop,
|
||||||
|
hyphenation: {
|
||||||
|
autoHyphenation: options.hyphenation?.autoHyphenation,
|
||||||
|
hyphenationZone: options.hyphenation?.hyphenationZone,
|
||||||
|
consecutiveHyphenLimit: options.hyphenation?.consecutiveHyphenLimit,
|
||||||
|
doNotHyphenateCaps: options.hyphenation?.doNotHyphenateCaps,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.media = new Media();
|
this.media = new Media();
|
||||||
|
@ -65,36 +65,6 @@ describe("ParagraphProperties", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create with numbering disabled", () => {
|
|
||||||
const properties = new ParagraphProperties({
|
|
||||||
numbering: false,
|
|
||||||
});
|
|
||||||
const tree = new Formatter().format(properties);
|
|
||||||
|
|
||||||
expect(tree).to.deep.equal({
|
|
||||||
"w:pPr": [
|
|
||||||
{
|
|
||||||
"w:numPr": [
|
|
||||||
{
|
|
||||||
"w:ilvl": {
|
|
||||||
_attr: {
|
|
||||||
"w:val": 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"w:numId": {
|
|
||||||
_attr: {
|
|
||||||
"w:val": 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should create with widowControl", () => {
|
it("should create with widowControl", () => {
|
||||||
const properties = new ParagraphProperties({
|
const properties = new ParagraphProperties({
|
||||||
widowControl: true,
|
widowControl: true,
|
||||||
|
@ -37,14 +37,12 @@ export interface ILevelParagraphStylePropertiesOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IParagraphStylePropertiesOptions extends ILevelParagraphStylePropertiesOptions {
|
export interface IParagraphStylePropertiesOptions extends ILevelParagraphStylePropertiesOptions {
|
||||||
readonly numbering?:
|
readonly numbering?: {
|
||||||
| {
|
readonly reference: string;
|
||||||
readonly reference: string;
|
readonly level: number;
|
||||||
readonly level: number;
|
readonly instance?: number;
|
||||||
readonly instance?: number;
|
readonly custom?: boolean;
|
||||||
readonly custom?: boolean;
|
};
|
||||||
}
|
|
||||||
| false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IParagraphPropertiesOptions extends IParagraphStylePropertiesOptions {
|
export interface IParagraphPropertiesOptions extends IParagraphStylePropertiesOptions {
|
||||||
@ -137,8 +135,6 @@ export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.push(new NumberProperties(`${options.numbering.reference}-${options.numbering.instance ?? 0}`, options.numbering.level));
|
this.push(new NumberProperties(`${options.numbering.reference}-${options.numbering.instance ?? 0}`, options.numbering.level));
|
||||||
} else if (options.numbering === false) {
|
|
||||||
this.push(new NumberProperties(0, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.border) {
|
if (options.border) {
|
||||||
|
23
src/file/settings/footnote-format.ts
Normal file
23
src/file/settings/footnote-format.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||||
|
import { NumberFormat } from "@file/shared/number-format";
|
||||||
|
|
||||||
|
export class FootnoteNumberingFormatAttributes extends XmlAttributeComponent<{
|
||||||
|
readonly numberFormat: (typeof NumberFormat)[keyof typeof NumberFormat];
|
||||||
|
}> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
numberFormat: "w:val",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FootnoteNumberingFormat extends XmlComponent {
|
||||||
|
public constructor(numberFormat: (typeof NumberFormat)[keyof typeof NumberFormat]) {
|
||||||
|
super("w:numFmt");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new FootnoteNumberingFormatAttributes({
|
||||||
|
numberFormat,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
23
src/file/settings/footnote-positioning.ts
Normal file
23
src/file/settings/footnote-positioning.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { FootnotePositioningLocationType } from "@file/shared/footnote-properties";
|
||||||
|
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
export class FootnotePositioningLocationAttributes extends XmlAttributeComponent<{
|
||||||
|
readonly position: FootnotePositioningLocationType;
|
||||||
|
}> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
position: "w:val",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FootnotePositioningLocation extends XmlComponent {
|
||||||
|
public constructor(position: FootnotePositioningLocationType) {
|
||||||
|
super("w:pos");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new FootnotePositioningLocationAttributes({
|
||||||
|
position,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
36
src/file/settings/footnote-properties.ts
Normal file
36
src/file/settings/footnote-properties.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// http://www.datypic.com/sc/ooxml/e-w_footnotePr-2.html
|
||||||
|
import { NumberValueElement, XmlComponent } from "@file/xml-components";
|
||||||
|
import { FootnotePositioningLocationType, FootnoteRestartLocationType } from "@file/shared/footnote-properties";
|
||||||
|
import { NumberFormat } from "@file/shared/number-format";
|
||||||
|
import { FootnoteNumberingRestart } from "./footnote-restart";
|
||||||
|
import { FootnotePositioningLocation } from "./footnote-positioning";
|
||||||
|
import { FootnoteNumberingFormat } from "./footnote-format";
|
||||||
|
|
||||||
|
export interface IFootnoteProperties {
|
||||||
|
readonly restartLocation?: FootnoteRestartLocationType;
|
||||||
|
readonly positioningLocation?: FootnotePositioningLocationType;
|
||||||
|
readonly numberFormat?: (typeof NumberFormat)[keyof typeof NumberFormat];
|
||||||
|
readonly startingNumber?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FootnoteProperties extends XmlComponent {
|
||||||
|
public constructor(options: IFootnoteProperties) {
|
||||||
|
super("w:footnotePr");
|
||||||
|
|
||||||
|
if (options.restartLocation !== undefined) {
|
||||||
|
this.root.push(new FootnoteNumberingRestart(options.restartLocation));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.positioningLocation !== undefined) {
|
||||||
|
this.root.push(new FootnotePositioningLocation(options.positioningLocation));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.numberFormat !== undefined) {
|
||||||
|
this.root.push(new FootnoteNumberingFormat(options.numberFormat));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.startingNumber !== undefined) {
|
||||||
|
this.root.push(new NumberValueElement('w:numStart', options.startingNumber));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
src/file/settings/footnote-restart.ts
Normal file
22
src/file/settings/footnote-restart.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { FootnoteRestartLocationType } from "@file/shared/footnote-properties";
|
||||||
|
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
export class FootnoteRestartNumberingAttributes extends XmlAttributeComponent<{
|
||||||
|
readonly restart: FootnoteRestartLocationType;
|
||||||
|
}> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
restart: "w:val",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FootnoteNumberingRestart extends XmlComponent {
|
||||||
|
public constructor(restart: FootnoteRestartLocationType) {
|
||||||
|
super("w:numRestart");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new FootnoteRestartNumberingAttributes({
|
||||||
|
restart,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
// TODO: Remove when deprecating compatibilityModeVersion
|
||||||
it("should add compatibility setting with legacy version", () => {
|
it("should add compatibility setting with legacy version", () => {
|
||||||
const settings = new Settings({
|
const settings = new Settings({
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { NumberValueElement, OnOffElement, XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
import { NumberValueElement, OnOffElement, XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
import { Compatibility, ICompatibilityOptions } from "./compatibility";
|
import { Compatibility, ICompatibilityOptions } from "./compatibility";
|
||||||
|
import { FootnoteProperties, IFootnoteProperties } from "./footnote-properties";
|
||||||
|
|
||||||
export class SettingsAttributes extends XmlAttributeComponent<{
|
export class SettingsAttributes extends XmlAttributeComponent<{
|
||||||
readonly wpc?: string;
|
readonly wpc?: string;
|
||||||
@ -153,6 +154,19 @@ export interface ISettingsOptions {
|
|||||||
readonly updateFields?: boolean;
|
readonly updateFields?: boolean;
|
||||||
readonly compatibility?: ICompatibilityOptions;
|
readonly compatibility?: ICompatibilityOptions;
|
||||||
readonly defaultTabStop?: number;
|
readonly defaultTabStop?: number;
|
||||||
|
readonly hyphenation?: IHyphenationOptions;
|
||||||
|
readonly footnoteProperties?: IFootnoteProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
export class Settings extends XmlComponent {
|
||||||
@ -204,6 +218,30 @@ export class Settings extends XmlComponent {
|
|||||||
this.root.push(new NumberValueElement("w:defaultTabStop", options.defaultTabStop));
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.footnoteProperties !== undefined) {
|
||||||
|
this.root.push(new FootnoteProperties(options.footnoteProperties));
|
||||||
|
}
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new Compatibility({
|
new Compatibility({
|
||||||
...(options.compatibility ?? {}),
|
...(options.compatibility ?? {}),
|
||||||
|
16
src/file/shared/footnote-properties.ts
Normal file
16
src/file/shared/footnote-properties.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export const FootnoteRestartLocation = {
|
||||||
|
CONTINUOUS: "continuous",
|
||||||
|
EACH_SECTION: "eachSect",
|
||||||
|
EACH_PAGE: "eachPage",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type FootnoteRestartLocationType = (typeof FootnoteRestartLocation)[keyof typeof FootnoteRestartLocation]
|
||||||
|
|
||||||
|
export const FootnotePositioningLocation = {
|
||||||
|
PAGE_BOTTOM: "pageBottom",
|
||||||
|
BENEATH_TEXT: "beneathText",
|
||||||
|
SECTION_END: "sectEnd",
|
||||||
|
DOCUMENT_END: "docEnd",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type FootnotePositioningLocationType = (typeof FootnotePositioningLocation)[keyof typeof FootnotePositioningLocation]
|
@ -1,3 +1,4 @@
|
|||||||
export * from "./alignment";
|
export * from "./alignment";
|
||||||
export * from "./number-format";
|
export * from "./number-format";
|
||||||
export * from "./space-type";
|
export * from "./space-type";
|
||||||
|
export * from "./footnote-properties";
|
||||||
|
@ -17,7 +17,7 @@ import { appendRelationship, getNextRelationshipIndex } from "./relationship-man
|
|||||||
import { appendContentType } from "./content-types-manager";
|
import { appendContentType } from "./content-types-manager";
|
||||||
|
|
||||||
// eslint-disable-next-line functional/prefer-readonly-type
|
// eslint-disable-next-line functional/prefer-readonly-type
|
||||||
export type InputDataType = Buffer | string | number[] | Uint8Array | ArrayBuffer | Blob | NodeJS.ReadableStream;
|
type InputDataType = Buffer | string | number[] | Uint8Array | ArrayBuffer | Blob | NodeJS.ReadableStream;
|
||||||
|
|
||||||
export const PatchType = {
|
export const PatchType = {
|
||||||
DOCUMENT: "file",
|
DOCUMENT: "file",
|
||||||
|
@ -1,2 +1 @@
|
|||||||
export * from "./from-docx";
|
export * from "./from-docx";
|
||||||
export * from "./patch-detector";
|
|
||||||
|
@ -1,225 +0,0 @@
|
|||||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
||||||
import JSZip from "jszip";
|
|
||||||
import { patchDetector } from "./patch-detector";
|
|
||||||
|
|
||||||
const MOCK_XML = `
|
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
||||||
<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
|
|
||||||
xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex"
|
|
||||||
xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex"
|
|
||||||
xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex"
|
|
||||||
xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex"
|
|
||||||
xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex"
|
|
||||||
xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex"
|
|
||||||
xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex"
|
|
||||||
xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex"
|
|
||||||
xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink"
|
|
||||||
xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d"
|
|
||||||
xmlns:o="urn:schemas-microsoft-com:office:office"
|
|
||||||
xmlns:oel="http://schemas.microsoft.com/office/2019/extlst"
|
|
||||||
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
|
||||||
xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
|
|
||||||
xmlns:v="urn:schemas-microsoft-com:vml"
|
|
||||||
xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"
|
|
||||||
xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
|
|
||||||
xmlns:w10="urn:schemas-microsoft-com:office:word"
|
|
||||||
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
|
||||||
xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
|
|
||||||
xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
|
|
||||||
xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex"
|
|
||||||
xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid"
|
|
||||||
xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml"
|
|
||||||
xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash"
|
|
||||||
xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex"
|
|
||||||
xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"
|
|
||||||
xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk"
|
|
||||||
xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"
|
|
||||||
xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
|
|
||||||
<w:body>
|
|
||||||
<w:p w14:paraId="2499FE9F" w14:textId="0A3D130F" w:rsidR="00B51233"
|
|
||||||
w:rsidRDefault="007B52ED" w:rsidP="007B52ED">
|
|
||||||
<w:pPr>
|
|
||||||
<w:pStyle w:val="Title" />
|
|
||||||
</w:pPr>
|
|
||||||
<w:r>
|
|
||||||
<w:t>Hello World</w:t>
|
|
||||||
</w:r>
|
|
||||||
</w:p>
|
|
||||||
<w:p w14:paraId="6410D9A0" w14:textId="7579AB49" w:rsidR="007B52ED"
|
|
||||||
w:rsidRDefault="007B52ED" />
|
|
||||||
<w:p w14:paraId="57ACF964" w14:textId="315D7A05" w:rsidR="007B52ED"
|
|
||||||
w:rsidRDefault="007B52ED">
|
|
||||||
<w:r>
|
|
||||||
<w:t>Hello {{name}},</w:t>
|
|
||||||
</w:r>
|
|
||||||
<w:r w:rsidR="008126CB">
|
|
||||||
<w:t xml:space="preserve"> how are you?</w:t>
|
|
||||||
</w:r>
|
|
||||||
</w:p>
|
|
||||||
<w:p w14:paraId="38C7DF4A" w14:textId="66CDEC9A" w:rsidR="007B52ED"
|
|
||||||
w:rsidRDefault="007B52ED" />
|
|
||||||
<w:p w14:paraId="04FABE2B" w14:textId="3DACA001" w:rsidR="007B52ED"
|
|
||||||
w:rsidRDefault="007B52ED">
|
|
||||||
<w:r>
|
|
||||||
<w:t>{{paragraph_replace}}</w:t>
|
|
||||||
</w:r>
|
|
||||||
</w:p>
|
|
||||||
<w:p w14:paraId="7AD7975D" w14:textId="77777777" w:rsidR="00EF161F"
|
|
||||||
w:rsidRDefault="00EF161F" />
|
|
||||||
<w:p w14:paraId="3BD6D75A" w14:textId="19AE3121" w:rsidR="00EF161F"
|
|
||||||
w:rsidRDefault="00EF161F">
|
|
||||||
<w:r>
|
|
||||||
<w:t>{{table}}</w:t>
|
|
||||||
</w:r>
|
|
||||||
</w:p>
|
|
||||||
<w:p w14:paraId="76023962" w14:textId="4E606AB9" w:rsidR="007B52ED"
|
|
||||||
w:rsidRDefault="007B52ED" />
|
|
||||||
<w:tbl>
|
|
||||||
<w:tblPr>
|
|
||||||
<w:tblStyle w:val="TableGrid" />
|
|
||||||
<w:tblW w:w="0" w:type="auto" />
|
|
||||||
<w:tblLook w:val="04A0" w:firstRow="1" w:lastRow="0" w:firstColumn="1"
|
|
||||||
w:lastColumn="0" w:noHBand="0" w:noVBand="1" />
|
|
||||||
</w:tblPr>
|
|
||||||
<w:tblGrid>
|
|
||||||
<w:gridCol w:w="3003" />
|
|
||||||
<w:gridCol w:w="3003" />
|
|
||||||
<w:gridCol w:w="3004" />
|
|
||||||
</w:tblGrid>
|
|
||||||
<w:tr w:rsidR="00EF161F" w14:paraId="1DEC5955" w14:textId="77777777" w:rsidTr="00EF161F">
|
|
||||||
<w:tc>
|
|
||||||
<w:tcPr>
|
|
||||||
<w:tcW w:w="3003" w:type="dxa" />
|
|
||||||
</w:tcPr>
|
|
||||||
<w:p w14:paraId="54DA5587" w14:textId="625BAC60" w:rsidR="00EF161F"
|
|
||||||
w:rsidRDefault="00EF161F">
|
|
||||||
<w:r>
|
|
||||||
<w:t>{{table_heading_1}}</w:t>
|
|
||||||
</w:r>
|
|
||||||
</w:p>
|
|
||||||
</w:tc>
|
|
||||||
<w:tc>
|
|
||||||
<w:tcPr>
|
|
||||||
<w:tcW w:w="3003" w:type="dxa" />
|
|
||||||
</w:tcPr>
|
|
||||||
<w:p w14:paraId="57100910" w14:textId="71FD5616" w:rsidR="00EF161F"
|
|
||||||
w:rsidRDefault="00EF161F" />
|
|
||||||
</w:tc>
|
|
||||||
<w:tc>
|
|
||||||
<w:tcPr>
|
|
||||||
<w:tcW w:w="3004" w:type="dxa" />
|
|
||||||
</w:tcPr>
|
|
||||||
<w:p w14:paraId="1D388FAB" w14:textId="77777777" w:rsidR="00EF161F"
|
|
||||||
w:rsidRDefault="00EF161F" />
|
|
||||||
</w:tc>
|
|
||||||
</w:tr>
|
|
||||||
<w:tr w:rsidR="00EF161F" w14:paraId="0F53D2DC" w14:textId="77777777" w:rsidTr="00EF161F">
|
|
||||||
<w:tc>
|
|
||||||
<w:tcPr>
|
|
||||||
<w:tcW w:w="3003" w:type="dxa" />
|
|
||||||
</w:tcPr>
|
|
||||||
<w:p w14:paraId="0F2BCCED" w14:textId="3C3B6706" w:rsidR="00EF161F"
|
|
||||||
w:rsidRDefault="00EF161F">
|
|
||||||
<w:r>
|
|
||||||
<w:t>Item: {{item_1}}</w:t>
|
|
||||||
</w:r>
|
|
||||||
</w:p>
|
|
||||||
</w:tc>
|
|
||||||
<w:tc>
|
|
||||||
<w:tcPr>
|
|
||||||
<w:tcW w:w="3003" w:type="dxa" />
|
|
||||||
</w:tcPr>
|
|
||||||
<w:p w14:paraId="1E6158AC" w14:textId="77777777" w:rsidR="00EF161F"
|
|
||||||
w:rsidRDefault="00EF161F" />
|
|
||||||
</w:tc>
|
|
||||||
<w:tc>
|
|
||||||
<w:tcPr>
|
|
||||||
<w:tcW w:w="3004" w:type="dxa" />
|
|
||||||
</w:tcPr>
|
|
||||||
<w:p w14:paraId="17937748" w14:textId="77777777" w:rsidR="00EF161F"
|
|
||||||
w:rsidRDefault="00EF161F" />
|
|
||||||
</w:tc>
|
|
||||||
</w:tr>
|
|
||||||
<w:tr w:rsidR="00EF161F" w14:paraId="781DAC1A" w14:textId="77777777" w:rsidTr="00EF161F">
|
|
||||||
<w:tc>
|
|
||||||
<w:tcPr>
|
|
||||||
<w:tcW w:w="3003" w:type="dxa" />
|
|
||||||
</w:tcPr>
|
|
||||||
<w:p w14:paraId="1DCD0343" w14:textId="77777777" w:rsidR="00EF161F"
|
|
||||||
w:rsidRDefault="00EF161F" />
|
|
||||||
</w:tc>
|
|
||||||
<w:tc>
|
|
||||||
<w:tcPr>
|
|
||||||
<w:tcW w:w="3003" w:type="dxa" />
|
|
||||||
</w:tcPr>
|
|
||||||
<w:p w14:paraId="5D02E3CD" w14:textId="77777777" w:rsidR="00EF161F"
|
|
||||||
w:rsidRDefault="00EF161F" />
|
|
||||||
</w:tc>
|
|
||||||
<w:tc>
|
|
||||||
<w:tcPr>
|
|
||||||
<w:tcW w:w="3004" w:type="dxa" />
|
|
||||||
</w:tcPr>
|
|
||||||
<w:p w14:paraId="52EA0DBB" w14:textId="77777777" w:rsidR="00EF161F"
|
|
||||||
w:rsidRDefault="00EF161F" />
|
|
||||||
</w:tc>
|
|
||||||
</w:tr>
|
|
||||||
</w:tbl>
|
|
||||||
<w:p w14:paraId="47CD1FBC" w14:textId="23474CBC" w:rsidR="007B52ED"
|
|
||||||
w:rsidRDefault="007B52ED" />
|
|
||||||
<w:p w14:paraId="0ACCEE90" w14:textId="67907499" w:rsidR="00EF161F"
|
|
||||||
w:rsidRDefault="0077578F">
|
|
||||||
<w:r>
|
|
||||||
<w:t>{{image_test}}</w:t>
|
|
||||||
</w:r>
|
|
||||||
</w:p>
|
|
||||||
<w:p w14:paraId="23FA9862" w14:textId="77777777" w:rsidR="0077578F"
|
|
||||||
w:rsidRDefault="0077578F" />
|
|
||||||
<w:p w14:paraId="01578F2F" w14:textId="3BDC6C85" w:rsidR="007B52ED"
|
|
||||||
w:rsidRDefault="007B52ED">
|
|
||||||
<w:r>
|
|
||||||
<w:t>Thank you</w:t>
|
|
||||||
</w:r>
|
|
||||||
</w:p>
|
|
||||||
<w:sectPr w:rsidR="007B52ED" w:rsidSect="0072043F">
|
|
||||||
<w:headerReference w:type="default" r:id="rId6" />
|
|
||||||
<w:footerReference w:type="default" r:id="rId7" />
|
|
||||||
<w:pgSz w:w="11900" w:h="16840" />
|
|
||||||
<w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="708"
|
|
||||||
w:footer="708" w:gutter="0" />
|
|
||||||
<w:cols w:space="708" />
|
|
||||||
<w:docGrid w:linePitch="360" />
|
|
||||||
</w:sectPr>
|
|
||||||
</w:body>
|
|
||||||
</w:document>
|
|
||||||
`;
|
|
||||||
|
|
||||||
describe("patch-detector", () => {
|
|
||||||
describe("patchDetector", () => {
|
|
||||||
describe("document.xml and [Content_Types].xml", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
vi.spyOn(JSZip, "loadAsync").mockReturnValue(
|
|
||||||
new Promise<JSZip>((resolve) => {
|
|
||||||
const zip = new JSZip();
|
|
||||||
|
|
||||||
zip.file("word/document.xml", MOCK_XML);
|
|
||||||
zip.file("[Content_Types].xml", `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>`);
|
|
||||||
resolve(zip);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
vi.restoreAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should patch the document", async () => {
|
|
||||||
const output = await patchDetector({
|
|
||||||
data: Buffer.from(""),
|
|
||||||
});
|
|
||||||
expect(output).toMatchObject(["name", "paragraph_replace", "table", "image_test", "table_heading_1", "item_1"]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,30 +0,0 @@
|
|||||||
import JSZip from "jszip";
|
|
||||||
import { toJson } from "./util";
|
|
||||||
import { traverse } from "./traverser";
|
|
||||||
import { InputDataType } from "./from-docx";
|
|
||||||
|
|
||||||
type PatchDetectorOptions = {
|
|
||||||
readonly data: InputDataType;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Detects which patches are needed/present in a template */
|
|
||||||
export const patchDetector = async ({ data }: PatchDetectorOptions): Promise<readonly string[]> => {
|
|
||||||
const zipContent = await JSZip.loadAsync(data);
|
|
||||||
const patches = new Set<string>();
|
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(zipContent.files)) {
|
|
||||||
if (!key.endsWith(".xml") && !key.endsWith(".rels")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (key.startsWith("word/") && !key.endsWith(".xml.rels")) {
|
|
||||||
const json = toJson(await value.async("text"));
|
|
||||||
traverse(json).forEach((p) => findPatchKeys(p.text).forEach((patch) => patches.add(patch)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Array.from(patches);
|
|
||||||
};
|
|
||||||
|
|
||||||
const findPatchKeys = (text: string): readonly string[] => {
|
|
||||||
const pattern = /(?<=\{\{).+?(?=\}\})/gs;
|
|
||||||
return text.match(pattern) ?? [];
|
|
||||||
};
|
|
@ -15,7 +15,7 @@ const elementsToWrapper = (wrapper: ElementWrapper): readonly ElementWrapper[] =
|
|||||||
parent: wrapper,
|
parent: wrapper,
|
||||||
})) ?? [];
|
})) ?? [];
|
||||||
|
|
||||||
export const traverse = (node: Element): readonly IRenderedParagraphNode[] => {
|
export const findLocationOfText = (node: Element, text: string): readonly IRenderedParagraphNode[] => {
|
||||||
let renderedParagraphs: readonly IRenderedParagraphNode[] = [];
|
let renderedParagraphs: readonly IRenderedParagraphNode[] = [];
|
||||||
|
|
||||||
// eslint-disable-next-line functional/prefer-readonly-type
|
// eslint-disable-next-line functional/prefer-readonly-type
|
||||||
@ -41,8 +41,5 @@ export const traverse = (node: Element): readonly IRenderedParagraphNode[] => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return renderedParagraphs;
|
return renderedParagraphs.filter((p) => p.text.includes(text));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const findLocationOfText = (node: Element, text: string): readonly IRenderedParagraphNode[] =>
|
|
||||||
traverse(node).filter((p) => p.text.includes(text));
|
|
||||||
|
@ -7,9 +7,7 @@ import { nodePolyfills } from "vite-plugin-node-polyfills";
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
tsconfigPaths(),
|
tsconfigPaths(),
|
||||||
dts({
|
dts(),
|
||||||
rollupTypes: true
|
|
||||||
}),
|
|
||||||
nodePolyfills({
|
nodePolyfills({
|
||||||
exclude: [],
|
exclude: [],
|
||||||
globals: {
|
globals: {
|
||||||
|
Reference in New Issue
Block a user