diff --git a/package-lock.json b/package-lock.json index a423e4086e..2b05e26f7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "docx", - "version": "8.0.3", + "version": "8.0.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "docx", - "version": "8.0.3", + "version": "8.0.4", "license": "MIT", "dependencies": { "@types/node": "^18.0.0", diff --git a/package.json b/package.json index 842d6c7591..9860f519dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "docx", - "version": "8.0.3", + "version": "8.0.4", "description": "Easily generate .docx files with JS/TS with a nice declarative API. Works for Node and on the Browser.", "type": "module", "main": "build/index.umd.cjs", diff --git a/src/file/drawing/anchor/anchor.spec.ts b/src/file/drawing/anchor/anchor.spec.ts index b6a368b4e6..64e628546e 100644 --- a/src/file/drawing/anchor/anchor.spec.ts +++ b/src/file/drawing/anchor/anchor.spec.ts @@ -1,8 +1,6 @@ import { assert, expect } from "chai"; -import { SinonStub, stub } from "sinon"; import { Formatter } from "@export/formatter"; -import * as convenienceFunctions from "@util/convenience-functions"; import { Utility } from "tests/utility"; @@ -40,14 +38,6 @@ const createAnchor = (drawingOptions: IDrawingOptions): Anchor => ); describe("Anchor", () => { - before(() => { - stub(convenienceFunctions, "docPropertiesUniqueNumericId").callsFake(() => 0); - }); - - after(() => { - (convenienceFunctions.docPropertiesUniqueNumericId as SinonStub).restore(); - }); - let anchor: Anchor; describe("#constructor()", () => { @@ -466,7 +456,7 @@ describe("Anchor", () => { "wp:docPr": { _attr: { descr: "test", - id: 0, + id: 1, name: "test", title: "test", }, diff --git a/src/file/drawing/doc-properties/doc-properties.ts b/src/file/drawing/doc-properties/doc-properties.ts index 8b0093c7f1..5df1497bb5 100644 --- a/src/file/drawing/doc-properties/doc-properties.ts +++ b/src/file/drawing/doc-properties/doc-properties.ts @@ -2,7 +2,7 @@ import { IContext, IXmlableObject, NextAttributeComponent, XmlComponent } from "@file/xml-components"; import { ConcreteHyperlink } from "@file/paragraph"; -import { docPropertiesUniqueNumericId } from "@util/convenience-functions"; +import { docPropertiesUniqueNumericIdGen } from "@util/convenience-functions"; import { createHyperlinkClick } from "./doc-properties-children"; @@ -25,6 +25,8 @@ export interface DocPropertiesOptions { } export class DocProperties extends XmlComponent { + private readonly docPropertiesUniqueNumericId = docPropertiesUniqueNumericIdGen(); + public constructor({ name, description, title }: DocPropertiesOptions = { name: "", description: "", title: "" }) { super("wp:docPr"); @@ -32,7 +34,7 @@ export class DocProperties extends XmlComponent { new NextAttributeComponent({ id: { key: "id", - value: docPropertiesUniqueNumericId(), + value: this.docPropertiesUniqueNumericId(), }, name: { key: "name", diff --git a/src/file/drawing/drawing.spec.ts b/src/file/drawing/drawing.spec.ts index 8850881159..c36f3e77ec 100644 --- a/src/file/drawing/drawing.spec.ts +++ b/src/file/drawing/drawing.spec.ts @@ -1,9 +1,7 @@ import { expect } from "chai"; -import { SinonStub, stub } from "sinon"; import { IContext } from "@file/xml-components"; import { Formatter } from "@export/formatter"; -import * as convenienceFunctions from "@util/convenience-functions"; import { ConcreteHyperlink, TextRun } from "../"; import { Drawing, IDrawingOptions } from "./drawing"; @@ -30,14 +28,6 @@ const createDrawing = (drawingOptions?: IDrawingOptions): Drawing => ); describe("Drawing", () => { - before(() => { - stub(convenienceFunctions, "docPropertiesUniqueNumericId").callsFake(() => 0); - }); - - after(() => { - (convenienceFunctions.docPropertiesUniqueNumericId as SinonStub).restore(); - }); - let currentBreak: Drawing; describe("#constructor()", () => { @@ -78,7 +68,7 @@ describe("Drawing", () => { "wp:docPr": { _attr: { descr: "", - id: 0, + id: 1, name: "", title: "", }, @@ -309,7 +299,7 @@ describe("Drawing", () => { "wp:docPr": { _attr: { descr: "", - id: 0, + id: 1, name: "", title: "", }, @@ -543,7 +533,7 @@ describe("Drawing", () => { { _attr: { descr: "", - id: 0, + id: 1, name: "", title: "", }, diff --git a/src/file/numbering/numbering.spec.ts b/src/file/numbering/numbering.spec.ts index 13f1b9afe6..056d4bd356 100644 --- a/src/file/numbering/numbering.spec.ts +++ b/src/file/numbering/numbering.spec.ts @@ -1,22 +1,10 @@ import { expect } from "chai"; -import { SinonStub, stub } from "sinon"; import { Formatter } from "@export/formatter"; -import * as convenienceFunctions from "@util/convenience-functions"; import { Numbering } from "./numbering"; describe("Numbering", () => { - before(() => { - stub(convenienceFunctions, "abstractNumUniqueNumericId").callsFake(() => 0); - stub(convenienceFunctions, "concreteNumUniqueNumericId").callsFake(() => 0); - }); - - after(() => { - (convenienceFunctions.abstractNumUniqueNumericId as SinonStub).restore(); - (convenienceFunctions.concreteNumUniqueNumericId as SinonStub).restore(); - }); - describe("#constructor", () => { it("creates a default numbering with one abstract and one concrete instance", () => { const numbering = new Numbering({ @@ -29,7 +17,7 @@ describe("Numbering", () => { const abstractNums: readonly any[] = tree["w:numbering"].filter((el: any) => el["w:abstractNum"]); expect(abstractNums).to.have.lengthOf(1); expect(abstractNums[0]["w:abstractNum"]).to.deep.include.members([ - { _attr: { "w:abstractNumId": 0, "w15:restartNumberingAfterBreak": 0 } }, + { _attr: { "w:abstractNumId": 1, "w15:restartNumberingAfterBreak": 0 } }, { "w:multiLevelType": { _attr: { "w:val": "hybridMultilevel" } } }, ]); diff --git a/src/file/numbering/numbering.ts b/src/file/numbering/numbering.ts index 272686ca8a..242c399795 100644 --- a/src/file/numbering/numbering.ts +++ b/src/file/numbering/numbering.ts @@ -2,7 +2,7 @@ // https://stackoverflow.com/questions/58622437/purpose-of-abstractnum-and-numberinginstance import { AlignmentType } from "@file/paragraph"; import { IContext, IXmlableObject, XmlComponent } from "@file/xml-components"; -import { abstractNumUniqueNumericId, concreteNumUniqueNumericId, convertInchesToTwip } from "@util/convenience-functions"; +import { abstractNumUniqueNumericIdGen, concreteNumUniqueNumericIdGen, convertInchesToTwip } from "@util/convenience-functions"; import { DocumentAttributes } from "../document/document-attributes"; import { AbstractNumbering } from "./abstract-numbering"; @@ -31,6 +31,8 @@ export class Numbering extends XmlComponent { private readonly concreteNumberingMap = new Map(); // eslint-disable-next-line @typescript-eslint/no-explicit-any private readonly referenceConfigMap = new Map>(); + private readonly abstractNumUniqueNumericId = abstractNumUniqueNumericIdGen(); + private readonly concreteNumUniqueNumericId = concreteNumUniqueNumericIdGen(); public constructor(options: INumberingOptions) { super("w:numbering"); @@ -56,7 +58,7 @@ export class Numbering extends XmlComponent { }), ); - const abstractNumbering = new AbstractNumbering(abstractNumUniqueNumericId(), [ + const abstractNumbering = new AbstractNumbering(this.abstractNumUniqueNumericId(), [ { level: 0, format: LevelFormat.BULLET, @@ -177,7 +179,7 @@ export class Numbering extends XmlComponent { this.abstractNumberingMap.set("default-bullet-numbering", abstractNumbering); for (const con of options.config) { - this.abstractNumberingMap.set(con.reference, new AbstractNumbering(abstractNumUniqueNumericId(), con.levels)); + this.abstractNumberingMap.set(con.reference, new AbstractNumbering(this.abstractNumUniqueNumericId(), con.levels)); this.referenceConfigMap.set(con.reference, con.levels); } } @@ -210,7 +212,7 @@ export class Numbering extends XmlComponent { const firstLevelStartNumber = referenceConfigLevels && referenceConfigLevels[0].start; const concreteNumberingSettings = { - numId: concreteNumUniqueNumericId(), + numId: this.concreteNumUniqueNumericId(), abstractNumId: abstractNumbering.id, reference, instance, diff --git a/src/file/paragraph/links/bookmark.ts b/src/file/paragraph/links/bookmark.ts index 8bb7c9b5ed..c6082b7d3d 100644 --- a/src/file/paragraph/links/bookmark.ts +++ b/src/file/paragraph/links/bookmark.ts @@ -1,17 +1,19 @@ // http://officeopenxml.com/WPbookmark.php import { XmlComponent } from "@file/xml-components"; -import { bookmarkUniqueNumericId } from "@util/convenience-functions"; +import { bookmarkUniqueNumericIdGen } from "@util/convenience-functions"; import { ParagraphChild } from "../paragraph"; import { BookmarkEndAttributes, BookmarkStartAttributes } from "./bookmark-attributes"; export class Bookmark { + private readonly bookmarkUniqueNumericId = bookmarkUniqueNumericIdGen(); + public readonly start: BookmarkStart; public readonly children: readonly ParagraphChild[]; public readonly end: BookmarkEnd; public constructor(options: { readonly id: string; readonly children: readonly ParagraphChild[] }) { - const linkId = bookmarkUniqueNumericId(); + const linkId = this.bookmarkUniqueNumericId(); this.start = new BookmarkStart(options.id, linkId); this.children = options.children; diff --git a/src/file/paragraph/paragraph.spec.ts b/src/file/paragraph/paragraph.spec.ts index 7d21b5d171..8f7ed03801 100644 --- a/src/file/paragraph/paragraph.spec.ts +++ b/src/file/paragraph/paragraph.spec.ts @@ -20,12 +20,12 @@ import { TextRun } from "./run"; describe("Paragraph", () => { before(() => { stub(convenienceFunctions, "uniqueId").callsFake(() => "test-unique-id"); - stub(convenienceFunctions, "bookmarkUniqueNumericId").callsFake(() => -101); + stub(convenienceFunctions, "bookmarkUniqueNumericIdGen").callsFake(() => () => -101); }); after(() => { (convenienceFunctions.uniqueId as SinonStub).restore(); - (convenienceFunctions.bookmarkUniqueNumericId as SinonStub).restore(); + (convenienceFunctions.bookmarkUniqueNumericIdGen as SinonStub).restore(); }); describe("#constructor()", () => { diff --git a/src/file/paragraph/run/image-run.spec.ts b/src/file/paragraph/run/image-run.spec.ts index 9e9ad89505..2dc3cd2557 100644 --- a/src/file/paragraph/run/image-run.spec.ts +++ b/src/file/paragraph/run/image-run.spec.ts @@ -11,12 +11,10 @@ import { ImageRun } from "./image-run"; describe("ImageRun", () => { before(() => { stub(convenienceFunctions, "uniqueId").callsFake(() => "test-unique-id"); - stub(convenienceFunctions, "docPropertiesUniqueNumericId").callsFake(() => 0); }); after(() => { (convenienceFunctions.uniqueId as SinonStub).restore(); - (convenienceFunctions.docPropertiesUniqueNumericId as SinonStub).restore(); }); describe("#constructor()", () => { @@ -126,7 +124,7 @@ describe("ImageRun", () => { "wp:docPr": { _attr: { descr: "", - id: 0, + id: 1, name: "", title: "", }, @@ -378,7 +376,7 @@ describe("ImageRun", () => { "wp:docPr": { _attr: { descr: "", - id: 0, + id: 1, name: "", title: "", }, @@ -634,7 +632,7 @@ describe("ImageRun", () => { "wp:docPr": { _attr: { descr: "", - id: 0, + id: 1, name: "", title: "", }, @@ -893,7 +891,7 @@ describe("ImageRun", () => { "wp:docPr": { _attr: { descr: "", - id: 0, + id: 1, name: "", title: "", }, diff --git a/src/util/convenience-functions.ts b/src/util/convenience-functions.ts index 543b6e9c7c..b6683b0d15 100644 --- a/src/util/convenience-functions.ts +++ b/src/util/convenience-functions.ts @@ -5,15 +5,21 @@ export const convertMillimetersToTwip = (millimeters: number): number => Math.fl export const convertInchesToTwip = (inches: number): number => Math.floor(inches * 72 * 20); -export const uniqueNumericIdCreator = (initial = 0): (() => number) => { +export type UniqueNumericIdCreator = () => number; + +export const uniqueNumericIdCreator = (initial = 0): UniqueNumericIdCreator => { let currentCount = initial; return () => ++currentCount; }; -export const abstractNumUniqueNumericId = uniqueNumericIdCreator(); -export const concreteNumUniqueNumericId = uniqueNumericIdCreator(1); // Setting initial to 1 as we have numId = 1 for "default-bullet-numbering" -export const docPropertiesUniqueNumericId = uniqueNumericIdCreator(); -export const bookmarkUniqueNumericId = uniqueNumericIdCreator(); +export const abstractNumUniqueNumericIdGen = (): UniqueNumericIdCreator => uniqueNumericIdCreator(); + +// Setting initial to 1 as we have numId = 1 for "default-bullet-numbering" +export const concreteNumUniqueNumericIdGen = (): UniqueNumericIdCreator => uniqueNumericIdCreator(1); + +export const docPropertiesUniqueNumericIdGen = (): UniqueNumericIdCreator => uniqueNumericIdCreator(); + +export const bookmarkUniqueNumericIdGen = (): UniqueNumericIdCreator => uniqueNumericIdCreator(); export const uniqueId = (): string => nanoid().toLowerCase();