Merge remote-tracking branch 'github.com/master'
This commit is contained in:
8
.github/workflows/default.yml
vendored
8
.github/workflows/default.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci
|
run: npm ci --force
|
||||||
- name: Build
|
- name: Build
|
||||||
run: npm run build
|
run: npm run build
|
||||||
- name: Archive Production Artifact
|
- name: Archive Production Artifact
|
||||||
@ -30,7 +30,7 @@ jobs:
|
|||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci
|
run: npm ci --force
|
||||||
- name: Test
|
- name: Test
|
||||||
run: npm run test.coverage
|
run: npm run test.coverage
|
||||||
- name: Codecov
|
- name: Codecov
|
||||||
@ -45,7 +45,7 @@ jobs:
|
|||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci
|
run: npm ci --force
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: npm run lint
|
run: npm run lint
|
||||||
prettier:
|
prettier:
|
||||||
@ -55,6 +55,6 @@ jobs:
|
|||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci
|
run: npm ci --force
|
||||||
- name: Prettier
|
- name: Prettier
|
||||||
run: npm run style
|
run: npm run style
|
||||||
|
4
.github/workflows/demos.yml
vendored
4
.github/workflows/demos.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci
|
run: npm ci --force
|
||||||
- name: Build
|
- name: Build
|
||||||
run: npm run build
|
run: npm run build
|
||||||
- name: Archive Production Artifact
|
- name: Archive Production Artifact
|
||||||
@ -31,7 +31,7 @@ jobs:
|
|||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci
|
run: npm ci --force
|
||||||
- name: Download Artifact
|
- name: Download Artifact
|
||||||
uses: actions/download-artifact@master
|
uses: actions/download-artifact@master
|
||||||
with:
|
with:
|
||||||
|
4
.github/workflows/github-pages.yml
vendored
4
.github/workflows/github-pages.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
|||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci
|
run: npm ci --force
|
||||||
- name: Build 🔧
|
- name: Build 🔧
|
||||||
run: |
|
run: |
|
||||||
npm run typedoc
|
npm run typedoc
|
||||||
@ -30,7 +30,7 @@ jobs:
|
|||||||
- name: Checkout Repo 🛎️
|
- name: Checkout Repo 🛎️
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci
|
run: npm ci --force
|
||||||
- name: Download Artifact
|
- name: Download Artifact
|
||||||
uses: actions/download-artifact@master
|
uses: actions/download-artifact@master
|
||||||
with:
|
with:
|
||||||
|
13
.mocharc.json
Normal file
13
.mocharc.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"diff": true,
|
||||||
|
"spec": "src/**/*.ts",
|
||||||
|
"extension": ["ts"],
|
||||||
|
"package": "./package.json",
|
||||||
|
"reporter": "spec",
|
||||||
|
"slow": "75",
|
||||||
|
"timeout": "2000",
|
||||||
|
"ui": "bdd",
|
||||||
|
"watch-files": ["src/**/*.ts"],
|
||||||
|
"watch-ignore": ["build", "demo"],
|
||||||
|
"require": ["mocha.env", "ts-node/register", "tsconfig-paths/register"]
|
||||||
|
}
|
@ -11,7 +11,6 @@
|
|||||||
[![NPM version][npm-image]][npm-url]
|
[![NPM version][npm-image]][npm-url]
|
||||||
[![Downloads per month][downloads-image]][downloads-url]
|
[![Downloads per month][downloads-image]][downloads-url]
|
||||||
[![GitHub Action Workflow Status][github-actions-workflow-image]][github-actions-workflow-url]
|
[![GitHub Action Workflow Status][github-actions-workflow-image]][github-actions-workflow-url]
|
||||||
[![Dependency Status][daviddm-image]][daviddm-url]
|
|
||||||
[![Known Vulnerabilities][snky-image]][snky-url]
|
[![Known Vulnerabilities][snky-image]][snky-url]
|
||||||
[![Chat on Gitter][gitter-image]][gitter-url]
|
[![Chat on Gitter][gitter-image]][gitter-url]
|
||||||
[![PRs Welcome][pr-image]][pr-url]
|
[![PRs Welcome][pr-image]][pr-url]
|
||||||
@ -105,8 +104,6 @@ Made with 💖
|
|||||||
[downloads-url]: https://npmjs.org/package/docx
|
[downloads-url]: https://npmjs.org/package/docx
|
||||||
[github-actions-workflow-image]: https://github.com/dolanmiu/docx/workflows/Default/badge.svg
|
[github-actions-workflow-image]: https://github.com/dolanmiu/docx/workflows/Default/badge.svg
|
||||||
[github-actions-workflow-url]: https://github.com/dolanmiu/docx/actions
|
[github-actions-workflow-url]: https://github.com/dolanmiu/docx/actions
|
||||||
[daviddm-image]: https://david-dm.org/dolanmiu/docx.svg?theme=shields.io
|
|
||||||
[daviddm-url]: https://david-dm.org/dolanmiu/docx
|
|
||||||
[snky-image]: https://snyk.io/test/github/dolanmiu/docx/badge.svg
|
[snky-image]: https://snyk.io/test/github/dolanmiu/docx/badge.svg
|
||||||
[snky-url]: https://snyk.io/test/github/dolanmiu/docx
|
[snky-url]: https://snyk.io/test/github/dolanmiu/docx
|
||||||
[gitter-image]: https://badges.gitter.im/dolanmiu/docx.svg
|
[gitter-image]: https://badges.gitter.im/dolanmiu/docx.svg
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Numbering and bullet points example
|
// Numbering and bullet points example
|
||||||
// Import from 'docx' rather than '../build' if you install from npm
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { AlignmentType, convertInchesToTwip, Document, HeadingLevel, LevelFormat, Packer, Paragraph } from "../build";
|
import { AlignmentType, convertInchesToTwip, Document, Footer, Header, HeadingLevel, LevelFormat, Packer, Paragraph } from "../build";
|
||||||
|
|
||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
numbering: {
|
numbering: {
|
||||||
@ -119,6 +119,46 @@ const doc = new Document({
|
|||||||
},
|
},
|
||||||
sections: [
|
sections: [
|
||||||
{
|
{
|
||||||
|
headers: {
|
||||||
|
default: new Header({
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
text: "Hey you",
|
||||||
|
numbering: {
|
||||||
|
reference: "my-crazy-numbering",
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "What's up fam",
|
||||||
|
numbering: {
|
||||||
|
reference: "my-crazy-numbering",
|
||||||
|
level: 1,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
footers: {
|
||||||
|
default: new Footer({
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
text: "Hey you",
|
||||||
|
numbering: {
|
||||||
|
reference: "my-crazy-numbering",
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "What's up fam",
|
||||||
|
numbering: {
|
||||||
|
reference: "my-crazy-numbering",
|
||||||
|
level: 1,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
},
|
||||||
children: [
|
children: [
|
||||||
new Paragraph({
|
new Paragraph({
|
||||||
text: "Hey you",
|
text: "Hey you",
|
||||||
|
37
demo/72-word-wrap.ts
Normal file
37
demo/72-word-wrap.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Example on how to preserve word wrap text. Works with all languages.
|
||||||
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { Document, Packer, Paragraph, TextRun, SpaceType } from "../build";
|
||||||
|
|
||||||
|
const doc = new Document({
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun("我今天遛狗去公园"),
|
||||||
|
new TextRun({
|
||||||
|
text: "456435234523456435564745673456345456435234523456435564745673456345456435234523456435564745673456345456435234523456435564745673456345456435234523456435564745673456345",
|
||||||
|
space: SpaceType.PRESERVE,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun(
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua",
|
||||||
|
),
|
||||||
|
new TextRun({
|
||||||
|
text: "456435234523456435564745673456345456435234523456435564745673456345456435234523456435564745673456345456435234523456435564745673456345456435234523456435564745673456345",
|
||||||
|
space: SpaceType.PRESERVE,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
Packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
|
});
|
@ -42,6 +42,17 @@ Example showing basic header and footer
|
|||||||
|
|
||||||
_Source: https://github.com/dolanmiu/docx/blob/master/demo/8-header-footer.ts_
|
_Source: https://github.com/dolanmiu/docx/blob/master/demo/8-header-footer.ts_
|
||||||
|
|
||||||
|
## Different First Page
|
||||||
|
|
||||||
|
To specify `'Different First Page'`, set `titlePage: true` in the sections array as shown below.
|
||||||
|
|
||||||
|
```
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
properties: {
|
||||||
|
titlePage: true,
|
||||||
|
```
|
||||||
|
|
||||||
## Multiple Headers and Footers
|
## Multiple Headers and Footers
|
||||||
|
|
||||||
More headers and footers can be accomplished by creating more `Section`. New headers and footers can be set per `Section`
|
More headers and footers can be accomplished by creating more `Section`. New headers and footers can be set per `Section`
|
||||||
|
9503
package-lock.json
generated
9503
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
@ -5,7 +5,7 @@
|
|||||||
"main": "build/index.js",
|
"main": "build/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"pretest": "rimraf ./build",
|
"pretest": "rimraf ./build",
|
||||||
"test": "cross-env TS_NODE_PROJECT=\"tsconfig.spec.json\" mocha -r ts-node/register -r tsconfig-paths/register \"src/**/*.ts\"",
|
"test": "mocha --config=.mocharc.json",
|
||||||
"test.coverage": "nyc npm test",
|
"test.coverage": "nyc npm test",
|
||||||
"test.watch": "npm test -- --watch",
|
"test.watch": "npm test -- --watch",
|
||||||
"prepublishOnly": "npm run build --production",
|
"prepublishOnly": "npm run build --production",
|
||||||
@ -49,7 +49,7 @@
|
|||||||
],
|
],
|
||||||
"types": "./build/index.d.ts",
|
"types": "./build/index.d.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "^17.0.0",
|
"@types/node": "^18.0.0",
|
||||||
"jszip": "^3.1.5",
|
"jszip": "^3.1.5",
|
||||||
"nanoid": "^3.1.20",
|
"nanoid": "^3.1.20",
|
||||||
"xml": "^1.0.1",
|
"xml": "^1.0.1",
|
||||||
@ -73,11 +73,10 @@
|
|||||||
"@types/webpack": "^5.0.0",
|
"@types/webpack": "^5.0.0",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"chai": "^3.5.0",
|
"chai": "^3.5.0",
|
||||||
"cross-env": "^7.0.3",
|
|
||||||
"docsify-cli": "^4.3.0",
|
"docsify-cli": "^4.3.0",
|
||||||
"glob": "^7.1.2",
|
"glob": "^8.0.1",
|
||||||
"jszip": "^3.1.5",
|
"jszip": "^3.1.5",
|
||||||
"mocha": "^9.0.2",
|
"mocha": "^10.0.0",
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^15.1.0",
|
||||||
"pre-commit": "^1.2.2",
|
"pre-commit": "^1.2.2",
|
||||||
"prettier": "^2.3.1",
|
"prettier": "^2.3.1",
|
||||||
@ -88,15 +87,15 @@
|
|||||||
"request-promise": "^4.2.2",
|
"request-promise": "^4.2.2",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"shelljs": "^0.8.4",
|
"shelljs": "^0.8.4",
|
||||||
"sinon": "^13.0.0",
|
"sinon": "^14.0.0",
|
||||||
"stream-browserify": "^3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
"ts-loader": "^9.0.0",
|
"ts-loader": "^9.0.0",
|
||||||
"ts-node": "^10.2.1",
|
"ts-node": "^10.2.1",
|
||||||
"tsconfig-paths": "^3.9.0",
|
"tsconfig-paths": "^4.0.0",
|
||||||
"tslint": "^6.1.3",
|
"tslint": "^6.1.3",
|
||||||
"tslint-immutable": "^6.0.1",
|
"tslint-immutable": "^6.0.1",
|
||||||
"typedoc": "^0.22.3",
|
"typedoc": "^0.22.3",
|
||||||
"typescript": "4.6.2",
|
"typescript": "4.7.3",
|
||||||
"unzipper": "^0.10.11",
|
"unzipper": "^0.10.11",
|
||||||
"webpack": "^5.28.0",
|
"webpack": "^5.28.0",
|
||||||
"webpack-cli": "^4.6.0"
|
"webpack-cli": "^4.6.0"
|
||||||
|
@ -43,19 +43,27 @@ describe("Compiler", () => {
|
|||||||
sections: [
|
sections: [
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
default: new Header(),
|
default: new Header({
|
||||||
|
children: [new Paragraph("test")],
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
footers: {
|
footers: {
|
||||||
default: new Footer(),
|
default: new Footer({
|
||||||
|
children: [new Paragraph("test")],
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
default: new Header(),
|
default: new Header({
|
||||||
|
children: [new Paragraph("test")],
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
footers: {
|
footers: {
|
||||||
default: new Footer(),
|
default: new Footer({
|
||||||
|
children: [new Paragraph("test")],
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
@ -99,5 +107,39 @@ describe("Compiler", () => {
|
|||||||
compiler.compile(file);
|
compiler.compile(file);
|
||||||
expect(spy.callCount).to.equal(12);
|
expect(spy.callCount).to.equal(12);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should work with media datas", () => {
|
||||||
|
// This test is required because before, there was a case where Document was formatted twice, which was inefficient
|
||||||
|
// This also caused issues such as running prepForXml multiple times as format() was ran multiple times.
|
||||||
|
const paragraph = new Paragraph("");
|
||||||
|
const file = new File({
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
properties: {},
|
||||||
|
children: [paragraph],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// tslint:disable-next-line: no-string-literal
|
||||||
|
sinon.stub(compiler["imageReplacer"], "getMediaData").returns([
|
||||||
|
{
|
||||||
|
stream: Buffer.from(""),
|
||||||
|
fileName: "test",
|
||||||
|
transformation: {
|
||||||
|
pixels: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
emus: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
compiler.compile(file);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -280,8 +280,10 @@ export class Compiler {
|
|||||||
// TODO: 0 needs to be changed when headers get relationships of their own
|
// TODO: 0 needs to be changed when headers get relationships of their own
|
||||||
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0);
|
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0);
|
||||||
|
|
||||||
|
const referenedXmlData = this.numberingReplacer.replace(xmlData, file.Numbering.ConcreteNumbering);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: xmlData,
|
data: referenedXmlData,
|
||||||
path: `word/header${index + 1}.xml`,
|
path: `word/header${index + 1}.xml`,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
@ -302,8 +304,10 @@ export class Compiler {
|
|||||||
// TODO: 0 needs to be changed when headers get relationships of their own
|
// TODO: 0 needs to be changed when headers get relationships of their own
|
||||||
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0);
|
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0);
|
||||||
|
|
||||||
|
const referenedXmlData = this.numberingReplacer.replace(xmlData, file.Numbering.ConcreteNumbering);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: xmlData,
|
data: referenedXmlData,
|
||||||
path: `word/footer${index + 1}.xml`,
|
path: `word/footer${index + 1}.xml`,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
@ -19,3 +19,4 @@ export * from "./shared";
|
|||||||
export * from "./border";
|
export * from "./border";
|
||||||
export * from "./values";
|
export * from "./values";
|
||||||
export * from "./vertical-align";
|
export * from "./vertical-align";
|
||||||
|
export * from "./space-type";
|
||||||
|
@ -82,5 +82,75 @@ describe("FrameProperties", () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should create without x and y", () => {
|
||||||
|
const currentFrameProperties = new FrameProperties({
|
||||||
|
width: 4000,
|
||||||
|
height: 1000,
|
||||||
|
anchor: {
|
||||||
|
horizontal: FrameAnchorType.MARGIN,
|
||||||
|
vertical: FrameAnchorType.MARGIN,
|
||||||
|
},
|
||||||
|
alignment: {
|
||||||
|
x: HorizontalPositionAlign.CENTER,
|
||||||
|
y: VerticalPositionAlign.TOP,
|
||||||
|
},
|
||||||
|
space: {
|
||||||
|
horizontal: 100,
|
||||||
|
vertical: 200,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const tree = new Formatter().format(currentFrameProperties);
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:framePr": {
|
||||||
|
_attr: {
|
||||||
|
"w:h": 1000,
|
||||||
|
"w:hAnchor": "margin",
|
||||||
|
"w:vAnchor": "margin",
|
||||||
|
"w:w": 4000,
|
||||||
|
"w:xAlign": "center",
|
||||||
|
"w:yAlign": "top",
|
||||||
|
"w:hSpace": 100,
|
||||||
|
"w:vSpace": 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create without alignments", () => {
|
||||||
|
const currentFrameProperties = new FrameProperties({
|
||||||
|
position: {
|
||||||
|
x: 1000,
|
||||||
|
y: 3000,
|
||||||
|
},
|
||||||
|
width: 4000,
|
||||||
|
height: 1000,
|
||||||
|
anchor: {
|
||||||
|
horizontal: FrameAnchorType.MARGIN,
|
||||||
|
vertical: FrameAnchorType.MARGIN,
|
||||||
|
},
|
||||||
|
space: {
|
||||||
|
horizontal: 100,
|
||||||
|
vertical: 200,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const tree = new Formatter().format(currentFrameProperties);
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:framePr": {
|
||||||
|
_attr: {
|
||||||
|
"w:h": 1000,
|
||||||
|
"w:hAnchor": "margin",
|
||||||
|
"w:vAnchor": "margin",
|
||||||
|
"w:w": 4000,
|
||||||
|
"w:x": 1000,
|
||||||
|
"w:y": 3000,
|
||||||
|
"w:hSpace": 100,
|
||||||
|
"w:vSpace": 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -24,15 +24,11 @@ export enum FrameWrap {
|
|||||||
TIGHT = "tight",
|
TIGHT = "tight",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IFrameOptions {
|
interface IBaseFrameOptions {
|
||||||
readonly anchorLock?: boolean;
|
readonly anchorLock?: boolean;
|
||||||
readonly dropCap?: DropCapType;
|
readonly dropCap?: DropCapType;
|
||||||
readonly width: number;
|
readonly width: number;
|
||||||
readonly height: number;
|
readonly height: number;
|
||||||
readonly position: {
|
|
||||||
readonly x: number;
|
|
||||||
readonly y: number;
|
|
||||||
};
|
|
||||||
readonly wrap?: FrameWrap;
|
readonly wrap?: FrameWrap;
|
||||||
readonly lines?: number;
|
readonly lines?: number;
|
||||||
readonly anchor: {
|
readonly anchor: {
|
||||||
@ -44,19 +40,33 @@ export interface IFrameOptions {
|
|||||||
readonly vertical: number;
|
readonly vertical: number;
|
||||||
};
|
};
|
||||||
readonly rule?: HeightRule;
|
readonly rule?: HeightRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IXYFrameOptions extends IBaseFrameOptions {
|
||||||
|
readonly position: {
|
||||||
|
readonly x: number;
|
||||||
|
readonly y: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAlignmentFrameOptions extends IBaseFrameOptions {
|
||||||
readonly alignment: {
|
readonly alignment: {
|
||||||
readonly x: HorizontalPositionAlign;
|
readonly x: HorizontalPositionAlign;
|
||||||
readonly y: VerticalPositionAlign;
|
readonly y: VerticalPositionAlign;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Be wary of Typescript's Open types:
|
||||||
|
// https://stackoverflow.com/q/46370222/3481582
|
||||||
|
export type IFrameOptions = IXYFrameOptions | IAlignmentFrameOptions;
|
||||||
|
|
||||||
export class FramePropertiesAttributes extends XmlAttributeComponent<{
|
export class FramePropertiesAttributes extends XmlAttributeComponent<{
|
||||||
readonly anchorLock?: boolean;
|
readonly anchorLock?: boolean;
|
||||||
readonly dropCap?: DropCapType;
|
readonly dropCap?: DropCapType;
|
||||||
readonly width: number;
|
readonly width: number;
|
||||||
readonly height: number;
|
readonly height: number;
|
||||||
readonly x: number;
|
readonly x?: number;
|
||||||
readonly y: number;
|
readonly y?: number;
|
||||||
readonly wrap?: FrameWrap;
|
readonly wrap?: FrameWrap;
|
||||||
readonly lines?: number;
|
readonly lines?: number;
|
||||||
readonly anchorHorizontal?: FrameAnchorType;
|
readonly anchorHorizontal?: FrameAnchorType;
|
||||||
@ -95,15 +105,15 @@ export class FrameProperties extends XmlComponent {
|
|||||||
dropCap: options.dropCap,
|
dropCap: options.dropCap,
|
||||||
width: options.width,
|
width: options.width,
|
||||||
height: options.height,
|
height: options.height,
|
||||||
x: options.position.x,
|
x: (options as IXYFrameOptions).position ? (options as IXYFrameOptions).position.x : undefined,
|
||||||
y: options.position.y,
|
y: (options as IXYFrameOptions).position ? (options as IXYFrameOptions).position.y : undefined,
|
||||||
anchorHorizontal: options.anchor.horizontal,
|
anchorHorizontal: options.anchor.horizontal,
|
||||||
anchorVertical: options.anchor.vertical,
|
anchorVertical: options.anchor.vertical,
|
||||||
spaceHorizontal: options.space?.horizontal,
|
spaceHorizontal: options.space?.horizontal,
|
||||||
spaceVertical: options.space?.vertical,
|
spaceVertical: options.space?.vertical,
|
||||||
rule: options.rule,
|
rule: options.rule,
|
||||||
alignmentX: options.alignment.x,
|
alignmentX: (options as IAlignmentFrameOptions).alignment ? (options as IAlignmentFrameOptions).alignment.x : undefined,
|
||||||
alignmentY: options.alignment.y,
|
alignmentY: (options as IAlignmentFrameOptions).alignment ? (options as IAlignmentFrameOptions).alignment.y : undefined,
|
||||||
lines: options.lines,
|
lines: options.lines,
|
||||||
wrap: options.wrap,
|
wrap: options.wrap,
|
||||||
}),
|
}),
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import { SpaceType } from "file/space-type";
|
import { SpaceType } from "file/space-type";
|
||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
import { IPageReferenceOptions } from "./pageref-properties";
|
|
||||||
|
|
||||||
class TextAttributes extends XmlAttributeComponent<{ readonly space: SpaceType }> {
|
import { TextAttributes } from "../run/text-attributes";
|
||||||
protected readonly xmlKeys = { space: "xml:space" };
|
import { IPageReferenceOptions } from "./pageref-properties";
|
||||||
}
|
|
||||||
|
|
||||||
export class PageReferenceFieldInstruction extends XmlComponent {
|
export class PageReferenceFieldInstruction extends XmlComponent {
|
||||||
constructor(bookmarkId: string, options: IPageReferenceOptions = {}) {
|
constructor(bookmarkId: string, options: IPageReferenceOptions = {}) {
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import { SpaceType } from "file/space-type";
|
import { SpaceType } from "file/space-type";
|
||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
class TextAttributes extends XmlAttributeComponent<{ readonly space: SpaceType }> {
|
import { TextAttributes } from "./text-attributes";
|
||||||
protected readonly xmlKeys = { space: "xml:space" };
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Page extends XmlComponent {
|
export class Page extends XmlComponent {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { ChangeAttributes, IChangedAttributesProperties } from "../../track-revision/track-revision";
|
|
||||||
|
|
||||||
import { BorderElement, IBorderOptions } from "file/border";
|
import { BorderElement, IBorderOptions } from "file/border";
|
||||||
import { IShadingAttributesProperties, Shading } from "file/shading";
|
import { IShadingAttributesProperties, Shading } from "file/shading";
|
||||||
|
import { SpaceType } from "file/space-type";
|
||||||
|
import { ChangeAttributes, IChangedAttributesProperties } from "file/track-revision/track-revision";
|
||||||
import { HpsMeasureElement, IgnoreIfEmptyXmlComponent, OnOffElement, StringValueElement, XmlComponent } from "file/xml-components";
|
import { HpsMeasureElement, IgnoreIfEmptyXmlComponent, OnOffElement, StringValueElement, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
import { EmphasisMark, EmphasisMarkType } from "./emphasis-mark";
|
import { EmphasisMark, EmphasisMarkType } from "./emphasis-mark";
|
||||||
import { CharacterSpacing, Color, Highlight, HighlightComplexScript } from "./formatting";
|
import { CharacterSpacing, Color, Highlight, HighlightComplexScript } from "./formatting";
|
||||||
import { IFontAttributesProperties, RunFonts } from "./run-fonts";
|
import { IFontAttributesProperties, RunFonts } from "./run-fonts";
|
||||||
@ -45,6 +46,7 @@ export interface IRunStylePropertiesOptions {
|
|||||||
readonly imprint?: boolean;
|
readonly imprint?: boolean;
|
||||||
readonly revision?: IRunPropertiesChangeOptions;
|
readonly revision?: IRunPropertiesChangeOptions;
|
||||||
readonly border?: IBorderOptions;
|
readonly border?: IBorderOptions;
|
||||||
|
readonly space?: SpaceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRunPropertiesOptions extends IRunStylePropertiesOptions {
|
export interface IRunPropertiesOptions extends IRunStylePropertiesOptions {
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import { SpaceType } from "file/space-type";
|
import { SpaceType } from "file/space-type";
|
||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
class TextAttributes extends XmlAttributeComponent<{ readonly space: SpaceType }> {
|
import { TextAttributes } from "../text-attributes";
|
||||||
protected readonly xmlKeys = { space: "xml:space" };
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Text extends XmlComponent {
|
export class Text extends XmlComponent {
|
||||||
constructor(text: string) {
|
constructor(text: string) {
|
||||||
|
@ -4,6 +4,7 @@ import { Formatter } from "export/formatter";
|
|||||||
import { BorderStyle } from "file/border";
|
import { BorderStyle } from "file/border";
|
||||||
// import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run";
|
// import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run";
|
||||||
import { ShadingType } from "file/shading";
|
import { ShadingType } from "file/shading";
|
||||||
|
import { SpaceType } from "file/space-type";
|
||||||
|
|
||||||
import { Run } from "./";
|
import { Run } from "./";
|
||||||
import { EmphasisMarkType } from "./emphasis-mark";
|
import { EmphasisMarkType } from "./emphasis-mark";
|
||||||
@ -521,4 +522,20 @@ describe("Run", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("#space", () => {
|
||||||
|
it("should correctly set the border", () => {
|
||||||
|
const run = new Run({
|
||||||
|
space: SpaceType.PRESERVE,
|
||||||
|
});
|
||||||
|
const tree = new Formatter().format(run);
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:r": {
|
||||||
|
_attr: {
|
||||||
|
"xml:space": "preserve",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,11 +3,13 @@ import { XmlComponent } from "file/xml-components";
|
|||||||
|
|
||||||
import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run";
|
import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run";
|
||||||
import { FieldInstruction } from "file/table-of-contents/field-instruction";
|
import { FieldInstruction } from "file/table-of-contents/field-instruction";
|
||||||
|
|
||||||
import { Break } from "./break";
|
import { Break } from "./break";
|
||||||
import { Begin, End, Separate } from "./field";
|
import { Begin, End, Separate } from "./field";
|
||||||
import { NumberOfPages, NumberOfPagesSection, Page } from "./page-number";
|
import { NumberOfPages, NumberOfPagesSection, Page } from "./page-number";
|
||||||
import { IRunPropertiesOptions, RunProperties } from "./properties";
|
import { IRunPropertiesOptions, RunProperties } from "./properties";
|
||||||
import { Text } from "./run-components/text";
|
import { Text } from "./run-components/text";
|
||||||
|
import { TextAttributes } from "./text-attributes";
|
||||||
|
|
||||||
export interface IRunOptions extends IRunPropertiesOptions {
|
export interface IRunOptions extends IRunPropertiesOptions {
|
||||||
readonly children?: (Begin | FieldInstruction | Separate | End | PageNumber | FootnoteReferenceRun | string)[];
|
readonly children?: (Begin | FieldInstruction | Separate | End | PageNumber | FootnoteReferenceRun | string)[];
|
||||||
@ -35,6 +37,10 @@ export class Run extends XmlComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.space) {
|
||||||
|
this.root.push(new TextAttributes({ space: options.space }));
|
||||||
|
}
|
||||||
|
|
||||||
if (options.children) {
|
if (options.children) {
|
||||||
for (const child of options.children) {
|
for (const child of options.children) {
|
||||||
if (typeof child === "string") {
|
if (typeof child === "string") {
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
// http://officeopenxml.com/WPfieldInstructions.php
|
// http://officeopenxml.com/WPfieldInstructions.php
|
||||||
import { SpaceType } from "file/space-type";
|
import { SpaceType } from "file/space-type";
|
||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
class TextAttributes extends XmlAttributeComponent<{ readonly space: SpaceType }> {
|
import { TextAttributes } from "./text-attributes";
|
||||||
protected readonly xmlKeys = { space: "xml:space" };
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SequentialIdentifierInstruction extends XmlComponent {
|
export class SequentialIdentifierInstruction extends XmlComponent {
|
||||||
constructor(identifier: string) {
|
constructor(identifier: string) {
|
||||||
|
6
src/file/paragraph/run/text-attributes.ts
Normal file
6
src/file/paragraph/run/text-attributes.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { SpaceType } from "file/space-type";
|
||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export class TextAttributes extends XmlAttributeComponent<{ readonly space: SpaceType }> {
|
||||||
|
protected readonly xmlKeys = { space: "xml:space" };
|
||||||
|
}
|
@ -1,11 +1,9 @@
|
|||||||
// http://officeopenxml.com/WPfieldInstructions.php
|
// http://officeopenxml.com/WPfieldInstructions.php
|
||||||
|
import { TextAttributes } from "file/paragraph/run/text-attributes";
|
||||||
import { SpaceType } from "file/space-type";
|
import { SpaceType } from "file/space-type";
|
||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
import { ITableOfContentsOptions } from "./table-of-contents-properties";
|
|
||||||
|
|
||||||
class TextAttributes extends XmlAttributeComponent<{ readonly space: SpaceType }> {
|
import { ITableOfContentsOptions } from "./table-of-contents-properties";
|
||||||
protected readonly xmlKeys = { space: "xml:space" };
|
|
||||||
}
|
|
||||||
|
|
||||||
export class FieldInstruction extends XmlComponent {
|
export class FieldInstruction extends XmlComponent {
|
||||||
private readonly properties: ITableOfContentsOptions;
|
private readonly properties: ITableOfContentsOptions;
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
|
import { TextAttributes } from "file/paragraph/run/text-attributes";
|
||||||
import { SpaceType } from "file/space-type";
|
import { SpaceType } from "file/space-type";
|
||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
class TextAttributes extends XmlAttributeComponent<{ readonly space: SpaceType }> {
|
|
||||||
protected readonly xmlKeys = { space: "xml:space" };
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DeletedPage extends XmlComponent {
|
export class DeletedPage extends XmlComponent {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
|
import { TextAttributes } from "file/paragraph/run/text-attributes";
|
||||||
import { SpaceType } from "file/space-type";
|
import { SpaceType } from "file/space-type";
|
||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
class TextAttributes extends XmlAttributeComponent<{ readonly space: SpaceType }> {
|
|
||||||
protected readonly xmlKeys = { space: "xml:space" };
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DeletedText extends XmlComponent {
|
export class DeletedText extends XmlComponent {
|
||||||
constructor(text: string) {
|
constructor(text: string) {
|
||||||
|
Reference in New Issue
Block a user