diff --git a/demo/21-bookmarks.ts b/demo/21-bookmarks.ts index 5455ee8875..decb882be0 100644 --- a/demo/21-bookmarks.ts +++ b/demo/21-bookmarks.ts @@ -1,7 +1,7 @@ // This demo shows how to create bookmarks then link to them with internal hyperlinks // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Bookmark, Document, Footer, HeadingLevel, InternalHyperlink, Packer, PageBreak, Paragraph, TextRun } from "../build"; +import { Bookmark, Document, Footer, HeadingLevel, InternalHyperlink, Packer, PageBreak, Paragraph, TextRun, PageReference } from "../build"; const LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam mi velit, convallis convallis scelerisque nec, faucibus nec leo. Phasellus at posuere mauris, tempus dignissim velit. Integer et tortor dolor. Duis auctor efficitur mattis. Vivamus ut metus accumsan tellus auctor sollicitudin venenatis et nibh. Cras quis massa ac metus fringilla venenatis. Proin rutrum mauris purus, ut suscipit magna consectetur id. Integer consectetur sollicitudin ante, vitae faucibus neque efficitur in. Praesent ultricies nibh lectus. Mauris pharetra id odio eget iaculis. Duis dictum, risus id pellentesque rutrum, lorem quam malesuada massa, quis ullamcorper turpis urna a diam. Cras vulputate metus vel massa porta ullamcorper. Etiam porta condimentum nulla nec tristique. Sed nulla urna, pharetra non tortor sed, sollicitudin molestie diam. Maecenas enim leo, feugiat eget vehicula id, sollicitudin vitae ante."; @@ -18,10 +18,12 @@ const doc = new Document({ new Paragraph({ children: [ new InternalHyperlink({ - child: new TextRun({ - text: "Click here!", - style: "Hyperlink", - }), + children: [ + new TextRun({ + text: "Click here!", + style: "Hyperlink", + }), + ], anchor: "myAnchorId", }), ], @@ -47,14 +49,24 @@ const doc = new Document({ new Paragraph({ children: [ new InternalHyperlink({ - child: new TextRun({ - text: "Anchor Text", - style: "Hyperlink", - }), + children: [ + new TextRun({ + text: "Styled", + bold: true, + style: "Hyperlink", + }), + new TextRun({ + text: " Anchor Text", + style: "Hyperlink", + }), + ], anchor: "myAnchorId", }), ], }), + new Paragraph({ + children: [new TextRun("The bookmark can be seen on page "), new PageReference("myAnchorId")], + }), ], }, ], diff --git a/demo/35-hyperlinks.ts b/demo/35-hyperlinks.ts index f8aca4f622..6039e6f443 100644 --- a/demo/35-hyperlinks.ts +++ b/demo/35-hyperlinks.ts @@ -11,10 +11,12 @@ const doc = new Document({ children: [ new TextRun("Click here for the "), new ExternalHyperlink({ - child: new TextRun({ - text: "Footnotes external hyperlink", - style: "Hyperlink", - }), + children: [ + new TextRun({ + text: "Footnotes external hyperlink", + style: "Hyperlink", + }), + ], link: "http://www.example.com", }), ], @@ -31,10 +33,12 @@ const doc = new Document({ children: [ new TextRun("Click here for the "), new ExternalHyperlink({ - child: new TextRun({ - text: "Footer external hyperlink", - style: "Hyperlink", - }), + children: [ + new TextRun({ + text: "Footer external hyperlink", + style: "Hyperlink", + }), + ], link: "http://www.example.com", }), ], @@ -49,10 +53,12 @@ const doc = new Document({ children: [ new TextRun("Click here for the "), new ExternalHyperlink({ - child: new TextRun({ - text: "Header external hyperlink", - style: "Hyperlink", - }), + children: [ + new TextRun({ + text: "Header external hyperlink", + style: "Hyperlink", + }), + ], link: "http://www.google.com", }), ], @@ -64,10 +70,12 @@ const doc = new Document({ new Paragraph({ children: [ new ExternalHyperlink({ - child: new TextRun({ - text: "Anchor Text", - style: "Hyperlink", - }), + children: [ + new TextRun({ + text: "Anchor Text", + style: "Hyperlink", + }), + ], link: "http://www.example.com", }), new FootnoteReferenceRun(1), @@ -76,24 +84,63 @@ const doc = new Document({ new Paragraph({ children: [ new ExternalHyperlink({ - child: new ImageRun({ - data: fs.readFileSync("./demo/images/image1.jpeg"), - transformation: { - width: 100, - height: 100, - }, - }), + children: [ + new ImageRun({ + data: fs.readFileSync("./demo/images/image1.jpeg"), + transformation: { + width: 100, + height: 100, + }, + }), + ], link: "http://www.google.com", }), new ExternalHyperlink({ - child: new TextRun({ - text: "BBC News Link", - style: "Hyperlink", - }), + children: [ + new TextRun({ + text: "BBC News Link", + style: "Hyperlink", + }), + ], link: "https://www.bbc.co.uk/news", }), ], }), + new Paragraph({ + children: [ + new TextRun({ + text: "This is a hyperlink with formatting: ", + }), + new ExternalHyperlink({ + children: [ + new TextRun({ + text: "A ", + style: "Hyperlink", + }), + new TextRun({ + text: "single ", + bold: true, + style: "Hyperlink", + }), + new TextRun({ + text: "link", + doubleStrike: true, + style: "Hyperlink", + }), + new TextRun({ + text: "1", + superScript: true, + style: "Hyperlink", + }), + new TextRun({ + text: "!", + style: "Hyperlink", + }), + ], + link: "http://www.example.com", + }), + ], + }), ], }, ], diff --git a/demo/68-numbering-instances-and-starting-number.ts b/demo/68-numbering-instances-and-starting-number.ts new file mode 100644 index 0000000000..6bfda02e96 --- /dev/null +++ b/demo/68-numbering-instances-and-starting-number.ts @@ -0,0 +1,86 @@ +import * as fs from "fs"; +import { Document, Packer, Paragraph, PageNumberFormat} from "../build"; + +const doc = new Document({ + numbering:{ + config:[ + { + reference: 'ref1', + levels: [ + { + level: 0, + format: PageNumberFormat.DECIMAL, + text: '%1', + start: 10, + } + ], + }, + { + reference: 'ref2', + levels: [ + { + level: 0, + format: PageNumberFormat.DECIMAL, + text: '%1' + } + ], + }, + ] + }, + sections: [{ + children: [ + new Paragraph({ + text: "REF1 - inst:0 - lvl:0", + numbering : { + reference: 'ref1', + instance: 0, + level: 0, + } + }), + new Paragraph({ + text: "REF1 - inst:0 - lvl:0", + numbering : { + reference: 'ref1', + instance: 0, + level: 0, + } + }), + new Paragraph({ + text: "REF1 - inst:1 - lvl:0", + numbering : { + reference: 'ref1', + instance: 1, + level: 0, + }, + }), + new Paragraph({ + text: "REF1 - inst:1 - lvl:0", + numbering : { + reference: 'ref1', + instance: 1, + level: 0, + } + }), + new Paragraph({ + text: "REF2 - inst:0 - lvl:0", + numbering : { + reference: 'ref2', + instance: 1, + level: 0, + } + }), + new Paragraph({ + text: "REF2 - inst:0 - lvl:0", + numbering : { + reference: 'ref2', + instance: 1, + level: 0, + } + }) + ], + }] +}); + +Packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 64a6a85225..6e06856207 100644 --- a/docs/README.md +++ b/docs/README.md @@ -44,7 +44,7 @@ const doc = new Document({ ], }), ], - }]; + }], }); // Used to export the file into a .docx file diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 7fa4e9f745..356f64239a 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -15,6 +15,7 @@ * [Image](usage/images.md) * [Headers & Footers](usage/headers-and-footers.md) * [Bullet Points](usage/bullet-points.md) + * [Hyperlinks](usage/hyperlinks.md) * [Numbering](usage/numbering.md) * [Tables](usage/tables.md) * [Tab Stops](usage/tab-stops.md) diff --git a/docs/usage/hyperlinks.md b/docs/usage/hyperlinks.md index 82bfb366f9..1d7c1355d5 100644 --- a/docs/usage/hyperlinks.md +++ b/docs/usage/hyperlinks.md @@ -1,47 +1,98 @@ # Hyperlinks +!> Hyperlinks require an understanding of [Paragraphs](usage/paragraph.md) and [Text](usage/text.md). + There are two types of hyperlinks: internal (pointing to a bookmark inside the document) and external (pointing to an external url). ## Internal -To create an internal hyperlink you need first to create a bookmark (the paragraph that will be the destination of the hyperlink) with `doc.createBookmark(anchor, text)`. +To create an internal hyperlink you need first to create a `Bookmark`, which contains the content that will be the destination of the hyperlink. -A bookmark is composed of an anchor (an identifier) and the text displayed. After creating a bookmark just add it to a paragraph with `paragraph.addBookmark(bookmark)` - -For example: +A bookmark is composed of an anchor (an identifier) and the text displayed. After creating a bookmark just add it to a paragraph. For example, creating a bookmarked heading: ```ts -const paragraph = this.doc.createParagraph(); -const bookmark = this.doc.createBookmark('anchorForChapter1', 'This is chapter1'); -paragraph.addBookmark(bookmark); +const chapter1 = new Paragraph({ + heading: HeadingLevel.HEADING_1, + children: [ + new Bookmark({ + id: "anchorForChapter1", + children: [ + new TextRun("Chapter 1"), + ], + }), + ], +}) ``` -Then you can create an hyperlink pointing to that bookmark with `doc.createInternalHyperLink(anchor,text)`: +Then you can create an hyperlink pointing to that bookmark with an `InternalHyperLink`: ```ts -const paragraph = this.doc.createParagraph(); -const link = this.doc.createInternalHyperLink('anchorForChapter1', 'This is a link to chapter1'); -paragraph.addHyperLink(link); +const link = new InternalHyperlink({ + children: [ + new TextRun({ + text: "See Chapter 1", + style: "Hyperlink", + }), + ], + anchor: "anchorForChapter1", +}) +``` + +You can also get the page number of the bookmark by creating a page reference to it: + +```ts +const paragraph = new Paragraph({ + children: [ + new TextRun("Chapter 1 can be seen on page "), + new PageReference("anchorForChapter1"), + ], +}); ``` ## External -To create an external hyperlink you just need to specify the url and the text of the link, then add it to a paragraph with `doc.createHyperlink(url, text)`: +To create an external hyperlink you just need to specify the url and the text of the link, then add it to a paragraph: ```ts -const paragraph = this.doc.createParagraph(); -const link = this.doc.createHyperlink('https://docx.js.org', 'This is an external link'); -paragraph.addHyperLink(link); +const paragraph = new Paragraph({ + children: [ + new ExternalHyperlink({ + children: [ + new TextRun({ + text: "This is an external link!", + style: "Hyperlink", + }), + ], + link: "https://docx.js.org", + }), + ], +}); ``` -## Styling an hyperlink +## Styling hyperlinks -It is possible to set the style of the text of an hyperlink. This can be done applying run formatting on `TextRun` property of the hyperlink. +It is possible to set the style of the text of both internal and external hyperlinks. This can be done applying run formatting on any of the `TextRun` children of the hyperlink. Use the `style: "Hyperlink"` property to show the default link styles, which can be combined with any other style. Example: ```ts -const link = this.doc.createHyperlink('https://docx.js.org', 'This is an external link'); -link.TextRun.bold().italics() +const styledLink = new ExternalHyperlink({ + children: [ + new TextRun({ + text: "This is a ", + style: "Hyperlink", + }), + new TextRun({ + text: "bold", + bold: true, + style: "Hyperlink", + }), + new TextRun({ + text: " link!", + style: "Hyperlink", + }), + ], + link: "https://docx.js.org", +}); ``` diff --git a/docs/usage/tab-stops.md b/docs/usage/tab-stops.md index 23b13905cb..5c859a1bac 100644 --- a/docs/usage/tab-stops.md +++ b/docs/usage/tab-stops.md @@ -4,15 +4,15 @@ !> **Note**: The unit of measurement for a tab stop is in [DXA](https://stackoverflow.com/questions/14360183/default-wordml-unit-measurement-pixel-or-point-or-inches) -![Word 2013 Tabs](http://www.teachucomp.com/wp-content/uploads/blog-4-22-2015-UsingTabStopsInWord-1024x577.png "Word 2013 Tab Stops") +![Word 2013 Tabs](https://support.content.office.net/en-us/media/d75ca75d-9fe9-4d46-9a8b-4534c13acbc5.png "Word 2013 Tab Stops") -Simply call the relevant methods on the paragraph listed below. Then just add a `tab()` method call to a text object. Adding multiple `tabStops` will mean you would have to chain `tab()` until the desired `tabStop` is selected. Example is shown below. +Simply declare the tab stops on the paragraph, as shown below. Use the tab character `\t` to indicate the tab position within the `text` property of a `TextRun`. Adding multiple `tabStops` will mean you can add additional `\t` characters until the desired `tabStop` is selected. Example is shown below. ## Example ```ts const paragraph = new Paragraph({ - children: [new TextRun("Hey everyone").bold(), new TextRun(\t"11th November 1999")], + children: [new TextRun({ text: "Hey everyone", bold: true}), new TextRun("\t11th November 1999")], tabStops: [ { type: TabStopType.RIGHT, @@ -26,7 +26,7 @@ The example above will create a left aligned text, and a right aligned text on t ```ts const paragraph = new Paragraph({ - children: [new TextRun("Second tab stop here I come!")], + children: [new TextRun("\t\tSecond tab stop here I come!")], tabStops: [ { type: TabStopType.RIGHT, @@ -46,7 +46,7 @@ You can add multiple tab stops of the same `type` too. ```ts const paragraph = new Paragraph({ - children: [new TextRun("Multiple tab stops!")], + children: [new TextRun("Multiple \ttab \tstops!")], tabStops: [ { type: TabStopType.RIGHT, diff --git a/docs/usage/tables.md b/docs/usage/tables.md index a13b7f5a02..aba2e35c6f 100644 --- a/docs/usage/tables.md +++ b/docs/usage/tables.md @@ -242,12 +242,12 @@ const cell = new TableCell({ `WidthType` values can be: -| Property | Notes | -| -------- | --------------------------------- | -| AUTO | | -| DXA | value is in twentieths of a point | -| NIL | is considered as zero | -| PCT | percent of table width | +| Property | Notes | +| ---------- | --------------------------------- | +| AUTO | | +| DXA | Value is in twentieths of a point | +| NIL | Is considered as zero | +| PERCENTAGE | Percent of table width | ### Nested Tables diff --git a/package-lock.json b/package-lock.json index 7b9bb14b34..bc528fa5cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -485,9 +485,9 @@ } }, "@sinonjs/fake-timers": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.0.4.tgz", - "integrity": "sha512-fW3SzjLF0sjI0x1Opc7cUG4J/Nr4U0TXPNnKNAgrxA4xXsQNk6nypZK0yJg5FNw5cCo2yC/ZMdaVhDTKeeF6zg==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", + "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.0" @@ -578,9 +578,15 @@ "dev": true }, "@types/json-schema": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", - "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, "@types/jszip": { @@ -598,9 +604,9 @@ "dev": true }, "@types/node": { - "version": "16.4.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.1.tgz", - "integrity": "sha512-UW7cbLqf/Wu5XH2RKKY1cHwUNLicIDRLMraYKz+HHAerJ0ZffUEk+fMnd8qU2JaS6cAy0r8tsaf7yqHASf/Y0Q==" + "version": "16.7.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.13.tgz", + "integrity": "sha512-pLUPDn+YG3FYEt/pHI74HmnJOWzeR+tOIQzUx93pi9M7D8OE7PSLr97HboXwk5F+JS+TLtWuzCOW97AHjmOXXA==" }, "@types/request": { "version": "2.48.6", @@ -842,9 +848,9 @@ } }, "@webpack-cli/serve": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.5.1.tgz", - "integrity": "sha512-4vSVUiOPJLmr45S8rMGy7WDvpWxfFxfP/Qx/cxZFCfvoypTYpPPL1X8VIZMe0WTA+Jr7blUxwUSEZNkjoMTgSw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.5.2.tgz", + "integrity": "sha512-vgJ5OLWadI8aKjDlOH3rb+dYyPd2GTZuQC/Tihjct6F9GpXGZINo3Y/IVuZVTM1eDQB+/AOsjPUWH/WySDaXvw==", "dev": true }, "@xtuc/ieee754": { @@ -860,9 +866,15 @@ "dev": true }, "acorn": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", - "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", + "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", + "dev": true + }, + "acorn-import-assertions": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.7.6.tgz", + "integrity": "sha512-FlVvVFA1TX6l3lp8VjDnYYq7R1nyW6x3svAt4nDgrWQ9SBaSh9CnbwgSUTasgfNfOG5HlM1ehugCvM+hjo56LA==", "dev": true }, "aggregate-error": { @@ -1206,16 +1218,24 @@ "dev": true }, "browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.0.tgz", + "integrity": "sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", + "caniuse-lite": "^1.0.30001254", + "colorette": "^1.3.0", + "electron-to-chromium": "^1.3.830", "escalade": "^3.1.1", - "node-releases": "^1.1.71" + "node-releases": "^1.1.75" + }, + "dependencies": { + "colorette": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", + "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", + "dev": true + } } }, "buffer": { @@ -1305,9 +1325,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001246", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001246.tgz", - "integrity": "sha512-Tc+ff0Co/nFNbLOrziBXmMVtpt9S2c2Y+Z9Nk9Khj09J+0zR9ejvIW5qkZAErCbOrVODCx/MN+GpB5FNBs5GFA==", + "version": "1.0.30001255", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001255.tgz", + "integrity": "sha512-F+A3N9jTZL882f/fg/WWVnKSu6IOo3ueLz4zwaOPbPYHNmM/ZaDUyzyJwS1mZhX7Ex5jqTyW599Gdelh5PDYLQ==", "dev": true }, "caseless": { @@ -1643,12 +1663,6 @@ } } }, - "deep-equal": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.2.tgz", - "integrity": "sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0=", - "dev": true - }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -1934,9 +1948,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.784", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.784.tgz", - "integrity": "sha512-JTPxdUibkefeomWNaYs8lI/x/Zb4cOhZWX+d7kpzsNKzUd07pNuo/AcHeNJ/qgEchxM1IAxda9aaGUhKN/poOg==", + "version": "1.3.830", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.830.tgz", + "integrity": "sha512-gBN7wNAxV5vl1430dG+XRcQhD4pIeYeak6p6rjdCtlz5wWNwDad8jwvphe5oi1chL5MV6RNRikfffBBiFuj+rQ==", "dev": true }, "emoji-regex": { @@ -2649,12 +2663,6 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, - "i": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/i/-/i-0.3.6.tgz", - "integrity": "sha1-2WyScyB28HJxG2sQ/X1PZa2O4j0=", - "dev": true - }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -2812,9 +2820,9 @@ } }, "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true }, "is-typedarray": { @@ -3037,9 +3045,9 @@ } }, "jest-worker": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.6.tgz", - "integrity": "sha512-qupxcj/dRuA3xHPMUd40gr2EaAurFbkwzOh7wfPaeE9id7hyjURRQoqNfHifHK3XjJU6YJJUQKILGUnwGPEOCA==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.1.0.tgz", + "integrity": "sha512-mO4PHb2QWLn9yRXGp7rkvXLAYuxwhq1ZYUo0LoDhg8wqvv4QizP1ZWEJOeolgbEgAWZLIEU0wsku8J+lGWfBhg==", "dev": true, "requires": { "@types/node": "*", @@ -3149,9 +3157,9 @@ } }, "jszip": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.6.0.tgz", - "integrity": "sha512-jgnQoG9LKnWO3mnVNBnfhkh0QknICd1FGSrXcgrl67zioyJ4wgx25o9ZqwNtrROSflGBCGYnJfjrIyRIby1OoQ==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz", + "integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==", "requires": { "lie": "~3.3.0", "pako": "~1.0.2", @@ -3384,9 +3392,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -3471,9 +3479,9 @@ "dev": true }, "marked": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz", - "integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-3.0.2.tgz", + "integrity": "sha512-TMJQQ79Z0e3rJYazY0tIoMsFzteUGw9fB3FD+gzuIT3zLuG9L9ckIvUfF51apdJkcqc208jJN2KbtPbOvXtbjA==", "dev": true }, "medium-zoom": { @@ -3560,27 +3568,10 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } - } - }, "mocha": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.2.tgz", - "integrity": "sha512-FpspiWU+UT9Sixx/wKimvnpkeW0mh6ROAKkIaPokj3xZgxeRhcna/k5X57jJghEr8X+Cgu/Vegf8zCX5ugSuTA==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.1.tgz", + "integrity": "sha512-0wE74YMgOkCgBUj8VyIDwmLUjTsS13WV1Pg7l0SHea2qzZzlq7MDnfbPsHKcELBRk3+izEVkRofjmClpycudCA==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", @@ -3660,6 +3651,12 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "nanoid": { + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", + "dev": true + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3705,15 +3702,9 @@ "dev": true }, "nanoid": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", - "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==" - }, - "ncp": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz", - "integrity": "sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=", - "dev": true + "version": "3.1.25", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", + "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==" }, "neo-async": { "version": "2.6.2", @@ -3756,9 +3747,9 @@ } }, "node-releases": { - "version": "1.1.73", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", - "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", + "version": "1.1.75", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", + "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", "dev": true }, "normalize-path": { @@ -4215,9 +4206,9 @@ } }, "pako": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", - "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==" + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "parent-require": { "version": "1.0.0", @@ -4250,9 +4241,9 @@ "dev": true }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "path-to-regexp": { @@ -4385,15 +4376,15 @@ "dev": true }, "prompt": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.1.0.tgz", - "integrity": "sha512-ec1vUPXCplDBDUVD8uPa3XGA+OzLrO40Vxv3F1uxoiZGkZhdctlK2JotcHq5X6ExjocDOGwGdCSXloGNyU5L1Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.2.0.tgz", + "integrity": "sha512-iGerYRpRUg5ZyC+FJ/25G5PUKuWAGRjW1uOlhX7Pi3O5YygdK6R+KEaBjRbHSkU5vfS5PZCltSPZdDtUYwRCZA==", "dev": true, "requires": { + "async": "~0.9.0", "colors": "^1.1.2", "read": "1.0.x", "revalidator": "0.1.x", - "utile": "0.3.x", "winston": "2.x" } }, @@ -4871,31 +4862,14 @@ } }, "shiki": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.9.5.tgz", - "integrity": "sha512-XFn+rl3wIowDjzdr5DlHoHgQphXefgUTs2bNp/bZu4WF9gTrTLnKwio3f28VjiFG6Jpip7yQn/p4mMj6OrjrtQ==", + "version": "0.9.8", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.9.8.tgz", + "integrity": "sha512-499zQUTjcNTVwwiaPrWldUTXIV3T9HZWxDwE82bY+9GE7P2uD6hpHUTXNbTof3iOG6WT+/062+OMbl0lDoG8WQ==", "dev": true, "requires": { "json5": "^2.2.0", "onigasm": "^2.2.5", "vscode-textmate": "5.2.0" - }, - "dependencies": { - "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - } } }, "signal-exit": { @@ -4905,28 +4879,19 @@ "dev": true }, "sinon": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.1.tgz", - "integrity": "sha512-ZSSmlkSyhUWbkF01Z9tEbxZLF/5tRC9eojCdFh33gtQaP7ITQVaMWQHGuFM7Cuf/KEfihuh1tTl3/ABju3AQMg==", + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", + "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", "dev": true, "requires": { "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": "^7.1.0", + "@sinonjs/fake-timers": "^7.1.2", "@sinonjs/samsam": "^6.0.2", "diff": "^5.0.0", "nise": "^5.1.0", "supports-color": "^7.2.0" }, "dependencies": { - "@sinonjs/fake-timers": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.0.tgz", - "integrity": "sha512-hAEzXi6Wbvlb67NnGMGSNOeAflLVnMa4yliPU/ty1qjgW/vAletH15/v/esJwASSIA0YlIyjnloenFbEZc9q9A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -4944,12 +4909,6 @@ } } }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5167,9 +5126,9 @@ "dev": true }, "terser": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.1.tgz", - "integrity": "sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.2.tgz", + "integrity": "sha512-0Omye+RD4X7X69O0eql3lC4Heh/5iLj3ggxR/B5ketZLOtLiOqukUgjw3q4PDnNQbsrkKr3UMypqStQG3XKRvw==", "dev": true, "requires": { "commander": "^2.20.0", @@ -5192,17 +5151,17 @@ } }, "terser-webpack-plugin": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.4.tgz", - "integrity": "sha512-C2WkFwstHDhVEmsmlCxrXUtVklS+Ir1A7twrYzrDrQQOIMOaVAYykaoo/Aq1K0QRkMoY2hhvDQY1cm4jnIMFwA==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.2.3.tgz", + "integrity": "sha512-eDbuaDlXhVaaoKuLD3DTNTozKqln6xOG6Us0SzlKG5tNlazG+/cdl8pm9qiF1Di89iWScTI0HcO+CDcf2dkXiw==", "dev": true, "requires": { - "jest-worker": "^27.0.2", + "jest-worker": "^27.0.6", "p-limit": "^3.1.0", - "schema-utils": "^3.0.0", + "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", "source-map": "^0.6.1", - "terser": "^5.7.0" + "terser": "^5.7.2" }, "dependencies": { "p-limit": { @@ -5273,9 +5232,9 @@ } }, "ts-loader": { - "version": "9.2.3", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.3.tgz", - "integrity": "sha512-sEyWiU3JMHBL55CIeC4iqJQadI0U70A5af0kvgbNLHVNz2ACztQg0j/9x10bjjIht8WfFYLKfn4L6tkZ+pu+8Q==", + "version": "9.2.5", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.5.tgz", + "integrity": "sha512-al/ATFEffybdRMUIr5zMEWQdVnCGMUA9d3fXJ8dBVvBlzytPvIszoG9kZoR+94k6/i293RnVOXwMaWbXhNy9pQ==", "dev": true, "requires": { "chalk": "^4.1.0", @@ -5294,9 +5253,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -5392,14 +5351,26 @@ } }, "tsconfig-paths": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.10.1.tgz", - "integrity": "sha512-rETidPDgCpltxF7MjBZlAFPUHv5aHH2MymyPvh+vEyWAED4Eb/WeMbsnD/JDr4OKPOA1TssDHgIcpTN5Kh0p6Q==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", + "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", "dev": true, "requires": { - "json5": "^2.2.0", + "@types/json5": "^0.0.29", + "json5": "^1.0.1", "minimist": "^1.2.0", "strip-bom": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } } }, "tslib": { @@ -5519,18 +5490,18 @@ } }, "typedoc": { - "version": "0.21.4", - "resolved": "http://registry.npmjs.org/typedoc/-/typedoc-0.21.4.tgz", - "integrity": "sha512-slZQhvD9U0d9KacktYAyuNMMOXJRFNHy+Gd8xY2Qrqq3eTTTv3frv3N4au/cFnab9t3T5WA0Orb6QUjMc+1bDA==", + "version": "0.21.9", + "resolved": "http://registry.npmjs.org/typedoc/-/typedoc-0.21.9.tgz", + "integrity": "sha512-VRo7aII4bnYaBBM1lhw4bQFmUcDQV8m8tqgjtc7oXl87jc1Slbhfw2X5MccfcR2YnEClHDWgsiQGgNB8KJXocA==", "dev": true, "requires": { "glob": "^7.1.7", "handlebars": "^4.7.7", "lunr": "^2.3.9", - "marked": "^2.1.1", + "marked": "^3.0.2", "minimatch": "^3.0.0", "progress": "^2.0.3", - "shiki": "^0.9.3", + "shiki": "^0.9.8", "typedoc-default-themes": "^0.12.10" } }, @@ -5541,15 +5512,15 @@ "dev": true }, "typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz", + "integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==", "dev": true }, "uglify-js": { - "version": "3.13.10", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.10.tgz", - "integrity": "sha512-57H3ACYFXeo1IaZ1w02sfA71wI60MGco/IQFjOqK+WtKoprh7Go2/yvd2HPtoJILO2Or84ncLccI4xoHMTSbGg==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.1.tgz", + "integrity": "sha512-JhS3hmcVaXlp/xSo3PKY5R0JqKs5M3IV+exdLHW99qKvKivPO4Z8qbej6mte17SOPqAOVMjt/XGgWacnFSzM3g==", "dev": true, "optional": true }, @@ -5669,31 +5640,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "utile": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/utile/-/utile-0.3.0.tgz", - "integrity": "sha1-E1LDQOuCDk2N26A5pPv6oy7U7zo=", - "dev": true, - "requires": { - "async": "~0.9.0", - "deep-equal": "~0.2.1", - "i": "0.3.x", - "mkdirp": "0.x.x", - "ncp": "1.0.x", - "rimraf": "2.x.x" - }, - "dependencies": { - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -5740,9 +5686,9 @@ } }, "webpack": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.46.0.tgz", - "integrity": "sha512-qxD0t/KTedJbpcXUmvMxY5PUvXDbF8LsThCzqomeGaDlCA6k998D8yYVwZMvO8sSM3BTEOaD4uzFniwpHaTIJw==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.52.0.tgz", + "integrity": "sha512-yRZOat8jWGwBwHpco3uKQhVU7HYaNunZiJ4AkAVQkPCUGoZk/tiIXiwG+8HIy/F+qsiZvSOa+GLQOj3q5RKRYg==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.0", @@ -5751,6 +5697,7 @@ "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.8.0", @@ -5767,27 +5714,27 @@ "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", "watchpack": "^2.2.0", - "webpack-sources": "^2.3.1" + "webpack-sources": "^3.2.0" }, "dependencies": { "graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true } } }, "webpack-cli": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.7.2.tgz", - "integrity": "sha512-mEoLmnmOIZQNiRl0ebnjzQ74Hk0iKS5SiEEnpq3dRezoyR3yPaeQZCMCe+db4524pj1Pd5ghZXjT41KLzIhSLw==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.8.0.tgz", + "integrity": "sha512-+iBSWsX16uVna5aAYN6/wjhJy1q/GKk4KjKvfg90/6hykCTSgozbfz5iRgDTSJt/LgSbYxdBX3KBHeobIs+ZEw==", "dev": true, "requires": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^1.0.4", "@webpack-cli/info": "^1.3.0", - "@webpack-cli/serve": "^1.5.1", + "@webpack-cli/serve": "^1.5.2", "colorette": "^1.2.1", "commander": "^7.0.0", "execa": "^5.0.0", @@ -5812,9 +5759,9 @@ "dev": true }, "rechoir": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", - "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", "dev": true, "requires": { "resolve": "^1.9.0" @@ -5833,14 +5780,10 @@ } }, "webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "dev": true, - "requires": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - } + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.0.tgz", + "integrity": "sha512-fahN08Et7P9trej8xz/Z7eRu8ltyiygEo/hnRi9KqBUs80KeDcnf96ZJo++ewWd84fEf3xSX9bp4ZS9hbw0OBw==", + "dev": true }, "which": { "version": "1.2.14", diff --git a/package.json b/package.json index e38e903856..142e167301 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "tslint": "^6.1.3", "tslint-immutable": "^6.0.1", "typedoc": "^0.21.1", - "typescript": "4.3.5", + "typescript": "4.4.2", "webpack": "^5.28.0", "webpack-cli": "^4.6.0" }, diff --git a/src/file/numbering/numbering.spec.ts b/src/file/numbering/numbering.spec.ts index 6053a5e3cd..83314eabcd 100644 --- a/src/file/numbering/numbering.spec.ts +++ b/src/file/numbering/numbering.spec.ts @@ -112,5 +112,26 @@ describe("Numbering", () => { expect(numbering.ConcreteNumbering).to.have.length(2); }); }); + describe("#referenceConfigMap", () => { + it("should store level configs into referenceConfigMap", () => { + const numbering = new Numbering({ + config: [ + { + reference: "test-reference", + levels: [ + { + level: 0, + start: 10, + }, + ], + }, + ], + }); + numbering.createConcreteNumberingInstance("test-reference", 0); + const referenceConfig = numbering.ReferenceConfig[0]; + const zeroLevelConfig = referenceConfig[0]; + expect(zeroLevelConfig.start).to.be.equal(10); + }); + }); }); }); diff --git a/src/file/numbering/numbering.ts b/src/file/numbering/numbering.ts index 8f37b386c5..998cd144a2 100644 --- a/src/file/numbering/numbering.ts +++ b/src/file/numbering/numbering.ts @@ -29,6 +29,7 @@ export interface INumberingOptions { export class Numbering extends XmlComponent { private readonly abstractNumberingMap = new Map(); private readonly concreteNumberingMap = new Map(); + private readonly referenceConfigMap = new Map(); constructor(options: INumberingOptions) { super("w:numbering"); @@ -174,6 +175,7 @@ export class Numbering extends XmlComponent { for (const con of options.config) { this.abstractNumberingMap.set(con.reference, new AbstractNumbering(uniqueNumericId(), con.levels)); + this.referenceConfigMap.set(con.reference, con.levels); } } @@ -201,22 +203,33 @@ export class Numbering extends XmlComponent { return; } - this.concreteNumberingMap.set( - fullReference, - new ConcreteNumbering({ - numId: uniqueNumericId(), - abstractNumId: abstractNumbering.id, - reference, - instance, - overrideLevel: { - num: 0, - start: 1, - }, - }), - ); + const concreteNumberingSettings = { + numId: uniqueNumericId(), + abstractNumId: abstractNumbering.id, + reference, + instance, + overrideLevel: { + num: 0, + start: 1, + }, + }; + + const referenceConfigLevels = this.referenceConfigMap.get(reference); + const firstLevelStartNumber = referenceConfigLevels && referenceConfigLevels[0].start; + if (firstLevelStartNumber && Number.isInteger(firstLevelStartNumber)) { + concreteNumberingSettings.overrideLevel = { + num: 0, + start: firstLevelStartNumber, + }; + } + + this.concreteNumberingMap.set(fullReference, new ConcreteNumbering(concreteNumberingSettings)); } public get ConcreteNumbering(): ConcreteNumbering[] { return Array.from(this.concreteNumberingMap.values()); } + public get ReferenceConfig(): object[] { + return Array.from(this.referenceConfigMap.values()); + } } diff --git a/src/file/paragraph/links/bookmark.ts b/src/file/paragraph/links/bookmark.ts index b7d32bdbad..a0342b6fcb 100644 --- a/src/file/paragraph/links/bookmark.ts +++ b/src/file/paragraph/links/bookmark.ts @@ -2,15 +2,15 @@ import { uniqueId } from "convenience-functions"; import { XmlComponent } from "file/xml-components"; -import { TextRun } from "../run"; +import { ParagraphChild } from "../paragraph"; import { BookmarkEndAttributes, BookmarkStartAttributes } from "./bookmark-attributes"; export class Bookmark { public readonly start: BookmarkStart; - public readonly children: TextRun[]; + public readonly children: ParagraphChild[]; public readonly end: BookmarkEnd; - constructor(options: { readonly id: string; readonly children: TextRun[] }) { + constructor(options: { readonly id: string; readonly children: ParagraphChild[] }) { const linkId = uniqueId(); this.start = new BookmarkStart(options.id, linkId); diff --git a/src/file/paragraph/links/hyperlink.spec.ts b/src/file/paragraph/links/hyperlink.spec.ts index 50d6aa76aa..9f79a19ff1 100644 --- a/src/file/paragraph/links/hyperlink.spec.ts +++ b/src/file/paragraph/links/hyperlink.spec.ts @@ -10,10 +10,12 @@ describe("ConcreteHyperlink", () => { beforeEach(() => { hyperlink = new ConcreteHyperlink( - new TextRun({ - text: "https://example.com", - style: "Hyperlink", - }), + [ + new TextRun({ + text: "https://example.com", + style: "Hyperlink", + }), + ], "superid", ); }); @@ -42,10 +44,12 @@ describe("ConcreteHyperlink", () => { describe("with optional anchor parameter", () => { beforeEach(() => { hyperlink = new ConcreteHyperlink( - new TextRun({ - text: "Anchor Text", - style: "Hyperlink", - }), + [ + new TextRun({ + text: "Anchor Text", + style: "Hyperlink", + }), + ], "superid2", "anchor", ); @@ -78,7 +82,7 @@ describe("ExternalHyperlink", () => { describe("#constructor()", () => { it("should create", () => { const externalHyperlink = new ExternalHyperlink({ - child: new TextRun("test"), + children: [new TextRun("test")], link: "http://www.google.com", }); @@ -91,7 +95,7 @@ describe("InternalHyperlink", () => { describe("#constructor()", () => { it("should create", () => { const internalHyperlink = new InternalHyperlink({ - child: new TextRun("test"), + children: [new TextRun("test")], anchor: "test-id", }); diff --git a/src/file/paragraph/links/hyperlink.ts b/src/file/paragraph/links/hyperlink.ts index 7ced10d07c..2c39997908 100644 --- a/src/file/paragraph/links/hyperlink.ts +++ b/src/file/paragraph/links/hyperlink.ts @@ -13,7 +13,7 @@ export enum HyperlinkType { export class ConcreteHyperlink extends XmlComponent { public readonly linkId: string; - constructor(child: ParagraphChild, relationshipId: string, anchor?: string) { + constructor(children: ParagraphChild[], relationshipId: string, anchor?: string) { super("w:hyperlink"); this.linkId = relationshipId; @@ -26,16 +26,18 @@ export class ConcreteHyperlink extends XmlComponent { const attributes = new HyperlinkAttributes(props); this.root.push(attributes); - this.root.push(child); + children.forEach((child) => { + this.root.push(child); + }); } } export class InternalHyperlink extends ConcreteHyperlink { - constructor(options: { readonly child: ParagraphChild; readonly anchor: string }) { - super(options.child, uniqueId(), options.anchor); + constructor(options: { readonly children: ParagraphChild[]; readonly anchor: string }) { + super(options.children, uniqueId(), options.anchor); } } export class ExternalHyperlink { - constructor(public readonly options: { readonly child: ParagraphChild; readonly link: string }) {} + constructor(public readonly options: { readonly children: ParagraphChild[]; readonly link: string }) {} } diff --git a/src/file/paragraph/links/index.ts b/src/file/paragraph/links/index.ts index 82715b62e8..f3b83733bd 100644 --- a/src/file/paragraph/links/index.ts +++ b/src/file/paragraph/links/index.ts @@ -1,3 +1,4 @@ export * from "./hyperlink"; export * from "./bookmark"; export * from "./outline-level"; +export * from "./pageref"; diff --git a/src/file/paragraph/links/pageref-field-instruction.spec.ts b/src/file/paragraph/links/pageref-field-instruction.spec.ts new file mode 100644 index 0000000000..942c108be9 --- /dev/null +++ b/src/file/paragraph/links/pageref-field-instruction.spec.ts @@ -0,0 +1,24 @@ +import { expect } from "chai"; + +import { Formatter } from "export/formatter"; +import { PageReferenceFieldInstruction } from "./pageref-field-instruction"; + +describe("PageReference field instruction", () => { + describe("#constructor()", () => { + it("should construct a pageref field instruction without options", () => { + const instruction = new PageReferenceFieldInstruction("anchor"); + const tree = new Formatter().format(instruction); + + expect(tree).to.be.deep.equal({ + "w:instrText": [ + { + _attr: { + "xml:space": "preserve", + }, + }, + "PAGEREF anchor", + ], + }); + }); + }); +}); diff --git a/src/file/paragraph/links/pageref-field-instruction.ts b/src/file/paragraph/links/pageref-field-instruction.ts new file mode 100644 index 0000000000..99be950d28 --- /dev/null +++ b/src/file/paragraph/links/pageref-field-instruction.ts @@ -0,0 +1,25 @@ +import { SpaceType } from "file/space-type"; +import { XmlAttributeComponent, XmlComponent } from "file/xml-components"; +import { IPageReferenceOptions } from "./pageref-properties"; + +class TextAttributes extends XmlAttributeComponent<{ readonly space: SpaceType }> { + protected readonly xmlKeys = { space: "xml:space" }; +} + +export class PageReferenceFieldInstruction extends XmlComponent { + constructor(bookmarkId: string, options: IPageReferenceOptions = {}) { + super("w:instrText"); + this.root.push(new TextAttributes({ space: SpaceType.PRESERVE })); + + let instruction = `PAGEREF ${bookmarkId}`; + + if (options.hyperlink) { + instruction = `${instruction} \\h`; + } + if (options.useRelativePosition) { + instruction = `${instruction} \\p`; + } + + this.root.push(instruction); + } +} diff --git a/src/file/paragraph/links/pageref-properties.ts b/src/file/paragraph/links/pageref-properties.ts new file mode 100644 index 0000000000..f557cfc322 --- /dev/null +++ b/src/file/paragraph/links/pageref-properties.ts @@ -0,0 +1,16 @@ +// Options according to https://www.ecma-international.org/publications/standards/Ecma-376.htm (at Part 1, Page 1234) + +export interface IPageReferenceOptions { + /** + * \h option - Creates a hyperlink to the bookmarked paragraph. + */ + readonly hyperlink?: boolean; + /** + * \p option - Causes the field to display its position relative to the source + * bookmark. If the PAGEREF field is on the same page as the + * bookmark, it omits "on page #" and returns "above" or "below" + * only. If the PAGEREF field is not on the same page as the + * bookmark, the string "on page #" is used. + */ + readonly useRelativePosition?: boolean; +} diff --git a/src/file/paragraph/links/pageref.spec.ts b/src/file/paragraph/links/pageref.spec.ts new file mode 100644 index 0000000000..c26c8c8632 --- /dev/null +++ b/src/file/paragraph/links/pageref.spec.ts @@ -0,0 +1,76 @@ +import { expect } from "chai"; + +import { Formatter } from "export/formatter"; +import { PageReference } from "./pageref"; + +describe("PageReference", () => { + describe("#constructor()", () => { + it("should construct a pageref without options", () => { + const pageref = new PageReference("some_bookmark"); + const tree = new Formatter().format(pageref); + expect(tree).to.be.deep.equal({ + "w:r": [ + { + "w:fldChar": { + _attr: { + "w:dirty": true, + "w:fldCharType": "begin", + }, + }, + }, + { + "w:instrText": [ + { + _attr: { + "xml:space": "preserve", + }, + }, + "PAGEREF some_bookmark", + ], + }, + { + "w:fldChar": { + _attr: { + "w:fldCharType": "end", + }, + }, + }, + ], + }); + }); + + it("should construct a pageref with all the options", () => { + const pageReference = new PageReference("some_bookmark", { hyperlink: true, useRelativePosition: true }); + const tree = new Formatter().format(pageReference); + expect(tree).to.be.deep.equal({ + "w:r": [ + { + "w:fldChar": { + _attr: { + "w:dirty": true, + "w:fldCharType": "begin", + }, + }, + }, + { + "w:instrText": [ + { + _attr: { + "xml:space": "preserve", + }, + }, + "PAGEREF some_bookmark \\h \\p", + ], + }, + { + "w:fldChar": { + _attr: { + "w:fldCharType": "end", + }, + }, + }, + ], + }); + }); + }); +}); diff --git a/src/file/paragraph/links/pageref.ts b/src/file/paragraph/links/pageref.ts new file mode 100644 index 0000000000..b2f1880d2d --- /dev/null +++ b/src/file/paragraph/links/pageref.ts @@ -0,0 +1,13 @@ +// See https://www.ecma-international.org/publications/standards/Ecma-376.htm (at Part 1, Page 1234) +import { Begin, End } from "file/paragraph/run/field"; +import { Run } from "../run"; +import { PageReferenceFieldInstruction } from "./pageref-field-instruction"; +import type { IPageReferenceOptions } from "./pageref-properties"; + +export class PageReference extends Run { + constructor(bookmarkId: string, options: IPageReferenceOptions = {}) { + super({ + children: [new Begin(true), new PageReferenceFieldInstruction(bookmarkId, options), new End()], + }); + } +} diff --git a/src/file/paragraph/paragraph.spec.ts b/src/file/paragraph/paragraph.spec.ts index 90c6c8bedd..ab06d59ac1 100644 --- a/src/file/paragraph/paragraph.spec.ts +++ b/src/file/paragraph/paragraph.spec.ts @@ -927,7 +927,7 @@ describe("Paragraph", () => { const paragraph = new Paragraph({ children: [ new ExternalHyperlink({ - child: new TextRun("test"), + children: [new TextRun("test")], link: "http://www.google.com", }), ], diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts index afd9da1b7d..2f73f7cc65 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -75,7 +75,7 @@ export class Paragraph extends XmlComponent { for (const element of this.root) { if (element instanceof ExternalHyperlink) { const index = this.root.indexOf(element); - const concreteHyperlink = new ConcreteHyperlink(element.options.child, uniqueId()); + const concreteHyperlink = new ConcreteHyperlink(element.options.children, uniqueId()); context.viewWrapper.Relationships.createRelationship( concreteHyperlink.linkId, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",