Compare commits
39 Commits
Author | SHA1 | Date | |
---|---|---|---|
bb686bbcbe | |||
c898d0a3c3 | |||
704c678333 | |||
c59c5350fd | |||
accb1d44d0 | |||
b61f798cd9 | |||
be2ec9d4cf | |||
514fbb1c09 | |||
8ce397f61e | |||
3b0dfb8489 | |||
f4933deaf2 | |||
add2273551 | |||
91b00466a0 | |||
d0612e115e | |||
e4a6cbe887 | |||
0386810714 | |||
d4585f60b3 | |||
18f015a959 | |||
10c866bdea | |||
680c938dcf | |||
c3a617fefd | |||
6362b498a6 | |||
2e30ab29be | |||
44568023cd | |||
c57aaa856d | |||
0f4f24c3f3 | |||
2fe7a2e3d3 | |||
20b62f5768 | |||
ab063eee08 | |||
66c7624b40 | |||
bfc302023f | |||
3505912f74 | |||
ec379f2e4d | |||
2d17954104 | |||
01c834b16b | |||
2aeb2c2e88 | |||
be88086434 | |||
28f0cc681d | |||
def29c535b |
61
.cspell.json
61
.cspell.json
@ -4,34 +4,40 @@
|
|||||||
"version": "0.2",
|
"version": "0.2",
|
||||||
// language - current active spelling language
|
// language - current active spelling language
|
||||||
"language": "en_US",
|
"language": "en_US",
|
||||||
"dictionaries": ["en_US", "typescript", "softwareTerms", "fonts", "npm"],
|
"dictionaries": [
|
||||||
|
"en_US",
|
||||||
|
"typescript",
|
||||||
|
"softwareTerms",
|
||||||
|
"fonts",
|
||||||
|
"npm"
|
||||||
|
],
|
||||||
// words - list of words to be always considered correct
|
// words - list of words to be always considered correct
|
||||||
"words": [
|
"words": [
|
||||||
"Xmlable",
|
"Abjad",
|
||||||
|
"aiueo",
|
||||||
|
"ATLEAST",
|
||||||
|
"chosung",
|
||||||
|
"clippy",
|
||||||
|
"datas",
|
||||||
|
"docsify",
|
||||||
|
"dolan",
|
||||||
|
"falsey",
|
||||||
|
"Initializable",
|
||||||
|
"iroha",
|
||||||
|
"jsonify",
|
||||||
|
"jszip",
|
||||||
|
"NUMPAGES",
|
||||||
|
"odttf",
|
||||||
|
"ooxml",
|
||||||
|
"panose",
|
||||||
|
"rels",
|
||||||
|
"rsid",
|
||||||
"twip",
|
"twip",
|
||||||
"twips",
|
"twips",
|
||||||
"jsonify",
|
"Xmlable",
|
||||||
"falsey",
|
|
||||||
"aiueo",
|
|
||||||
"iroha",
|
|
||||||
"aiueo",
|
|
||||||
"iroha",
|
|
||||||
"chosung",
|
|
||||||
"Abjad",
|
|
||||||
"Initializable",
|
|
||||||
"rels",
|
|
||||||
"dolan",
|
|
||||||
"xmlify",
|
|
||||||
"Xmlifyed",
|
|
||||||
"xmlified",
|
"xmlified",
|
||||||
"datas",
|
"xmlify",
|
||||||
"jszip",
|
"Xmlifyed"
|
||||||
"rsid",
|
|
||||||
"NUMPAGES",
|
|
||||||
"ATLEAST",
|
|
||||||
"ooxml",
|
|
||||||
"clippy",
|
|
||||||
"docsify"
|
|
||||||
],
|
],
|
||||||
"ignoreRegExpList": [
|
"ignoreRegExpList": [
|
||||||
"/\"w:.+\"/",
|
"/\"w:.+\"/",
|
||||||
@ -51,10 +57,15 @@
|
|||||||
"/<element name=\"[a-z]+\"/gi",
|
"/<element name=\"[a-z]+\"/gi",
|
||||||
"/<attribute name=\"[a-z]+\"/gi"
|
"/<attribute name=\"[a-z]+\"/gi"
|
||||||
],
|
],
|
||||||
"ignorePaths": ["package.json", "docs/api"],
|
"ignorePaths": [
|
||||||
|
"package.json",
|
||||||
|
"docs/api"
|
||||||
|
],
|
||||||
"allowCompoundWords": true,
|
"allowCompoundWords": true,
|
||||||
// flagWords - list of words to be always considered incorrect
|
// flagWords - list of words to be always considered incorrect
|
||||||
// This is useful for offensive words and common spelling errors.
|
// This is useful for offensive words and common spelling errors.
|
||||||
// For example "hte" should be "the"
|
// For example "hte" should be "the"
|
||||||
"flagWords": ["hte"]
|
"flagWords": [
|
||||||
|
"hte"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,55 @@ const doc = new Document({
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
author: "Bob Ross",
|
||||||
|
date: new Date(),
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
text: "Some initial text content",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
text: "comment text content",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
author: "John Doe",
|
||||||
|
date: new Date(),
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
text: "Hello World",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
author: "Beatriz",
|
||||||
|
date: new Date(),
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
text: "Another reply",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
sections: [
|
sections: [
|
||||||
@ -53,6 +102,32 @@ const doc = new Document({
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new CommentRangeStart(1),
|
||||||
|
new CommentRangeStart(2),
|
||||||
|
new CommentRangeStart(3),
|
||||||
|
new TextRun({
|
||||||
|
text: "Some text which need commenting",
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
new CommentRangeEnd(1),
|
||||||
|
new TextRun({
|
||||||
|
children: [new CommentReference(1)],
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
new CommentRangeEnd(2),
|
||||||
|
new TextRun({
|
||||||
|
children: [new CommentReference(2)],
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
new CommentRangeEnd(3),
|
||||||
|
new TextRun({
|
||||||
|
children: [new CommentReference(3)],
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
31
demo/88-template-document.ts
Normal file
31
demo/88-template-document.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Patch a document with patches
|
||||||
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { IPatch, patchDocument, PatchType, TextRun } from "../build";
|
||||||
|
|
||||||
|
export const font = "Trebuchet MS";
|
||||||
|
export const getPatches = (fields: { [key: string]: string }) => {
|
||||||
|
const patches: { [key: string]: IPatch } = {};
|
||||||
|
|
||||||
|
for (const field in fields) {
|
||||||
|
patches[field] = {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: fields[field], font })],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return patches;
|
||||||
|
};
|
||||||
|
|
||||||
|
const patches = getPatches({
|
||||||
|
name: "Mr",
|
||||||
|
table_heading_1: "John",
|
||||||
|
item_1: "Doe",
|
||||||
|
paragraph_replace: "Lorem ipsum paragraph",
|
||||||
|
});
|
||||||
|
|
||||||
|
patchDocument(fs.readFileSync("demo/assets/simple-template.docx"), {
|
||||||
|
patches,
|
||||||
|
}).then((doc) => {
|
||||||
|
fs.writeFileSync("My Document.docx", doc);
|
||||||
|
});
|
29
demo/89-template-document.ts
Normal file
29
demo/89-template-document.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Patch a document with patches
|
||||||
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { IPatch, patchDocument, PatchType, TextRun } from "../build";
|
||||||
|
|
||||||
|
export const font = "Trebuchet MS";
|
||||||
|
export const getPatches = (fields: { [key: string]: string }) => {
|
||||||
|
const patches: { [key: string]: IPatch } = {};
|
||||||
|
|
||||||
|
for (const field in fields) {
|
||||||
|
patches[field] = {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: fields[field], font })],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return patches;
|
||||||
|
};
|
||||||
|
|
||||||
|
const patches = getPatches({
|
||||||
|
salutation: "Mr.",
|
||||||
|
"first-name": "John",
|
||||||
|
});
|
||||||
|
|
||||||
|
patchDocument(fs.readFileSync("demo/assets/simple-template-3.docx"), {
|
||||||
|
patches,
|
||||||
|
}).then((doc) => {
|
||||||
|
fs.writeFileSync("My Document.docx", doc);
|
||||||
|
});
|
BIN
demo/assets/simple-template-3.docx
Normal file
BIN
demo/assets/simple-template-3.docx
Normal file
Binary file not shown.
@ -38,6 +38,7 @@
|
|||||||
<script src="https://unpkg.com/docsify-copy-code@2"></script>
|
<script src="https://unpkg.com/docsify-copy-code@2"></script>
|
||||||
<script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script>
|
<script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script>
|
||||||
<script src="//unpkg.com/prismjs/components/prism-typescript.min.js"></script>
|
<script src="//unpkg.com/prismjs/components/prism-typescript.min.js"></script>
|
||||||
|
<script src="https://unpkg.com/docsify-sign-off-sheet@1.0.0/dist/index.iife.js"></script>
|
||||||
<script src="//cdn.jsdelivr.net/npm/docsify-darklight-theme@latest/dist/index.min.js" type="text/javascript"></script>
|
<script src="//cdn.jsdelivr.net/npm/docsify-darklight-theme@latest/dist/index.min.js" type="text/javascript"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -305,4 +305,12 @@ Example: https://github.com/dolanmiu/docx/blob/master/demo/15-page-break-before.
|
|||||||
|
|
||||||
## Page break control
|
## Page break control
|
||||||
|
|
||||||
Paragraphs have `.keepLines()` and `.keepNext()` methods that allow restricting page breaks within and between paragraphs. See [this Microsoft article](https://support.office.com/en-us/article/Keep-lines-and-paragraphs-together-d72af534-926f-4c4b-830a-abfc2daa3bfa) for more details)
|
Paragraphs have `keepLines` and `keepNext` properties that allow restricting page breaks within and between paragraphs. See [this Microsoft article](https://support.office.com/en-us/article/Keep-lines-and-paragraphs-together-d72af534-926f-4c4b-830a-abfc2daa3bfa) for more details.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const paragraph = new Paragraph({
|
||||||
|
text: "Stay on the same page",
|
||||||
|
keepLines: true,
|
||||||
|
keepNext: true,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
829
package-lock.json
generated
829
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "docx",
|
"name": "docx",
|
||||||
"version": "8.0.1",
|
"version": "8.0.3",
|
||||||
"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.",
|
||||||
"main": "build/index.js",
|
"main": "build/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -104,7 +104,7 @@
|
|||||||
"tsconfig-paths": "^4.0.0",
|
"tsconfig-paths": "^4.0.0",
|
||||||
"tsconfig-paths-webpack-plugin": "^4.0.0",
|
"tsconfig-paths-webpack-plugin": "^4.0.0",
|
||||||
"typedoc": "^0.23.2",
|
"typedoc": "^0.23.2",
|
||||||
"typescript": "5.0.2",
|
"typescript": "5.0.3",
|
||||||
"unzipper": "^0.10.11",
|
"unzipper": "^0.10.11",
|
||||||
"webpack": "^5.28.0",
|
"webpack": "^5.28.0",
|
||||||
"webpack-cli": "^5.0.0"
|
"webpack-cli": "^5.0.0"
|
||||||
|
@ -41,11 +41,11 @@ const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
|||||||
|
|
||||||
describe("Anchor", () => {
|
describe("Anchor", () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
stub(convenienceFunctions, "uniqueNumericId").callsFake(() => 0);
|
stub(convenienceFunctions, "docPropertiesUniqueNumericId").callsFake(() => 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
(convenienceFunctions.uniqueNumericId as SinonStub).restore();
|
(convenienceFunctions.docPropertiesUniqueNumericId as SinonStub).restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
let anchor: Anchor;
|
let anchor: Anchor;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { IContext, IXmlableObject, NextAttributeComponent, XmlComponent } from "@file/xml-components";
|
import { IContext, IXmlableObject, NextAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||||
import { ConcreteHyperlink } from "@file/paragraph";
|
import { ConcreteHyperlink } from "@file/paragraph";
|
||||||
|
|
||||||
import { uniqueNumericId } from "@util/convenience-functions";
|
import { docPropertiesUniqueNumericId } from "@util/convenience-functions";
|
||||||
|
|
||||||
import { createHyperlinkClick } from "./doc-properties-children";
|
import { createHyperlinkClick } from "./doc-properties-children";
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ export class DocProperties extends XmlComponent {
|
|||||||
new NextAttributeComponent({
|
new NextAttributeComponent({
|
||||||
id: {
|
id: {
|
||||||
key: "id",
|
key: "id",
|
||||||
value: uniqueNumericId(),
|
value: docPropertiesUniqueNumericId(),
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
key: "name",
|
key: "name",
|
||||||
|
@ -31,11 +31,11 @@ const createDrawing = (drawingOptions?: IDrawingOptions): Drawing =>
|
|||||||
|
|
||||||
describe("Drawing", () => {
|
describe("Drawing", () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
stub(convenienceFunctions, "uniqueNumericId").callsFake(() => 0);
|
stub(convenienceFunctions, "docPropertiesUniqueNumericId").callsFake(() => 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
(convenienceFunctions.uniqueNumericId as SinonStub).restore();
|
(convenienceFunctions.docPropertiesUniqueNumericId as SinonStub).restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
let currentBreak: Drawing;
|
let currentBreak: Drawing;
|
||||||
|
@ -8,11 +8,13 @@ import { Numbering } from "./numbering";
|
|||||||
|
|
||||||
describe("Numbering", () => {
|
describe("Numbering", () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
stub(convenienceFunctions, "uniqueNumericId").callsFake(() => 0);
|
stub(convenienceFunctions, "abstractNumUniqueNumericId").callsFake(() => 0);
|
||||||
|
stub(convenienceFunctions, "concreteNumUniqueNumericId").callsFake(() => 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
(convenienceFunctions.uniqueNumericId as SinonStub).restore();
|
(convenienceFunctions.abstractNumUniqueNumericId as SinonStub).restore();
|
||||||
|
(convenienceFunctions.concreteNumUniqueNumericId as SinonStub).restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#constructor", () => {
|
describe("#constructor", () => {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// https://stackoverflow.com/questions/58622437/purpose-of-abstractnum-and-numberinginstance
|
// https://stackoverflow.com/questions/58622437/purpose-of-abstractnum-and-numberinginstance
|
||||||
import { AlignmentType } from "@file/paragraph";
|
import { AlignmentType } from "@file/paragraph";
|
||||||
import { IContext, IXmlableObject, XmlComponent } from "@file/xml-components";
|
import { IContext, IXmlableObject, XmlComponent } from "@file/xml-components";
|
||||||
import { convertInchesToTwip, uniqueNumericId } from "@util/convenience-functions";
|
import { abstractNumUniqueNumericId, concreteNumUniqueNumericId, convertInchesToTwip } from "@util/convenience-functions";
|
||||||
|
|
||||||
import { DocumentAttributes } from "../document/document-attributes";
|
import { DocumentAttributes } from "../document/document-attributes";
|
||||||
import { AbstractNumbering } from "./abstract-numbering";
|
import { AbstractNumbering } from "./abstract-numbering";
|
||||||
@ -55,7 +55,7 @@ export class Numbering extends XmlComponent {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const abstractNumbering = new AbstractNumbering(uniqueNumericId(), [
|
const abstractNumbering = new AbstractNumbering(abstractNumUniqueNumericId(), [
|
||||||
{
|
{
|
||||||
level: 0,
|
level: 0,
|
||||||
format: LevelFormat.BULLET,
|
format: LevelFormat.BULLET,
|
||||||
@ -176,7 +176,7 @@ export class Numbering extends XmlComponent {
|
|||||||
this.abstractNumberingMap.set("default-bullet-numbering", abstractNumbering);
|
this.abstractNumberingMap.set("default-bullet-numbering", abstractNumbering);
|
||||||
|
|
||||||
for (const con of options.config) {
|
for (const con of options.config) {
|
||||||
this.abstractNumberingMap.set(con.reference, new AbstractNumbering(uniqueNumericId(), con.levels));
|
this.abstractNumberingMap.set(con.reference, new AbstractNumbering(abstractNumUniqueNumericId(), con.levels));
|
||||||
this.referenceConfigMap.set(con.reference, con.levels);
|
this.referenceConfigMap.set(con.reference, con.levels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,7 +209,7 @@ export class Numbering extends XmlComponent {
|
|||||||
const firstLevelStartNumber = referenceConfigLevels && referenceConfigLevels[0].start;
|
const firstLevelStartNumber = referenceConfigLevels && referenceConfigLevels[0].start;
|
||||||
|
|
||||||
const concreteNumberingSettings = {
|
const concreteNumberingSettings = {
|
||||||
numId: uniqueNumericId(),
|
numId: concreteNumUniqueNumericId(),
|
||||||
abstractNumId: abstractNumbering.id,
|
abstractNumId: abstractNumbering.id,
|
||||||
reference,
|
reference,
|
||||||
instance,
|
instance,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// http://officeopenxml.com/WPbookmark.php
|
// http://officeopenxml.com/WPbookmark.php
|
||||||
import { XmlComponent } from "@file/xml-components";
|
import { XmlComponent } from "@file/xml-components";
|
||||||
import { uniqueNumericId } from "@util/convenience-functions";
|
import { bookmarkUniqueNumericId } from "@util/convenience-functions";
|
||||||
|
|
||||||
import { ParagraphChild } from "../paragraph";
|
import { ParagraphChild } from "../paragraph";
|
||||||
import { BookmarkEndAttributes, BookmarkStartAttributes } from "./bookmark-attributes";
|
import { BookmarkEndAttributes, BookmarkStartAttributes } from "./bookmark-attributes";
|
||||||
@ -11,7 +11,7 @@ export class Bookmark {
|
|||||||
public readonly end: BookmarkEnd;
|
public readonly end: BookmarkEnd;
|
||||||
|
|
||||||
public constructor(options: { readonly id: string; readonly children: readonly ParagraphChild[] }) {
|
public constructor(options: { readonly id: string; readonly children: readonly ParagraphChild[] }) {
|
||||||
const linkId = uniqueNumericId();
|
const linkId = bookmarkUniqueNumericId();
|
||||||
|
|
||||||
this.start = new BookmarkStart(options.id, linkId);
|
this.start = new BookmarkStart(options.id, linkId);
|
||||||
this.children = options.children;
|
this.children = options.children;
|
||||||
|
@ -20,12 +20,12 @@ import { TextRun } from "./run";
|
|||||||
describe("Paragraph", () => {
|
describe("Paragraph", () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
stub(convenienceFunctions, "uniqueId").callsFake(() => "test-unique-id");
|
stub(convenienceFunctions, "uniqueId").callsFake(() => "test-unique-id");
|
||||||
stub(convenienceFunctions, "uniqueNumericId").callsFake(() => -101);
|
stub(convenienceFunctions, "bookmarkUniqueNumericId").callsFake(() => -101);
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
(convenienceFunctions.uniqueId as SinonStub).restore();
|
(convenienceFunctions.uniqueId as SinonStub).restore();
|
||||||
(convenienceFunctions.uniqueNumericId as SinonStub).restore();
|
(convenienceFunctions.bookmarkUniqueNumericId as SinonStub).restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
|
@ -23,7 +23,13 @@ export interface ILevelParagraphStylePropertiesOptions {
|
|||||||
readonly leftTabStop?: number;
|
readonly leftTabStop?: number;
|
||||||
readonly indent?: IIndentAttributesProperties;
|
readonly indent?: IIndentAttributesProperties;
|
||||||
readonly spacing?: ISpacingProperties;
|
readonly spacing?: ISpacingProperties;
|
||||||
|
/**
|
||||||
|
* Specifies that the paragraph (or at least part of it) should be rendered on the same page as the next paragraph when possible. If multiple paragraphs are to be kept together but they exceed a page, then the set of paragraphs begin on a new page and page breaks are used thereafter as needed.
|
||||||
|
*/
|
||||||
readonly keepNext?: boolean;
|
readonly keepNext?: boolean;
|
||||||
|
/**
|
||||||
|
* Specifies that all lines of the paragraph are to be kept on a single page when possible.
|
||||||
|
*/
|
||||||
readonly keepLines?: boolean;
|
readonly keepLines?: boolean;
|
||||||
readonly outlineLevel?: number;
|
readonly outlineLevel?: number;
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,12 @@ import { ImageRun } from "./image-run";
|
|||||||
describe("ImageRun", () => {
|
describe("ImageRun", () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
stub(convenienceFunctions, "uniqueId").callsFake(() => "test-unique-id");
|
stub(convenienceFunctions, "uniqueId").callsFake(() => "test-unique-id");
|
||||||
stub(convenienceFunctions, "uniqueNumericId").callsFake(() => 0);
|
stub(convenienceFunctions, "docPropertiesUniqueNumericId").callsFake(() => 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
(convenienceFunctions.uniqueId as SinonStub).restore();
|
(convenienceFunctions.uniqueId as SinonStub).restore();
|
||||||
(convenienceFunctions.uniqueNumericId as SinonStub).restore();
|
(convenienceFunctions.docPropertiesUniqueNumericId as SinonStub).restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
|
@ -41,6 +41,13 @@ export interface IStyleAttributes {
|
|||||||
|
|
||||||
export interface IStyleOptions {
|
export interface IStyleOptions {
|
||||||
readonly name?: string;
|
readonly name?: string;
|
||||||
|
/**
|
||||||
|
* Specifies the style upon which the current style is based-that is, the style from which the current style inherits. It is the mechanism for implementing style inheritance.
|
||||||
|
* Note that if the type of the current style must match the type of the style upon which it is based or the basedOn element will be ignored.
|
||||||
|
* However, if the current style is a numbering style, then the `basedOn` element is ignored.
|
||||||
|
*
|
||||||
|
* **WARNING**: You cannot set `basedOn` to be the same as `name`. This is akin to inheriting from itself. This creates a cyclic dependency and cause undesirable behavior.
|
||||||
|
*/
|
||||||
readonly basedOn?: string;
|
readonly basedOn?: string;
|
||||||
readonly next?: string;
|
readonly next?: string;
|
||||||
readonly link?: string;
|
readonly link?: string;
|
||||||
|
@ -86,6 +86,59 @@ describe("paragraph-split-inject", () => {
|
|||||||
),
|
),
|
||||||
).to.throw();
|
).to.throw();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should continue if text run doesn't have text", () => {
|
||||||
|
expect(() =>
|
||||||
|
findRunElementIndexWithToken(
|
||||||
|
{
|
||||||
|
name: "w:p",
|
||||||
|
type: "element",
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
name: "w:r",
|
||||||
|
type: "element",
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
name: "w:t",
|
||||||
|
type: "element",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"hello",
|
||||||
|
),
|
||||||
|
).to.throw();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should continue if text run doesn't have text", () => {
|
||||||
|
expect(() =>
|
||||||
|
findRunElementIndexWithToken(
|
||||||
|
{
|
||||||
|
name: "w:p",
|
||||||
|
type: "element",
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
name: "w:r",
|
||||||
|
type: "element",
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
name: "w:t",
|
||||||
|
type: "element",
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"hello",
|
||||||
|
),
|
||||||
|
).to.throw();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("splitRunElement", () => {
|
describe("splitRunElement", () => {
|
||||||
|
@ -8,7 +8,11 @@ export const findRunElementIndexWithToken = (paragraphElement: Element, token: s
|
|||||||
const textElement = (element.elements ?? []).filter((e) => e.type === "element" && e.name === "w:t");
|
const textElement = (element.elements ?? []).filter((e) => e.type === "element" && e.name === "w:t");
|
||||||
|
|
||||||
for (const text of textElement) {
|
for (const text of textElement) {
|
||||||
if ((text.elements?.[0].text as string)?.includes(token)) {
|
if (!text.elements?.[0]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((text.elements[0].text as string)?.includes(token)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { convertInchesToTwip, convertMillimetersToTwip, uniqueId, uniqueNumericId } from "./convenience-functions";
|
import { convertInchesToTwip, convertMillimetersToTwip, uniqueId, uniqueNumericIdCreator } from "./convenience-functions";
|
||||||
|
|
||||||
describe("Utility", () => {
|
describe("Utility", () => {
|
||||||
describe("#convertMillimetersToTwip", () => {
|
describe("#convertMillimetersToTwip", () => {
|
||||||
@ -17,8 +17,9 @@ describe("Utility", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#uniqueNumericId", () => {
|
describe("#uniqueNumericIdCreator", () => {
|
||||||
it("should generate a unique incrementing ID", () => {
|
it("should generate a unique incrementing ID", () => {
|
||||||
|
const uniqueNumericId = uniqueNumericIdCreator();
|
||||||
expect(uniqueNumericId()).to.not.be.undefined;
|
expect(uniqueNumericId()).to.not.be.undefined;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,19 @@
|
|||||||
import { nanoid } from "nanoid/non-secure";
|
import { nanoid } from "nanoid/non-secure";
|
||||||
|
|
||||||
let currentCount = 0;
|
|
||||||
|
|
||||||
// Twip - twentieths of a point
|
// Twip - twentieths of a point
|
||||||
export const convertMillimetersToTwip = (millimeters: number): number => Math.floor((millimeters / 25.4) * 72 * 20);
|
export const convertMillimetersToTwip = (millimeters: number): number => Math.floor((millimeters / 25.4) * 72 * 20);
|
||||||
|
|
||||||
export const convertInchesToTwip = (inches: number): number => Math.floor(inches * 72 * 20);
|
export const convertInchesToTwip = (inches: number): number => Math.floor(inches * 72 * 20);
|
||||||
|
|
||||||
export const uniqueNumericId = (): number => ++currentCount;
|
export const uniqueNumericIdCreator = (initial = 0): (() => number) => {
|
||||||
|
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 uniqueId = (): string => nanoid().toLowerCase();
|
export const uniqueId = (): string => nanoid().toLowerCase();
|
||||||
|
Reference in New Issue
Block a user