Compare commits
155 Commits
Author | SHA1 | Date | |
---|---|---|---|
6eb11d8842 | |||
3ad68337e7 | |||
07f363fcb7 | |||
2d2e4cdab2 | |||
0cadec7f58 | |||
e86dbd3398 | |||
021f1b0c4d | |||
5aa2027252 | |||
2fc297ef3c | |||
3fe216846c | |||
649a50f7c5 | |||
dc14123a5a | |||
048a035a5d | |||
f212cf0251 | |||
1f2f5988e1 | |||
f1359a4750 | |||
f2775ed13c | |||
3ae749278e | |||
0bcc6910f4 | |||
c15951550c | |||
8308b6413e | |||
5b75875684 | |||
28029f4c1c | |||
824d7f9893 | |||
b3aea4b9a0 | |||
32377d187d | |||
a80815822d | |||
c198154fdc | |||
618c7a8578 | |||
ef7b930d4d | |||
8296895cc6 | |||
1dce6fee15 | |||
444e7771b4 | |||
962795743c | |||
f98f852a55 | |||
e379a7fe04 | |||
022b25cfcd | |||
e20bd66663 | |||
6b8e22368b | |||
4304e82751 | |||
75715fde37 | |||
e779f6ea62 | |||
9280cdba50 | |||
8410d0c06d | |||
d47d85bdcf | |||
6ae45327fe | |||
464cd946dc | |||
cbff540b6e | |||
a8e6ba4c49 | |||
efc1ceaf1a | |||
c4ed19e589 | |||
13cf3eee5a | |||
24c159de37 | |||
7570fc2bf5 | |||
6929dee846 | |||
d4ac2a08ee | |||
010ef05ce3 | |||
fa401297da | |||
ce0e9936c3 | |||
c13e9938cf | |||
b8f97553b3 | |||
2550da199d | |||
682b679bdb | |||
e0fd7e751c | |||
9b57db4716 | |||
d23f453d28 | |||
6c28f8bab0 | |||
10b87b5a70 | |||
6b6f9d7ed4 | |||
0434d00ff7 | |||
7e3acc25b9 | |||
62ad8f12b7 | |||
a6a656f1a0 | |||
1bf36009e8 | |||
86bdf3e199 | |||
a3c796aae3 | |||
dbe0586f70 | |||
7e2538dffc | |||
c3080ff9d9 | |||
772fc8462a | |||
e194780cd1 | |||
5b80ea32d7 | |||
31b7e07ab3 | |||
939d418af1 | |||
4258dd2a2e | |||
b7334a1ab5 | |||
9229f45d59 | |||
2bd4aacdd5 | |||
abbd695a8f | |||
f7b98bcde8 | |||
a756a7697c | |||
fd1ea5b4dc | |||
d83e089cd3 | |||
33715cc50c | |||
f3f1f2d0b1 | |||
c35e706fa8 | |||
35cebfe1a2 | |||
d04c42cbe8 | |||
8744e613ac | |||
cbeecbf3e1 | |||
f8ab2d1701 | |||
adc5c6f594 | |||
c9524cc497 | |||
90de6ba7e1 | |||
78d74ae60b | |||
579593a467 | |||
b5393dadae | |||
528ab1933e | |||
36181f8c91 | |||
45af681db1 | |||
ad6b482136 | |||
a6e1c2b019 | |||
3eb98533ae | |||
f5f021834e | |||
35702c3f77 | |||
8fbbd571ad | |||
2dd228be69 | |||
562835cfe7 | |||
6bac06e84d | |||
88436168ee | |||
0c3206d2e2 | |||
033debd339 | |||
d4f160732a | |||
4238fc9ab4 | |||
0d042b8dd1 | |||
afdd5f2d8f | |||
70c7b3d1b3 | |||
7b1cd5fe86 | |||
09ab169ffd | |||
35a82cf12e | |||
8d33cb01dd | |||
438d11dd86 | |||
d23b0d0789 | |||
1fa8c7ac82 | |||
3d6ead0359 | |||
379050dccd | |||
f9d1c197cf | |||
a89ee463e6 | |||
036caaacc8 | |||
80c37afe2b | |||
3a36d912fe | |||
c741d5d8ac | |||
0fa7dd13ad | |||
d5d80550e7 | |||
23a0a59454 | |||
066aa56f6a | |||
3997b7a5d6 | |||
ccc391607a | |||
9577192d41 | |||
968c3aed0f | |||
9c7a80729b | |||
5f26ca1c94 | |||
f2b1587bff | |||
3b9f80fb1a | |||
8da57bec51 |
@ -17,9 +17,11 @@
|
|||||||
"dolan",
|
"dolan",
|
||||||
"execa",
|
"execa",
|
||||||
"falsey",
|
"falsey",
|
||||||
|
"horz",
|
||||||
"iife",
|
"iife",
|
||||||
"Initializable",
|
"Initializable",
|
||||||
"iroha",
|
"iroha",
|
||||||
|
"JOHAB",
|
||||||
"jsonify",
|
"jsonify",
|
||||||
"jszip",
|
"jszip",
|
||||||
"NUMPAGES",
|
"NUMPAGES",
|
||||||
@ -53,7 +55,8 @@
|
|||||||
"\\.to\\.include\\.members\\(\\[[^\\]]+]\\)",
|
"\\.to\\.include\\.members\\(\\[[^\\]]+]\\)",
|
||||||
"/new [a-zA-Z]+\\({[^£]+}\\)/g",
|
"/new [a-zA-Z]+\\({[^£]+}\\)/g",
|
||||||
"/<element name=\"[a-z]+\"/gi",
|
"/<element name=\"[a-z]+\"/gi",
|
||||||
"/<attribute name=\"[a-z]+\"/gi"
|
"/<attribute name=\"[a-z]+\"/gi",
|
||||||
|
"/key: \".+\"/"
|
||||||
],
|
],
|
||||||
"ignorePaths": ["package.json", "docs/api", "*.docx", "build"],
|
"ignorePaths": ["package.json", "docs/api", "*.docx", "build"],
|
||||||
"allowCompoundWords": true,
|
"allowCompoundWords": true,
|
||||||
|
@ -7,7 +7,6 @@ parser: "@typescript-eslint/parser"
|
|||||||
parserOptions:
|
parserOptions:
|
||||||
project:
|
project:
|
||||||
- tsconfig.json
|
- tsconfig.json
|
||||||
- demo/tsconfig.json
|
|
||||||
sourceType: module
|
sourceType: module
|
||||||
plugins:
|
plugins:
|
||||||
- eslint-plugin-import
|
- eslint-plugin-import
|
||||||
@ -93,6 +92,7 @@ rules:
|
|||||||
format:
|
format:
|
||||||
- camelCase
|
- camelCase
|
||||||
- PascalCase
|
- PascalCase
|
||||||
|
- UPPER_CASE # for constants
|
||||||
filter:
|
filter:
|
||||||
regex: (^[a-z]+:.+)|_attr|[0-9]
|
regex: (^[a-z]+:.+)|_attr|[0-9]
|
||||||
match: false
|
match: false
|
||||||
@ -214,8 +214,7 @@ rules:
|
|||||||
valid-typeof: "off"
|
valid-typeof: "off"
|
||||||
functional/immutable-data:
|
functional/immutable-data:
|
||||||
- error
|
- error
|
||||||
- assumeTypes: true
|
- ignoreImmediateMutation: true
|
||||||
ignoreImmediateMutation: true
|
|
||||||
ignoreAccessorPattern:
|
ignoreAccessorPattern:
|
||||||
- "**.root*"
|
- "**.root*"
|
||||||
- "**.numberingReferences*"
|
- "**.numberingReferences*"
|
||||||
|
12
.github/actions/install-and-build/action.yml
vendored
Normal file
12
.github/actions/install-and-build/action.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
name: Install dependencies and build ⚙️
|
||||||
|
description: Install dependencies and build
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Install Dependencies
|
||||||
|
shell: bash
|
||||||
|
run: npm ci --force
|
||||||
|
- name: Build
|
||||||
|
shell: bash
|
||||||
|
run: npm run build
|
14
.github/actions/validate-docx/action.yml
vendored
Normal file
14
.github/actions/validate-docx/action.yml
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
name: Extract and Validate Document ⚙️
|
||||||
|
description: Extract the document and validate the XML against the schema.
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Extract Word Document
|
||||||
|
shell: bash
|
||||||
|
run: npm run extract
|
||||||
|
- name: Validate XML
|
||||||
|
uses: ChristophWurst/xmllint-action@v1
|
||||||
|
with:
|
||||||
|
xml-file: build/extracted-doc/word/document.xml
|
||||||
|
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
25
.github/workflows/default.yml
vendored
25
.github/workflows/default.yml
vendored
@ -13,13 +13,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@v4
|
||||||
- name: Install Dependencies
|
- uses: "./.github/actions/install-and-build"
|
||||||
run: npm ci --force
|
|
||||||
- name: Build
|
|
||||||
run: npm run build
|
|
||||||
- name: Archive Production Artifact
|
- name: Archive Production Artifact
|
||||||
uses: actions/upload-artifact@master
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: build
|
name: build
|
||||||
path: build
|
path: build
|
||||||
@ -28,22 +25,24 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@v4
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci --force
|
run: npm ci --force
|
||||||
- name: Test
|
- name: Test
|
||||||
run: npm run test.ci
|
run: npm run test:ci
|
||||||
- name: Codecov
|
- name: Codecov
|
||||||
uses: codecov/codecov-action@v3
|
uses: codecov/codecov-action@v4
|
||||||
with:
|
with:
|
||||||
fail_ci_if_error: true
|
fail_ci_if_error: true
|
||||||
verbose: true
|
verbose: true
|
||||||
|
env:
|
||||||
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
lint:
|
lint:
|
||||||
name: Lint
|
name: Lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@v4
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci --force
|
run: npm ci --force
|
||||||
- name: Lint
|
- name: Lint
|
||||||
@ -53,17 +52,17 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@v4
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci --force
|
run: npm ci --force
|
||||||
- name: Prettier
|
- name: Prettier
|
||||||
run: npm run style
|
run: npm run prettier
|
||||||
cspell:
|
cspell:
|
||||||
name: CSpell
|
name: CSpell
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@v4
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci --force
|
run: npm ci --force
|
||||||
- name: Prettier
|
- name: Prettier
|
||||||
|
943
.github/workflows/demos.yml
vendored
943
.github/workflows/demos.yml
vendored
@ -8,792 +8,189 @@ on:
|
|||||||
- master
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
|
||||||
name: Build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repo
|
|
||||||
uses: actions/checkout@master
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: npm ci --force
|
|
||||||
- name: Build
|
|
||||||
run: npm run build
|
|
||||||
- name: Archive Production Artifact
|
|
||||||
uses: actions/upload-artifact@master
|
|
||||||
with:
|
|
||||||
name: build
|
|
||||||
path: build
|
|
||||||
demos:
|
demos:
|
||||||
name: Run Demos and Validate
|
name: Demos
|
||||||
needs: [build]
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repo
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@master
|
- uses: "./.github/actions/install-and-build"
|
||||||
- name: Install Dependencies
|
- name: Run Demos
|
||||||
run: npm ci --force
|
run: npm run run-ts -- ./demo/1-basic.ts
|
||||||
- name: Download Artifact
|
- uses: "./.github/actions/validate-docx"
|
||||||
uses: actions/download-artifact@master
|
- run: npm run run-ts -- ./demo/2-declaritive-styles.ts
|
||||||
with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
name: build
|
- run: npm run run-ts -- ./demo/3-numbering-and-bullet-points.ts
|
||||||
path: build
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/4-basic-table.ts
|
||||||
run: npm run ts-node -- ./demo/1-basic.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/5-images.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/6-page-borders.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/7-landscape.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- run: npm run run-ts -- ./demo/8-header-footer.ts
|
||||||
- name: Run Demo
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run ts-node -- ./demo/2-declaritive-styles.ts
|
- run: npm run run-ts -- ./demo/9-images-in-header-and-footer.ts
|
||||||
- name: Extract Word Document
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run extract
|
- run: npm run run-ts -- ./demo/10-my-cv.ts
|
||||||
- name: Validate XML
|
- uses: "./.github/actions/validate-docx"
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/11-declaritive-styles-2.ts
|
||||||
with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/12-scaling-images.ts
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/13-xml-styles.ts
|
||||||
run: npm run ts-node -- ./demo/3-numbering-and-bullet-points.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/14-page-numbers.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/15-page-break-before.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/16-multiple-sections.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- run: npm run run-ts -- ./demo/17-footnotes.ts
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/4-basic-table.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/5-images.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/6-page-borders.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/7-landscape.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/8-header-footer.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/9-images-in-header-and-footer.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/10-my-cv.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/11-declaritive-styles-2.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/12-scaling-images.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/13-xml-styles.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/14-page-numbers.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/15-page-break-before.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/16-multiple-sections.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/17-footnotes.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
# element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected.
|
# element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected.
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/18-image-from-buffer.ts
|
||||||
# with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/19-export-to-base64.ts
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/18-image-from-buffer.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/19-export-to-base64.ts
|
|
||||||
# Base 64 No longer works, abruptly. Node issue?
|
# Base 64 No longer works, abruptly. Node issue?
|
||||||
# - name: Extract Word Document
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# run: npm run extract
|
- run: npm run run-ts -- ./demo/20-table-cell-borders.ts
|
||||||
# - name: Validate XML
|
- uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/21-bookmarks.ts
|
||||||
# with:
|
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/20-table-cell-borders.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/21-bookmarks.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
# Bad ID - need numeric ID
|
# Bad ID - need numeric ID
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/22-right-to-left-text.ts
|
||||||
# with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/23-base64-images.ts
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/24-images-to-table-cell.ts
|
||||||
run: npm run ts-node -- ./demo/22-right-to-left-text.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/25-table-xml-styles.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/26-paragraph-borders.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/27-declaritive-styles-3.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- run: npm run run-ts -- ./demo/28-table-of-contents.ts
|
||||||
- name: Run Demo
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run ts-node -- ./demo/23-base64-images.ts
|
- run: npm run run-ts -- ./demo/29-numbered-lists.ts
|
||||||
- name: Extract Word Document
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run extract
|
- run: npm run run-ts -- ./demo/31-tables.ts
|
||||||
- name: Validate XML
|
- uses: "./.github/actions/validate-docx"
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/32-merge-and-shade-table-cells.ts
|
||||||
with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/33-sequential-captions.ts
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/34-floating-tables.ts
|
||||||
run: npm run ts-node -- ./demo/24-images-to-table-cell.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/25-table-xml-styles.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/26-paragraph-borders.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/27-declaritive-styles-3.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/28-table-of-contents.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/29-numbered-lists.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/31-tables.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/32-merge-and-shade-table-cells.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/33-sequential-captions.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/34-floating-tables.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
# element tblpPr: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tblpPr', attribute 'overlap': The attribute 'overlap' is not allowed.
|
# element tblpPr: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tblpPr', attribute 'overlap': The attribute 'overlap' is not allowed.
|
||||||
# element tblpPr: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tblpPr': Element content is not allowed, because the content type is empty.
|
# element tblpPr: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tblpPr': Element content is not allowed, because the content type is empty.
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/35-hyperlinks.ts
|
||||||
# with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/36-image-to-table-cell.ts
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/37-images-to-header-and-footer.ts
|
||||||
run: npm run ts-node -- ./demo/35-hyperlinks.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/38-text-wrapping.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/39-page-numbers.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/40-line-numbers.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- run: npm run run-ts -- ./demo/41-merge-table-cells-2.ts
|
||||||
- name: Run Demo
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run ts-node -- ./demo/36-image-to-table-cell.ts
|
- run: npm run run-ts -- ./demo/42-restart-page-numbers.ts
|
||||||
- name: Extract Word Document
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run extract
|
- run: npm run run-ts -- ./demo/43-images-to-table-cell-2.ts
|
||||||
- name: Validate XML
|
- uses: "./.github/actions/validate-docx"
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/44-multiple-columns.ts
|
||||||
with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/45-highlighting-text.ts
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/46-shading-text.ts
|
||||||
run: npm run ts-node -- ./demo/37-images-to-header-and-footer.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/47-number-of-total-pages-section.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/48-vertical-align.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/49-table-borders.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- run: npm run run-ts -- ./demo/50-readme-demo.ts
|
||||||
- name: Run Demo
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run ts-node -- ./demo/38-text-wrapping.ts
|
- run: npm run run-ts -- ./demo/51-character-styles.ts
|
||||||
- name: Extract Word Document
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run extract
|
- run: npm run run-ts -- ./demo/52-japanese.ts
|
||||||
- name: Validate XML
|
- uses: "./.github/actions/validate-docx"
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/53-chinese.ts
|
||||||
with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/54-custom-properties.ts
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/55-math.ts
|
||||||
run: npm run ts-node -- ./demo/39-page-numbers.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/40-line-numbers.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/41-merge-table-cells-2.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/42-restart-page-numbers.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/43-images-to-table-cell-2.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/44-multiple-columns.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/45-highlighting-text.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/46-shading-text.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/47-number-of-total-pages-section.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/48-vertical-align.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/49-table-borders.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/50-readme-demo.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/51-character-styles.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/52-japanese.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/53-chinese.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/54-custom-properties.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/55-math.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
#: element subHide: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}subHide': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}ctrlPr ).
|
#: element subHide: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}subHide': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}ctrlPr ).
|
||||||
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sub ).
|
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sub ).
|
||||||
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sup ).
|
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sup ).
|
||||||
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sub ).
|
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sub ).
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/56-background-color.ts
|
||||||
# with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/57-add-parent-numbered-lists.ts
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/58-section-types.ts
|
||||||
run: npm run ts-node -- ./demo/56-background-color.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/59-header-footer-margins.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/60-track-revisions.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/57-add-parent-numbered-lists.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/58-section-types.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/59-header-footer-margins.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/60-track-revisions.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
# element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected.
|
# element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected.
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/61-text-frame.ts
|
||||||
# with:
|
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/61-text-frame.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
# element left: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}left': This element is not expected. Expected is one of ( {http://schemas.openxmlformats.org/wordprocessingml/2006/main}right, {http://schemas.openxmlformats.org/wordprocessingml/2006/main}between, {http://schemas.openxmlformats.org/wordprocessingml/2006/main}bar ).
|
# element left: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}left': This element is not expected. Expected is one of ( {http://schemas.openxmlformats.org/wordprocessingml/2006/main}right, {http://schemas.openxmlformats.org/wordprocessingml/2006/main}between, {http://schemas.openxmlformats.org/wordprocessingml/2006/main}bar ).
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/62-paragraph-spacing.ts
|
||||||
# with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/63-odd-even-header-footer.ts
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/64-complex-numbering-text.ts
|
||||||
run: npm run ts-node -- ./demo/62-paragraph-spacing.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/65-page-sizes.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/66-fields.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/63-odd-even-header-footer.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/64-complex-numbering-text.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/65-page-sizes.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/66-fields.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
# element bookmarkStart: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}bookmarkStart', attribute '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}id': '-irrswq-ln94j4fdgdjxs' is not a valid value of the atomic type '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ST_DecimalNumber'.
|
# element bookmarkStart: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}bookmarkStart', attribute '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}id': '-irrswq-ln94j4fdgdjxs' is not a valid value of the atomic type '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ST_DecimalNumber'.
|
||||||
# element bookmarkEnd: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}bookmarkEnd', attribute '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}id': '-irrswq-ln94j4fdgdjxs' is not a valid value of the atomic type '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ST_DecimalNumber'.
|
# element bookmarkEnd: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}bookmarkEnd', attribute '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}id': '-irrswq-ln94j4fdgdjxs' is not a valid value of the atomic type '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ST_DecimalNumber'.
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/67-column-break.ts
|
||||||
# with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/68-numbering-instances-and-starting-number.ts
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/69-different-width-columns.ts
|
||||||
run: npm run ts-node -- ./demo/67-column-break.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/70-line-numbers-suppression.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/71-page-borders-2.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/72-word-wrap.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- run: npm run run-ts -- ./demo/73-comments.ts
|
||||||
- name: Run Demo
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run ts-node -- ./demo/68-numbering-instances-and-starting-number.ts
|
- run: npm run run-ts -- ./demo/74-nodejs-stream.ts
|
||||||
- name: Extract Word Document
|
# - uses: "./.github/actions/validate-docx"
|
||||||
run: npm run extract
|
# run: npm run run-ts -- ./demo/75-tab-stops.ts
|
||||||
- name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/76-compatibility.ts
|
||||||
with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/77-side-by-side-tables.ts
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/78-thai-distributed.ts
|
||||||
run: npm run ts-node -- ./demo/69-different-width-columns.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/79-table-from-data-source.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/80-thai-distributed.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/81-continuous-header.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- run: npm run run-ts -- ./demo/82-new-headers-new-section.ts
|
||||||
- name: Run Demo
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run ts-node -- ./demo/70-line-numbers-suppression.ts
|
- run: npm run run-ts -- ./demo/83-setting-languages.ts
|
||||||
- name: Extract Word Document
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run extract
|
- run: npm run run-ts -- ./demo/84-positional-tabs.ts
|
||||||
- name: Validate XML
|
- uses: "./.github/actions/validate-docx"
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/71-page-borders-2.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/72-word-wrap.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/73-comments.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/73-comments.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
# - name: Run Demo
|
|
||||||
# run: npm run ts-node -- ./demo/75-tab-stops.ts
|
|
||||||
# - name: Extract Word Document
|
|
||||||
# run: npm run extract
|
|
||||||
# - name: Validate XML
|
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
|
||||||
# with:
|
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/76-compatibility.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/77-side-by-side-tables.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/78-thai-distributed.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/79-table-from-data-source.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/80-thai-distributed.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/81-continuous-header.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/82-new-headers-new-section.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/83-setting-languages.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run ts-node -- ./demo/84-positional-tabs.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
- name: Validate XML
|
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
|
8
.github/workflows/github-pages.yml
vendored
8
.github/workflows/github-pages.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@v4
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci --force
|
run: npm ci --force
|
||||||
- name: Build 🔧
|
- name: Build 🔧
|
||||||
@ -19,7 +19,7 @@ jobs:
|
|||||||
echo "docx.js.org" > docs/.nojekyll
|
echo "docx.js.org" > docs/.nojekyll
|
||||||
echo "docx.js.org" > docs/CNAME
|
echo "docx.js.org" > docs/CNAME
|
||||||
- name: Archive Production Artifact
|
- name: Archive Production Artifact
|
||||||
uses: actions/upload-artifact@master
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: docs
|
name: docs
|
||||||
path: docs
|
path: docs
|
||||||
@ -28,11 +28,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repo 🛎️
|
- name: Checkout Repo 🛎️
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@v4
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci --force
|
run: npm ci --force
|
||||||
- name: Download Artifact
|
- name: Download Artifact
|
||||||
uses: actions/download-artifact@master
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: docs
|
name: docs
|
||||||
path: docs
|
path: docs
|
||||||
|
46
.github/workflows/npm-publish.yml
vendored
Normal file
46
.github/workflows/npm-publish.yml
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
||||||
|
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
|
||||||
|
|
||||||
|
name: Node.js Package
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "20.x"
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run cspell
|
||||||
|
- run: npm run prettier
|
||||||
|
- run: npm run lint
|
||||||
|
- run: npm run test:ci
|
||||||
|
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "20.x"
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run build
|
||||||
|
|
||||||
|
publish-npm:
|
||||||
|
needs: [test, build]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "20.x"
|
||||||
|
registry-url: https://registry.npmjs.org/
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm publish
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
16
.vscode/launch.json
vendored
16
.vscode/launch.json
vendored
@ -1,18 +1,4 @@
|
|||||||
{
|
{
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": []
|
||||||
{
|
|
||||||
"name": "Run Demo",
|
|
||||||
"type": "node",
|
|
||||||
"request": "launch",
|
|
||||||
"runtimeArgs": [
|
|
||||||
"-r",
|
|
||||||
"${workspaceFolder}/node_modules/ts-node/register",
|
|
||||||
"-r",
|
|
||||||
"${workspaceFolder}/node_modules/tsconfig-paths/register"
|
|
||||||
],
|
|
||||||
"cwd": "${workspaceRoot}",
|
|
||||||
"program": "${workspaceFolder}/demo/85-template-document.ts"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
20
.vscode/tasks.json
vendored
20
.vscode/tasks.json
vendored
@ -2,23 +2,5 @@
|
|||||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
// for the documentation about the tasks.json format
|
// for the documentation about the tasks.json format
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": []
|
||||||
{
|
|
||||||
"type": "typescript",
|
|
||||||
"tsconfig": "tsconfig.json",
|
|
||||||
"option": "watch",
|
|
||||||
"problemMatcher": [
|
|
||||||
"$tsc-watch"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "npm",
|
|
||||||
"script": "ts-node",
|
|
||||||
"problemMatcher": [],
|
|
||||||
"group": {
|
|
||||||
"kind": "build",
|
|
||||||
"isDefault": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
@ -45,7 +45,7 @@ const doc = new Document({
|
|||||||
children: [
|
children: [
|
||||||
new TextRun("My Title "),
|
new TextRun("My Title "),
|
||||||
new TextRun({
|
new TextRun({
|
||||||
children: ["Footer - Page ", PageNumber.CURRENT],
|
children: ["Footer - Page ", PageNumber.CURRENT, " of ", PageNumber.TOTAL_PAGES],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import {
|
import {
|
||||||
|
convertMillimetersToTwip,
|
||||||
Document,
|
Document,
|
||||||
HorizontalPositionAlign,
|
HorizontalPositionAlign,
|
||||||
HorizontalPositionRelativeFrom,
|
HorizontalPositionRelativeFrom,
|
||||||
@ -20,6 +21,7 @@ const doc = new Document({
|
|||||||
new Paragraph({
|
new Paragraph({
|
||||||
children: [
|
children: [
|
||||||
new ImageRun({
|
new ImageRun({
|
||||||
|
type: "jpg",
|
||||||
data: fs.readFileSync("./demo/images/image1.jpeg"),
|
data: fs.readFileSync("./demo/images/image1.jpeg"),
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 100,
|
width: 100,
|
||||||
@ -36,17 +38,24 @@ const doc = new Document({
|
|||||||
new Paragraph({
|
new Paragraph({
|
||||||
children: [
|
children: [
|
||||||
new ImageRun({
|
new ImageRun({
|
||||||
|
type: "png",
|
||||||
data: fs.readFileSync("./demo/images/dog.png").toString("base64"),
|
data: fs.readFileSync("./demo/images/dog.png").toString("base64"),
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
},
|
},
|
||||||
|
outline: {
|
||||||
|
type: "solidFill",
|
||||||
|
solidFillType: "rgb",
|
||||||
|
value: "FF0000",
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
new Paragraph({
|
new Paragraph({
|
||||||
children: [
|
children: [
|
||||||
new ImageRun({
|
new ImageRun({
|
||||||
|
type: "jpg",
|
||||||
data: fs.readFileSync("./demo/images/cat.jpg"),
|
data: fs.readFileSync("./demo/images/cat.jpg"),
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 100,
|
width: 100,
|
||||||
@ -55,12 +64,19 @@ const doc = new Document({
|
|||||||
vertical: true,
|
vertical: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
outline: {
|
||||||
|
type: "solidFill",
|
||||||
|
solidFillType: "rgb",
|
||||||
|
value: "0000FF",
|
||||||
|
width: convertMillimetersToTwip(600),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
new Paragraph({
|
new Paragraph({
|
||||||
children: [
|
children: [
|
||||||
new ImageRun({
|
new ImageRun({
|
||||||
|
type: "bmp",
|
||||||
data: fs.readFileSync("./demo/images/parrots.bmp"),
|
data: fs.readFileSync("./demo/images/parrots.bmp"),
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 150,
|
width: 150,
|
||||||
@ -76,6 +92,7 @@ const doc = new Document({
|
|||||||
new Paragraph({
|
new Paragraph({
|
||||||
children: [
|
children: [
|
||||||
new ImageRun({
|
new ImageRun({
|
||||||
|
type: "gif",
|
||||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 200,
|
width: 200,
|
||||||
@ -91,6 +108,7 @@ const doc = new Document({
|
|||||||
new Paragraph({
|
new Paragraph({
|
||||||
children: [
|
children: [
|
||||||
new ImageRun({
|
new ImageRun({
|
||||||
|
type: "gif",
|
||||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 200,
|
width: 200,
|
||||||
@ -112,6 +130,7 @@ const doc = new Document({
|
|||||||
new Paragraph({
|
new Paragraph({
|
||||||
children: [
|
children: [
|
||||||
new ImageRun({
|
new ImageRun({
|
||||||
|
type: "jpg",
|
||||||
data: fs.readFileSync("./demo/images/cat.jpg"),
|
data: fs.readFileSync("./demo/images/cat.jpg"),
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 200,
|
width: 200,
|
||||||
@ -131,6 +150,22 @@ const doc = new Document({
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new ImageRun({
|
||||||
|
type: "svg",
|
||||||
|
data: fs.readFileSync("./demo/images/linux-svg.svg"),
|
||||||
|
transformation: {
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
},
|
||||||
|
fallback: {
|
||||||
|
type: "png",
|
||||||
|
data: fs.readFileSync("./demo/images/linux-png.png"),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -21,6 +21,8 @@ import {
|
|||||||
Packer,
|
Packer,
|
||||||
Paragraph,
|
Paragraph,
|
||||||
TextRun,
|
TextRun,
|
||||||
|
MathLimitLower,
|
||||||
|
MathLimitUpper,
|
||||||
} from "docx";
|
} from "docx";
|
||||||
|
|
||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
@ -316,6 +318,23 @@ const doc = new Document({
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new Math({
|
||||||
|
children: [
|
||||||
|
new MathLimitUpper({
|
||||||
|
children: [new MathRun("x")],
|
||||||
|
limit: [new MathRun("-")],
|
||||||
|
}),
|
||||||
|
new MathRun("="),
|
||||||
|
new MathLimitLower({
|
||||||
|
children: [new MathRun("lim")],
|
||||||
|
limit: [new MathRun("x→0")],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import {
|
import {
|
||||||
|
AlignmentType,
|
||||||
BorderStyle,
|
BorderStyle,
|
||||||
Document,
|
Document,
|
||||||
FrameAnchorType,
|
FrameAnchorType,
|
||||||
@ -20,6 +21,7 @@ const doc = new Document({
|
|||||||
children: [
|
children: [
|
||||||
new Paragraph({
|
new Paragraph({
|
||||||
frame: {
|
frame: {
|
||||||
|
type: "absolute",
|
||||||
position: {
|
position: {
|
||||||
x: 1000,
|
x: 1000,
|
||||||
y: 3000,
|
y: 3000,
|
||||||
@ -30,6 +32,54 @@ const doc = new Document({
|
|||||||
horizontal: FrameAnchorType.MARGIN,
|
horizontal: FrameAnchorType.MARGIN,
|
||||||
vertical: FrameAnchorType.MARGIN,
|
vertical: FrameAnchorType.MARGIN,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
top: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
bottom: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
left: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
new TextRun("Hello World"),
|
||||||
|
new TextRun({
|
||||||
|
text: "Foo Bar",
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
children: [new Tab(), "Github is the best"],
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
frame: {
|
||||||
|
type: "alignment",
|
||||||
|
width: 4000,
|
||||||
|
height: 1000,
|
||||||
|
anchor: {
|
||||||
|
horizontal: FrameAnchorType.MARGIN,
|
||||||
|
vertical: FrameAnchorType.MARGIN,
|
||||||
|
},
|
||||||
alignment: {
|
alignment: {
|
||||||
x: HorizontalPositionAlign.CENTER,
|
x: HorizontalPositionAlign.CENTER,
|
||||||
y: VerticalPositionAlign.TOP,
|
y: VerticalPositionAlign.TOP,
|
||||||
@ -73,6 +123,59 @@ const doc = new Document({
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
frame: {
|
||||||
|
type: "alignment",
|
||||||
|
width: 4000,
|
||||||
|
height: 1000,
|
||||||
|
anchor: {
|
||||||
|
horizontal: FrameAnchorType.MARGIN,
|
||||||
|
vertical: FrameAnchorType.MARGIN,
|
||||||
|
},
|
||||||
|
alignment: {
|
||||||
|
x: HorizontalPositionAlign.CENTER,
|
||||||
|
y: VerticalPositionAlign.BOTTOM,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
top: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
bottom: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
left: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
alignment: AlignmentType.RIGHT,
|
||||||
|
children: [
|
||||||
|
new TextRun("Hello World"),
|
||||||
|
new TextRun({
|
||||||
|
text: "Foo Bar",
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
children: [new Tab(), "Github is the best"],
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -107,5 +107,5 @@ const doc = new Document({
|
|||||||
|
|
||||||
// Used to export the file into a .docx file
|
// Used to export the file into a .docx file
|
||||||
Packer.toBuffer(doc).then((buffer) => {
|
Packer.toBuffer(doc).then((buffer) => {
|
||||||
fs.writeFileSync("6-numbering.docx", buffer);
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
});
|
});
|
||||||
|
@ -18,6 +18,7 @@ const receiptTabStops = [
|
|||||||
const twoTabStops = [{ type: TabStopType.RIGHT, position: TabStopPosition.MAX }];
|
const twoTabStops = [{ type: TabStopType.RIGHT, position: TabStopPosition.MAX }];
|
||||||
|
|
||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
|
defaultTabStop: 0,
|
||||||
sections: [
|
sections: [
|
||||||
{
|
{
|
||||||
properties: {},
|
properties: {},
|
||||||
|
@ -16,7 +16,9 @@ import {
|
|||||||
VerticalAlign,
|
VerticalAlign,
|
||||||
} from "docx";
|
} from "docx";
|
||||||
|
|
||||||
patchDocument(fs.readFileSync("demo/assets/simple-template.docx"), {
|
patchDocument({
|
||||||
|
outputType: "nodebuffer",
|
||||||
|
data: fs.readFileSync("demo/assets/simple-template.docx"),
|
||||||
patches: {
|
patches: {
|
||||||
name: {
|
name: {
|
||||||
type: PatchType.PARAGRAPH,
|
type: PatchType.PARAGRAPH,
|
||||||
@ -56,7 +58,11 @@ patchDocument(fs.readFileSync("demo/assets/simple-template.docx"), {
|
|||||||
],
|
],
|
||||||
link: "https://www.google.co.uk",
|
link: "https://www.google.co.uk",
|
||||||
}),
|
}),
|
||||||
new ImageRun({ data: fs.readFileSync("./demo/images/dog.png"), transformation: { width: 100, height: 100 } }),
|
new ImageRun({
|
||||||
|
type: "png",
|
||||||
|
data: fs.readFileSync("./demo/images/dog.png"),
|
||||||
|
transformation: { width: 100, height: 100 },
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@ -82,7 +88,13 @@ patchDocument(fs.readFileSync("demo/assets/simple-template.docx"), {
|
|||||||
},
|
},
|
||||||
image_test: {
|
image_test: {
|
||||||
type: PatchType.PARAGRAPH,
|
type: PatchType.PARAGRAPH,
|
||||||
children: [new ImageRun({ data: fs.readFileSync("./demo/images/image1.jpeg"), transformation: { width: 100, height: 100 } })],
|
children: [
|
||||||
|
new ImageRun({
|
||||||
|
type: "jpg",
|
||||||
|
data: fs.readFileSync("./demo/images/image1.jpeg"),
|
||||||
|
transformation: { width: 100, height: 100 },
|
||||||
|
}),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
type: PatchType.DOCUMENT,
|
type: PatchType.DOCUMENT,
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { patchDocument, PatchType, TextRun } from "docx";
|
import { patchDocument, PatchType, TextRun } from "docx";
|
||||||
|
|
||||||
patchDocument(fs.readFileSync("demo/assets/simple-template-2.docx"), {
|
patchDocument({
|
||||||
|
outputType: "nodebuffer",
|
||||||
|
data: fs.readFileSync("demo/assets/simple-template-2.docx"),
|
||||||
patches: {
|
patches: {
|
||||||
name: {
|
name: {
|
||||||
type: PatchType.PARAGRAPH,
|
type: PatchType.PARAGRAPH,
|
||||||
|
@ -24,7 +24,9 @@ const patches = getPatches({
|
|||||||
paragraph_replace: "Lorem ipsum paragraph",
|
paragraph_replace: "Lorem ipsum paragraph",
|
||||||
});
|
});
|
||||||
|
|
||||||
patchDocument(fs.readFileSync("demo/assets/simple-template.docx"), {
|
patchDocument({
|
||||||
|
outputType: "nodebuffer",
|
||||||
|
data: fs.readFileSync("demo/assets/simple-template.docx"),
|
||||||
patches,
|
patches,
|
||||||
}).then((doc) => {
|
}).then((doc) => {
|
||||||
fs.writeFileSync("My Document.docx", doc);
|
fs.writeFileSync("My Document.docx", doc);
|
||||||
|
@ -22,8 +22,11 @@ const patches = getPatches({
|
|||||||
"first-name": "John",
|
"first-name": "John",
|
||||||
});
|
});
|
||||||
|
|
||||||
patchDocument(fs.readFileSync("demo/assets/simple-template-3.docx"), {
|
patchDocument({
|
||||||
|
outputType: "nodebuffer",
|
||||||
|
data: fs.readFileSync("demo/assets/simple-template-3.docx"),
|
||||||
patches,
|
patches,
|
||||||
|
keepOriginalStyles: true,
|
||||||
}).then((doc) => {
|
}).then((doc) => {
|
||||||
fs.writeFileSync("My Document.docx", doc);
|
fs.writeFileSync("My Document.docx", doc);
|
||||||
});
|
});
|
||||||
|
40
demo/91-custom-fonts.ts
Normal file
40
demo/91-custom-fonts.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Simple example to add text to a document
|
||||||
|
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { CharacterSet, Document, Packer, Paragraph, Tab, TextRun } from "docx";
|
||||||
|
|
||||||
|
const font = fs.readFileSync("./demo/assets/Pacifico.ttf");
|
||||||
|
|
||||||
|
const doc = new Document({
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
properties: {},
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
run: {
|
||||||
|
font: "Pacifico",
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
new TextRun("Hello World"),
|
||||||
|
new TextRun({
|
||||||
|
text: "Foo Bar",
|
||||||
|
bold: true,
|
||||||
|
size: 40,
|
||||||
|
font: "Pacifico",
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
children: [new Tab(), "Github is the best"],
|
||||||
|
bold: true,
|
||||||
|
font: "Pacifico",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
fonts: [{ name: "Pacifico", data: font, characterSet: CharacterSet.ANSI }],
|
||||||
|
});
|
||||||
|
|
||||||
|
Packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
|
});
|
44
demo/92-declarative-custom-fonts.ts
Normal file
44
demo/92-declarative-custom-fonts.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Simple example to add text to a document
|
||||||
|
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { Document, Packer, Paragraph, Tab, TextRun } from "docx";
|
||||||
|
|
||||||
|
const font = fs.readFileSync("./demo/assets/Pacifico.ttf");
|
||||||
|
|
||||||
|
const doc = new Document({
|
||||||
|
styles: {
|
||||||
|
default: {
|
||||||
|
document: {
|
||||||
|
run: {
|
||||||
|
font: "Pacifico",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
properties: {},
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun("Hello World"),
|
||||||
|
new TextRun({
|
||||||
|
text: "Foo Bar",
|
||||||
|
bold: true,
|
||||||
|
size: 40,
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
children: [new Tab(), "Github is the best"],
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
fonts: [{ name: "Pacifico", data: font, characterSet: "00" }],
|
||||||
|
});
|
||||||
|
|
||||||
|
Packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
|
});
|
72
demo/93-template-document.ts
Normal file
72
demo/93-template-document.ts
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// Patch a document with patches
|
||||||
|
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { patchDocument, PatchType, TextRun } from "docx";
|
||||||
|
|
||||||
|
patchDocument({
|
||||||
|
outputType: "nodebuffer",
|
||||||
|
data: fs.readFileSync("demo/assets/field-trip.docx"),
|
||||||
|
patches: {
|
||||||
|
todays_date: {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: new Date().toLocaleDateString() })],
|
||||||
|
},
|
||||||
|
|
||||||
|
school_name: {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: "test" })],
|
||||||
|
},
|
||||||
|
|
||||||
|
address: {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: "blah blah" })],
|
||||||
|
},
|
||||||
|
|
||||||
|
city: {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: "test" })],
|
||||||
|
},
|
||||||
|
|
||||||
|
state: {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: "test" })],
|
||||||
|
},
|
||||||
|
|
||||||
|
zip: {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: "test" })],
|
||||||
|
},
|
||||||
|
|
||||||
|
phone: {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: "test" })],
|
||||||
|
},
|
||||||
|
|
||||||
|
first_name: {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: "test" })],
|
||||||
|
},
|
||||||
|
|
||||||
|
last_name: {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: "test" })],
|
||||||
|
},
|
||||||
|
|
||||||
|
email_address: {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: "test" })],
|
||||||
|
},
|
||||||
|
|
||||||
|
ft_dates: {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: "test" })],
|
||||||
|
},
|
||||||
|
|
||||||
|
grade: {
|
||||||
|
type: PatchType.PARAGRAPH,
|
||||||
|
children: [new TextRun({ text: "test" })],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).then((doc) => {
|
||||||
|
fs.writeFileSync("My Document.docx", doc);
|
||||||
|
});
|
BIN
demo/assets/Pacifico.ttf
Normal file
BIN
demo/assets/Pacifico.ttf
Normal file
Binary file not shown.
BIN
demo/assets/field-trip.docx
Normal file
BIN
demo/assets/field-trip.docx
Normal file
Binary file not shown.
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<script src="../build/index.umd.js"></script>
|
<script src="../build/index.umd.js"></script>
|
||||||
|
BIN
demo/images/linux-png.png
Normal file
BIN
demo/images/linux-png.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 71 KiB |
183
demo/images/linux-svg.svg
Normal file
183
demo/images/linux-svg.svg
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="500pt" height="600pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://web.resource.org/cc/">
|
||||||
|
|
||||||
|
<defs>
|
||||||
|
|
||||||
|
<linearGradient id="linearGradient172">
|
||||||
|
|
||||||
|
<stop style="stop-color:#3f2600;stop-opacity:0.6;" offset="0" id="stop173" />
|
||||||
|
|
||||||
|
<stop style="stop-color:#3f2600;stop-opacity:0;" offset="1" id="stop174" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="linearGradient167">
|
||||||
|
|
||||||
|
<stop style="stop-color:#ffffff;stop-opacity:0.65;" offset="0" id="stop168" />
|
||||||
|
|
||||||
|
<stop style="stop-color:#ffffff;stop-opacity:0;" offset="1" id="stop169" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="linearGradient162">
|
||||||
|
|
||||||
|
<stop style="stop-color:#ffa63f;stop-opacity:1;" offset="0" id="stop163" />
|
||||||
|
|
||||||
|
<stop style="stop-color:#ffff00;stop-opacity:1;" offset="1" id="stop164" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="linearGradient153">
|
||||||
|
|
||||||
|
<stop style="stop-color:#ffeed7;stop-opacity:1;" offset="0" id="stop154" />
|
||||||
|
|
||||||
|
<stop style="stop-color:#bdbfc2;stop-opacity:1;" offset="1" id="stop155" /></linearGradient>
|
||||||
|
|
||||||
|
<linearGradient id="linearGradient138">
|
||||||
|
|
||||||
|
<stop style="stop-color:#ffffff;stop-opacity:0.8;" offset="0" id="stop139" />
|
||||||
|
|
||||||
|
<stop style="stop-color:#ffffff;stop-opacity:0;" offset="1" id="stop140" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient xlink:href="#linearGradient138" id="linearGradient141" x1="0.47424799" y1="0.020191999" x2="0.417539" y2="0.90125799" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient142" x1="0.55880702" y1="0.031192999" x2="0.553922" y2="0.94531101" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient143" x1="0.46557701" y1="0.028819799" x2="0.41365999" y2="0.93366498" gradientUnits="objectBoundingBox"/>
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient144" x1="0.70346397" y1="0.059404202" x2="0.64553201" y2="0.94063401" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient145" x1="0.46741399" y1="-0.036155298" x2="0.86741799" y2="0.75857902" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient146" x1="0.57152498" y1="0.023441499" x2="0.57143003" y2="0.71875" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient147" x1="0.5" y1="0.0234362" x2="0.5" y2="0.8125" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient148" x1="0.50799799" y1="0.37435901" x2="0.51599997" y2="0.92820501" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient138" id="linearGradient149" x1="0.5" y1="0.131707" x2="0.50400001" y2="0.94634098" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient150" x1="-0.30509499" y1="0.099496603" x2="0.156323" y2="0.94191301" gradientUnits="objectBoundingBox" gradientTransform="matrix(-0.928523,0.283938,0.435332,0.943857,-1.91327e-7,5.49908e-8)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient151" x1="0.433979" y1="0.022184599" x2="0.487055" y2="1.02569" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient153" id="linearGradient152" x1="0.5" y1="0.89842999" x2="0.5" y2="0.40625" gradientUnits="objectBoundingBox" spreadMethod="reflect" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient153" id="linearGradient156" x1="0.43568701" y1="0.98882002" x2="0.453989" y2="0.23093501" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient153" id="linearGradient157" x1="0.49180499" y1="1.15284" x2="0.49482101" y2="0.41252401" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient153" id="linearGradient158" x1="0.51730198" y1="0.85418499" x2="0.49843901" y2="0.136172" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient153" id="linearGradient159" x1="0.46201" y1="0.87917101" x2="0.49215299" y2="0.096282303" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient162" id="linearGradient161" x1="0.50086302" y1="0.34872901" x2="0.41209599" y2="0.98558098" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient162" id="linearGradient165" x1="0.60399801" y1="0.51020199" x2="0.46399999" y2="0.98367399" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient162" id="linearGradient166" x1="0.50000501" y1="0.191616" x2="0.50800002" y2="0.97005898" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<radialGradient xlink:href="#linearGradient172" id="radialGradient171" cx="0.5" cy="0.5" fx="0.5" fy="0.5" r="0.5" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<radialGradient xlink:href="#linearGradient172" id="radialGradient176" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient153" id="linearGradient178" x1="0.94027299" y1="1.2934099" x2="0.19452" y2="-0.675295" gradientUnits="objectBoundingBox" />
|
||||||
|
|
||||||
|
<radialGradient xlink:href="#linearGradient172" id="radialGradient1399" gradientTransform="scale(1.045233,0.956725)" cx="446.77762" cy="1219.4125" fx="446.77762" fy="1219.4125" r="195.07191" gradientUnits="userSpaceOnUse" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient153" id="linearGradient1401" gradientUnits="userSpaceOnUse" x1="400.57785" y1="369.53015" x2="400.84448" y2="304.07886" gradientTransform="scale(0.575262,1.738339)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient138" id="linearGradient1403" gradientUnits="userSpaceOnUse" x1="303.01761" y1="237.93179" x2="297.0856" y2="330.09561" gradientTransform="scale(1.116071,0.896001)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient153" id="linearGradient1405" gradientUnits="userSpaceOnUse" gradientTransform="scale(0.816497,1.224744)" x1="378.93771" y1="278.60202" x2="380.27319" y2="243.91606" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient153" id="linearGradient1407" gradientUnits="userSpaceOnUse" x1="381.38742" y1="277.495" x2="380.5517" y2="245.68338" gradientTransform="scale(0.816497,1.224744)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient1409" gradientUnits="userSpaceOnUse" gradientTransform="scale(0.816497,1.224744)" x1="379.09573" y1="240.92712" x2="376.79556" y2="281.01636" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient1411" gradientUnits="userSpaceOnUse" x1="389.63535" y1="242.28218" x2="387.06866" y2="281.32513" gradientTransform="scale(0.816497,1.224744)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient153" id="linearGradient1413" gradientUnits="userSpaceOnUse" spreadMethod="reflect" x1="437.57941" y1="528.87177" x2="437.57941" y2="394.10361" gradientTransform="scale(0.812855,1.230232)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient153" id="linearGradient1415" gradientUnits="userSpaceOnUse" x1="375.17325" y1="419.78485" x2="377.48541" y2="324.03815" gradientTransform="scale(0.649784,1.538974)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient138" id="linearGradient1417" gradientUnits="userSpaceOnUse" x1="320.75104" y1="498.17776" x2="321.32224" y2="614.50439" gradientTransform="scale(1.074798,0.930408)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient1419" gradientUnits="userSpaceOnUse" x1="322.48257" y1="435.26761" x2="323.2514" y2="488.48251" gradientTransform="scale(1.077001,0.928504)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient1421" gradientUnits="userSpaceOnUse" x1="411.2215" y1="242.94365" x2="411.2215" y2="331.44858" gradientTransform="scale(0.571707,1.749147)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient1423" gradientUnits="userSpaceOnUse" x1="867.34546" y1="234.73897" x2="867.33453" y2="314.83911" gradientTransform="scale(0.572667,1.746214)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient162" id="linearGradient1425" gradientUnits="userSpaceOnUse" x1="236.25362" y1="657.11133" x2="212.5099" y2="737.41229" gradientTransform="scale(1.011514,0.988617)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient153" id="linearGradient1427" gradientUnits="userSpaceOnUse" x1="381.56607" y1="655.73102" x2="279.64313" y2="386.66583" gradientTransform="scale(1.065499,0.938527)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient162" id="linearGradient1429" gradientUnits="userSpaceOnUse" x1="218.11714" y1="630.30475" x2="203.12654" y2="737.8537" gradientTransform="scale(1.009851,0.990245)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient1431" gradientUnits="userSpaceOnUse" gradientTransform="scale(1.007724,0.992335)" x1="117.88966" y1="587.23602" x2="182.24524" y2="704.73077" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient1433" gradientUnits="userSpaceOnUse" x1="223.10072" y1="570.41809" x2="230.53499" y2="710.97723" gradientTransform="scale(0.999504,1.000496)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient1435" gradientUnits="userSpaceOnUse" x1="316.93988" y1="474.01779" x2="371.60889" y2="582.63507" gradientTransform="scale(1.065499,0.938527)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient162" id="linearGradient1437" gradientUnits="userSpaceOnUse" x1="284.68652" y1="410.46326" x2="285.45923" y2="485.69934" gradientTransform="scale(1.218684,0.820557)" />
|
||||||
|
|
||||||
|
<linearGradient xlink:href="#linearGradient167" id="linearGradient1439" gradientUnits="userSpaceOnUse" x1="288.82358" y1="398.85422" x2="288.37628" y2="482.55939" gradientTransform="scale(1.221941,0.81837)" />
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<g id="g1369" transform="translate(-310.7524,-64.25268)">
|
||||||
|
|
||||||
|
<path transform="matrix(1.4177,0,0,0.414745,-38.7944,222.194)" d="M 670.88202 1166.6423 A 203.89551 186.63016 0 1 1 263.091,1166.6423 A 203.89551 186.63016 0 1 1 670.88202 1166.6423 z" id="path175" style="fill:url(#radialGradient1399);stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter" />
|
||||||
|
|
||||||
|
<path transform="matrix(1.25,0,0,1.25,185.454,-167.505)" id="path106" d="M 223.627,632.24 C 201.239,600.017 196.873,495.256 249.114,430.81 C 275,399.892 281.604,378.345 283.645,349.417 C 285.034,316.438 260.32,217.975 353.528,210.473 C 447.934,202.941 442.864,296.133 442.321,345.448 C 441.87,387.088 472.895,410.689 494.117,443.143 C 533.396,502.773 530.074,605.443 486.718,661.015 C 431.801,730.583 384.765,700.413 353.528,702.945 C 295.035,706.147 293.101,737.336 223.627,632.24 z " style="fill:#000000;stroke:none;stroke-width:1.25;" />
|
||||||
|
|
||||||
|
<path transform="matrix(-1.67739,-2.24516e-2,-2.11236e-2,1.4709,1173.58,-293.017)" id="path113" d="M 246.571,470.864 C 234.332,483.36 202.175,539.956 251.44,576.224 C 268.809,588.857 235.063,635.719 219.435,612.532 C 191.865,570.914 210.604,505.591 227.75,482.344 C 239.402,465.857 256.98,459.668 246.571,470.864 z " style="fill:url(#linearGradient1401);stroke:none;stroke-width:0.99464899;" />
|
||||||
|
|
||||||
|
<path transform="matrix(-1.67755,0,0,1.52374,1174.62,-318.082)" id="path111" d="M 256.513,459.837 C 236.598,477.554 200.337,539.928 253.225,580.443 C 270.595,593.075 237.832,632.906 219.435,612.532 C 155.472,541.712 221.104,460.278 243.697,432.282 C 263.889,407.935 281.775,438.034 256.513,459.837 z " style="fill:#000000;stroke:#000000;stroke-width:0.97729802;" />
|
||||||
|
|
||||||
|
<path transform="matrix(1.26626,-7.13667e-2,-4.59795e-2,1.19574,202.143,-125.761)" d="M 399.56879 258.15753 A 58.37323 46.863022 0 1 1 282.82233,258.15753 A 58.37323 46.863022 0 1 1 399.56879 258.15753 z" id="path114" style="fill:url(#linearGradient1403);stroke:none;stroke-width:1.26498997;" />
|
||||||
|
|
||||||
|
<path transform="matrix(1.30445,-7.55326e-2,7.71251e-2,1.34257,144.757,-177.617)" d="M 328.86324 320.64151 A 18.087479 27.131195 0 1 1 292.68828,320.64151 A 18.087479 27.131195 0 1 1 328.86324 320.64151 z" id="path115" style="fill:url(#linearGradient1405);stroke:none;stroke-width:1.17873001;" />
|
||||||
|
|
||||||
|
<path transform="matrix(-1.81082,4.95107e-2,3.17324e-2,1.55333,1207.46,-284.777)" d="M 328.86324 320.64151 A 18.087479 27.131195 0 1 1 292.68828,320.64151 A 18.087479 27.131195 0 1 1 328.86324 320.64151 z" id="path116" style="fill:url(#linearGradient1407);stroke:none;stroke-width:0.93138498;" />
|
||||||
|
|
||||||
|
<path transform="matrix(-0.823196,-1.76123e-3,-1.82321e-2,0.852662,913.674,-37.9902)" d="M 328.86324 320.64151 A 18.087479 27.131195 0 1 1 292.68828,320.64151 A 18.087479 27.131195 0 1 1 328.86324 320.64151 z" id="path117" style="fill:#000000;stroke:none;stroke-width:1.86495996;" />
|
||||||
|
|
||||||
|
<path transform="matrix(0.59438,-7.22959e-2,6.88176e-2,0.705838,367.448,32.4186)" d="M 328.86324 320.64151 A 18.087479 27.131195 0 1 1 292.68828,320.64151 A 18.087479 27.131195 0 1 1 328.86324 320.64151 z" id="path118" style="fill:#000000;stroke:none;stroke-width:2.39814997;" />
|
||||||
|
|
||||||
|
<path transform="matrix(-0.480323,-3.6454e-2,-4.67935e-2,0.475606,813.496,87.0124)" d="M 328.86324 320.64151 A 18.087479 27.131195 0 1 1 292.68828,320.64151 A 18.087479 27.131195 0 1 1 328.86324 320.64151 z" id="path121" style="fill:url(#linearGradient1409);stroke:none;stroke-width:3.1916101;" />
|
||||||
|
|
||||||
|
<path transform="matrix(0.35691,-4.08211e-2,4.13232e-2,0.398544,449.334,114.991)" d="M 328.86324 320.64151 A 18.087479 27.131195 0 1 1 292.68828,320.64151 A 18.087479 27.131195 0 1 1 328.86324 320.64151 z" id="path122" style="fill:url(#linearGradient1411);stroke:none;stroke-width:4.12025976;" />
|
||||||
|
|
||||||
|
<path transform="matrix(1.25,0,0,1.25,185.454,-168.23)" id="path128" d="M 258.702,495.425 C 271.538,466.322 298.816,415.199 299.397,375.667 C 299.397,344.225 393.576,336.716 401.134,368.109 C 408.692,399.502 427.875,446.592 440.084,469.265 C 452.292,491.937 487.893,563.96 449.968,626.811 C 415.811,682.455 312.243,726.477 256.958,619.254 C 238.355,582.047 241.673,535.939 258.702,495.425 z " style="fill:url(#linearGradient1413);stroke:none;stroke-width:1.25;" />
|
||||||
|
|
||||||
|
<path transform="matrix(1.38936,-0.111074,0.102211,1.30214,108.413,-165.938)" id="path112" d="M 242.905,473.815 C 231.642,492.782 207.405,543.124 255.042,575.862 C 306.353,610.682 301.515,672.924 239.435,637.817 C 182.658,606.028 216.59,500.039 234.925,475.551 C 247.032,458.337 264.822,437.52 242.905,473.815 z " style="fill:url(#linearGradient1415);stroke:none;stroke-width:1.15804005;" />
|
||||||
|
|
||||||
|
<path transform="matrix(1.25,0,0,1.25,185.454,-167.505)" id="path109" d="M 256.513,449.72 C 239.048,478.228 197.136,545.533 253.225,580.443 C 328.794,626.798 307.398,673.154 238.426,631.417 C 141.317,573.153 226.601,455.801 265.557,411.079 C 310.001,360.879 274.111,420.166 256.513,449.72 z " style="fill:#000000;stroke:#000000;stroke-width:1.25;" />
|
||||||
|
|
||||||
|
<path id="path125" d="M 421.481,504.727 C 421.481,537.139 392.209,579.243 341.953,578.865 C 290.125,579.32 268.004,537.139 268.004,504.727 C 268.004,472.315 302.383,446.01 344.743,446.01 C 387.102,446.01 421.481,472.315 421.481,504.727 z " style="font-size:12px;fill:url(#linearGradient1417);stroke:none;stroke-width:1.23705006;stroke-dasharray:none" transform="matrix(1.30209,0,0,1.22525,170.042,-153.557)" />
|
||||||
|
|
||||||
|
<path id="path127" d="M 398.227,412.292 C 397.615,450.864 375.047,459.963 346.487,459.963 C 317.926,459.963 297.195,454.269 294.746,412.292 C 294.746,385.978 317.926,370.75 346.487,370.75 C 375.047,370.75 398.227,385.978 398.227,412.292 z " style="font-size:12px;fill:url(#linearGradient1419);stroke:none;stroke-width:1.38846004;stroke-dasharray:none" transform="matrix(1.1868,0,0,1.06708,210.623,-100.078)" />
|
||||||
|
|
||||||
|
<path transform="matrix(1.25,0,0,1.25,185.454,-167.505)" id="path129" d="M 234.285,456.475 C 252.001,429.479 289.3,388.111 241.262,462.288 C 202.311,523.331 226.859,562.561 239.518,573.327 C 276.045,605.889 274.484,627.676 245.913,610.533 C 184.288,573.907 197.078,512.285 234.285,456.475 z " style="fill:url(#linearGradient1421);stroke:none;stroke-width:1.25;" />
|
||||||
|
|
||||||
|
<path transform="matrix(1.25,0,0,1.25,185.454,-167.505)" id="path131" d="M 490.662,467.52 C 475.343,435.819 426.528,355.618 492.988,448.917 C 553.449,533.214 511.01,591.93 503.452,597.744 C 495.895,603.557 470.315,615.184 477.873,594.837 C 485.43,574.49 523.107,535.864 490.662,467.52 z " style="fill:url(#linearGradient1423);stroke:none;stroke-width:1.25;" />
|
||||||
|
|
||||||
|
<path transform="matrix(1.25,0,0,1.25,185.454,-167.505)" id="path132" d="M 220.915,716.921 C 180.473,695.505 121.663,721.045 143.013,662.855 C 147.289,649.617 136.638,629.847 143.594,616.929 C 151.733,601.231 169.174,604.72 179.639,594.255 C 189.957,583.364 196.498,564.606 215.683,567.513 C 234.867,570.42 247.628,593.974 261.027,622.742 C 270.91,643.38 305.968,672.406 303.677,695.5 C 300.981,731 260.65,737.69 220.915,716.921 z " style="fill:url(#linearGradient1425);stroke:#e68c3f;stroke-width:6.25;" />
|
||||||
|
|
||||||
|
<path id="path177" d="M 415.072,495.764 C 412.065,520.67 379.259,572.391 345.554,577.298 C 311.294,582.634 279.122,543.238 271.407,506.184 C 261.518,464.978 293.994,448.584 343.345,449.557 C 396.646,451.211 417.466,463.448 415.072,495.764 z " style="font-size:12px;fill:url(#linearGradient1427);stroke:none;stroke-width:2.85509992;stroke-dasharray:none" transform="matrix(0.598206,0.268584,-0.239623,0.617213,700.568,140.464)" />
|
||||||
|
|
||||||
|
<path transform="matrix(-1.1685,0.423145,0.475283,1.16478,728.343,-213.821)" id="path133" d="M 220.274,718.402 C 178.947,694.812 120.38,724.007 143.013,662.855 C 147.749,649.787 136.417,629.303 143.373,616.385 C 151.512,600.687 169.174,604.72 179.639,594.255 C 189.957,583.364 198.466,566.387 217.651,569.294 C 236.835,572.201 247.628,593.974 261.027,622.742 C 270.91,643.38 304.442,671.713 302.151,694.807 C 299.455,730.307 259.427,740.278 220.274,718.402 z " style="fill:url(#linearGradient1429);stroke:#e68c3f;stroke-width:6.25067997;" />
|
||||||
|
|
||||||
|
<path transform="matrix(-0.945096,0.343745,0.424076,0.956058,714.328,-64.342)" id="path134" d="M 216.482,675.68 C 129.951,618.177 169.174,604.72 179.639,594.255 C 189.957,583.364 198.466,566.387 217.651,569.294 C 236.835,572.201 247.628,593.974 261.027,622.742 C 270.91,643.38 304.087,671.66 302.151,694.807 C 299.535,721.917 253.961,700.294 216.482,675.68 z " style="fill:url(#linearGradient1431);stroke:none;stroke-width:1.52532005;" />
|
||||||
|
|
||||||
|
<path transform="matrix(1.00431,-5.2286e-2,-1.74e-2,1.04575,244.191,-28.4653)" id="path135" d="M 216.506,677.071 C 129.975,619.568 169.709,603.501 182.56,595.791 C 197.959,585.849 197.718,564.96 216.903,567.867 C 236.087,570.774 247.628,593.974 261.027,622.742 C 270.91,643.38 304.087,671.66 302.151,694.807 C 299.535,721.917 253.985,701.685 216.506,677.071 z " style="fill:url(#linearGradient1433);stroke:none;stroke-width:1.52532005;" />
|
||||||
|
|
||||||
|
<path id="path136" d="M 415.072,495.764 C 412.065,520.67 379.259,572.391 345.554,577.298 C 311.294,582.634 279.122,543.238 271.407,506.184 C 261.518,464.978 293.994,448.584 343.345,449.557 C 396.646,451.211 417.466,463.448 415.072,495.764 z " style="font-size:12px;fill:#000000;stroke:none;stroke-width:2.85509992;" transform="matrix(0.515584,0.215259,-0.206526,0.49467,713.3,222.559)" />
|
||||||
|
|
||||||
|
<path id="path137" d="M 415.072,495.764 C 412.065,520.67 379.259,572.391 345.554,577.298 C 311.294,582.634 279.122,543.238 271.407,506.184 C 261.518,464.978 293.994,448.584 343.345,449.557 C 396.646,451.211 417.466,463.448 415.072,495.764 z " style="font-size:12px;fill:url(#linearGradient1435);stroke:none;stroke-width:2.85509992;" transform="matrix(0.351231,0.149463,-0.128856,0.343469,724.522,318.291)" />
|
||||||
|
|
||||||
|
<path transform="matrix(1.25,0,0,1.25,185.454,-167.505)" id="path119" d="M 309.954,338.729 C 317.101,331.959 334.765,311.663 367.915,332.974 C 374.077,336.984 379.077,337.351 390.936,342.429 C 414.662,352.178 403.318,375.688 378.192,383.537 C 367.434,387.026 357.656,400.093 338.063,398.976 C 321.329,397.999 316.944,387.102 306.665,381.07 C 288.396,370.759 285.7,356.816 295.565,349.417 C 305.431,342.018 309.29,339.358 309.954,338.729 z " style="fill:url(#linearGradient1437);stroke:#e68c3f;stroke-width:3.75;" />
|
||||||
|
|
||||||
|
<path transform="matrix(1.25,0,0,1.25,185.454,-167.505)" id="path120" d="M 391.251,357.645 C 381.368,358.226 359.858,379.736 337.185,379.736 C 314.512,379.736 301.141,358.807 297.653,358.807" style="fill:none;stroke:#e68c3f;stroke-width:2.5;" />
|
||||||
|
|
||||||
|
<path transform="matrix(0.627885,0,0,0.595666,392.366,51.8173)" id="path123" d="M 309.954,338.729 C 317.101,331.959 339.645,313.381 369.542,332.401 C 375.841,336.167 382.346,340.266 392.02,345.865 C 411.182,357.613 401.691,374.543 378.734,385.255 C 368.316,389.75 351.141,399.67 338.063,398.976 C 323.53,397.568 314.128,387.577 304.496,381.07 C 286.826,368.767 287.899,358.833 296.107,350.562 C 302.312,344.883 309.29,339.358 309.954,338.729 z " style="fill:url(#linearGradient1439);stroke:none;" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 21 KiB |
@ -55,7 +55,7 @@ if (files.length === 0) {
|
|||||||
const filePath = path.join(dir, files[0]);
|
const filePath = path.join(dir, files[0]);
|
||||||
|
|
||||||
console.log(`Running demo ${demoNumber}: ${files[0]}`);
|
console.log(`Running demo ${demoNumber}: ${files[0]}`);
|
||||||
const { stdout } = await $`ts-node --project demo/tsconfig.json ${filePath}`;
|
const { stdout } = await $`tsx ${filePath}`;
|
||||||
console.log(stdout);
|
console.log(stdout);
|
||||||
console.log("Successfully created document!");
|
console.log("Successfully created document!");
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
- Simple, declarative API
|
- Simple, declarative API
|
||||||
- 80+ usage examples
|
- 80+ usage examples
|
||||||
- Battle tested, mature, 99.9%+ coverage
|
- Battle tested, mature, 100% coverage (yes, every line is tested)
|
||||||
|
|
||||||
[GitHub](https://github.com/dolanmiu/docx)
|
[GitHub](https://github.com/dolanmiu/docx)
|
||||||
[Get Started](#Welcome)
|
[Get Started](#Welcome)
|
||||||
|
@ -22,7 +22,7 @@ const doc = new Document({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
}];
|
}]
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ To create a `floating` image on top of text:
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
const image = new ImageRun({
|
const image = new ImageRun({
|
||||||
|
type: 'gif',
|
||||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 200,
|
width: 200,
|
||||||
@ -26,6 +27,7 @@ By default with no arguments, its an `inline` image:
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
const image = new ImageRun({
|
const image = new ImageRun({
|
||||||
|
type: 'gif',
|
||||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 100,
|
width: 100,
|
||||||
@ -59,6 +61,7 @@ const doc = new Document({
|
|||||||
new Paragraph({
|
new Paragraph({
|
||||||
children: [
|
children: [
|
||||||
new ImageRun({
|
new ImageRun({
|
||||||
|
type: [IMAGE_TYPE],
|
||||||
data: [IMAGE_BUFFER],
|
data: [IMAGE_BUFFER],
|
||||||
transformation: {
|
transformation: {
|
||||||
width: [IMAGE_SIZE],
|
width: [IMAGE_SIZE],
|
||||||
@ -97,6 +100,7 @@ To change the position the image to be on top of the text, simply add the `float
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
const image = new ImageRun({
|
const image = new ImageRun({
|
||||||
|
type: 'png',
|
||||||
data: buffer,
|
data: buffer,
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 903,
|
width: 903,
|
||||||
@ -115,6 +119,7 @@ const image = new ImageRun({
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
const image = new ImageRun({
|
const image = new ImageRun({
|
||||||
|
type: 'png',
|
||||||
data: buffer,
|
data: buffer,
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 903,
|
width: 903,
|
||||||
@ -180,6 +185,7 @@ For example:
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
const image = new ImageRun({
|
const image = new ImageRun({
|
||||||
|
type: 'gif',
|
||||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 200,
|
width: 200,
|
||||||
@ -228,6 +234,7 @@ For example:
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
const image = new ImageRun({
|
const image = new ImageRun({
|
||||||
|
type: 'gif',
|
||||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 200,
|
width: 200,
|
||||||
@ -258,6 +265,7 @@ Specifies common non-visual DrawingML properties. A name, title and description
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
const image = new ImageRun({
|
const image = new ImageRun({
|
||||||
|
type: 'gif',
|
||||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||||
altText: {
|
altText: {
|
||||||
title: "This is an ultimate title",
|
title: "This is an ultimate title",
|
||||||
|
@ -263,3 +263,23 @@ new MathAngledBrackets({
|
|||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Limit
|
||||||
|
|
||||||
|
#### Limit Upper
|
||||||
|
|
||||||
|
```ts
|
||||||
|
new MathLimitUpper({
|
||||||
|
children: [new MathRun("x")],
|
||||||
|
limit: [new MathRun("-")],
|
||||||
|
}),
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Limit Lower
|
||||||
|
|
||||||
|
```ts
|
||||||
|
new MathLimitLower({
|
||||||
|
children: [new MathRun("lim")],
|
||||||
|
limit: [new MathRun("x→0")],
|
||||||
|
}),
|
||||||
|
```
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# Bullets and Numbering
|
# Bullets and Numbering
|
||||||
|
|
||||||
|
!> Bullets and Numbering requires an understanding of [Sections](usage/sections.md) and [Paragraphs](usage/paragraph.md).
|
||||||
|
|
||||||
`docx` is quite flexible in its bullets and numbering system, allowing
|
`docx` is quite flexible in its bullets and numbering system, allowing
|
||||||
the user great freedom in how bullets and numbers are to be styled and
|
the user great freedom in how bullets and numbers are to be styled and
|
||||||
displayed. E.g., numbers can be shown using Arabic numerals, roman
|
displayed. E.g., numbers can be shown using Arabic numerals, roman
|
||||||
@ -8,112 +10,184 @@ format also supports re-using bullets/numbering styles throughout the
|
|||||||
document, so that different lists using the same style need not
|
document, so that different lists using the same style need not
|
||||||
redefine them.
|
redefine them.
|
||||||
|
|
||||||
Because of this flexibility, bullets and numbering in DOCX involves a
|
## Configuration
|
||||||
couple of moving pieces:
|
|
||||||
|
|
||||||
1. Document-level bullets/numbering definitions (abstract)
|
Numbering is configured by adding config into `Document`:
|
||||||
2. Document-level bullets/numbering definitions (concrete)
|
|
||||||
3. Paragraph-level bullets/numbering selection
|
|
||||||
|
|
||||||
## Document-level bullets/numbering definitions (abstract)
|
|
||||||
|
|
||||||
Every document contains a set of abstract bullets/numbering
|
|
||||||
definitions which define the formatting and layout of paragraphs using
|
|
||||||
those bullets/numbering. An abstract numbering system defines how
|
|
||||||
bullets/numbers are to be shown for lists, including any sublists that
|
|
||||||
may be used. Thus each abstract definition includes a series of
|
|
||||||
_levels_ which form a sequence starting at 0 indicating the top-level
|
|
||||||
list look and increasing from there to describe the sublists, then
|
|
||||||
sub-sublists, etc. Each level includes the following properties:
|
|
||||||
|
|
||||||
* **level**: This is its 0-based index in the definition stack
|
|
||||||
* **numberFormat**: This indicates how the bullet or number should be
|
|
||||||
generated. Options include `bullet` (meaning don't count), `decimal`
|
|
||||||
(arabic numerals), `upperRoman`, `lowerRoman`, `hex`, and many
|
|
||||||
more.
|
|
||||||
* **levelText**: This is a format string using the output of the
|
|
||||||
`numberFormat` function and generating a string to insert before
|
|
||||||
every item in the list. You may use `%1`, `%2`, ... to reference the
|
|
||||||
numbers from each numbering level before this one. Thus a level
|
|
||||||
text of `%d)` with a number format of `lowerLetter` would result in
|
|
||||||
the sequence "a)", "b)", ...
|
|
||||||
* and a few others, which you can see in the OOXML spec section 17.9.6
|
|
||||||
|
|
||||||
## Document-level bullets/numbering definitions (concrete)
|
|
||||||
|
|
||||||
Concrete definitions are sort of like concrete subclasses of the
|
|
||||||
abstract definitions. They indicate their parent and are allowed to
|
|
||||||
override certain level definitions. Thus two lists that differ only in
|
|
||||||
how sub-sub-lists are to be displayed can share the same abstract
|
|
||||||
numbering definition and have slightly different concrete definitions.
|
|
||||||
|
|
||||||
## Paragraph-level bullets/numbering selection
|
|
||||||
|
|
||||||
In order to use a bullets/numbering definition (which must be
|
|
||||||
concrete), paragraphs need to select it, similar to applying a CSS
|
|
||||||
class to an element, using both the concrete numbering definition ID
|
|
||||||
and the level number that the paragraph should be at. Additionally, MS
|
|
||||||
Word and LibreOffice typically apply a "ListParagraph" style to
|
|
||||||
paragraphs that are being numbered.
|
|
||||||
|
|
||||||
## Using bullets/numbering in `docx`
|
|
||||||
|
|
||||||
`docx` includes a pre-defined bullet style which you can add to your
|
|
||||||
paragraphs using `para.bullets()`. If you require different bullet
|
|
||||||
styles or numbering of any kind, you'll have to use the
|
|
||||||
`docx.Numbering` class.
|
|
||||||
|
|
||||||
First you need to create a new numbering container class and use it to
|
|
||||||
create your abstract numbering style, define your levels, and create
|
|
||||||
your concrete numbering style:
|
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const numbering = new docx.Numbering();
|
new Document({
|
||||||
|
numbering: {
|
||||||
const abstractNum = numbering.createAbstractNumbering();
|
config: [...]
|
||||||
abstractNum.createLevel(0, "upperRoman", "%1", "start").addParagraphProperty(new Indent(720, 260));
|
}
|
||||||
abstractNum.createLevel(1, "decimal", "%2.", "start").addParagraphProperty(new Indent(1440, 980));
|
})
|
||||||
abstractNum.createLevel(2, "lowerLetter", "%3)", "start").addParagraphProperty(new Indent(2160, 1700));
|
|
||||||
|
|
||||||
const concrete = numbering.createConcreteNumbering(abstractNum);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can then apply your concrete style to paragraphs using the
|
Each `config` entry includes the following properties:
|
||||||
`setNumbering` method:
|
|
||||||
|
. Each level includes the following properties:
|
||||||
|
|
||||||
|
| Property | Type | Notes | Possible Values |
|
||||||
|
| --------- | ----------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| reference | `string` | Required | A unique `string` |
|
||||||
|
| levels | `ILevelOptions[]` | Required | a series of _levels_ which form a sequence starting at 0 indicating the top-level list look and increasing from there to describe the sublists, then sub-sublists, etc |
|
||||||
|
|
||||||
|
### Level Options
|
||||||
|
|
||||||
|
Levels define the numbering definition itself, what it looks like, the indention, the alignment and the style. The reason why it is an array is because it allows the ability to create sub-lists. A sub list will have a different configuration because you may want the sub-list to have a different indentation or different bullet.
|
||||||
|
|
||||||
|
| Property | Type | Notes | Possible Values |
|
||||||
|
| --------- | ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| level | `number` | Required | The list level this definition is for. `0` is for the root level, `1` is for a sub list, `2` is for a sub-sub-list etc. |
|
||||||
|
| format | `LevelFormat` | Optional | `DECIMAL`, `UPPER_ROMAN`, `LOWER_ROMAN`, `UPPER_LETTER`, `LOWER_LETTER`, `ORDINAL`, `CARDINAL_TEXT`, `ORDINAL_TEXT`, `HEX`, `CHICAGO`, `IDEOGRAPH__DIGITAL`, `JAPANESE_COUNTING`, `AIUEO`, `IROHA`, `DECIMAL_FULL_WIDTH`, `DECIMAL_HALF_WIDTH`, `JAPANESE_LEGAL`, `JAPANESE_DIGITAL_TEN_THOUSAND`, `DECIMAL_ENCLOSED_CIRCLE`, `DECIMAL_FULL_WIDTH2`, `AIUEO_FULL_WIDTH`, `IROHA_FULL_WIDTH`, `DECIMAL_ZERO`, `BULLET`, `GANADA`, `CHOSUNG`, `DECIMAL_ENCLOSED_FULLSTOP`, `DECIMAL_ENCLOSED_PARENTHESES`, `DECIMAL_ENCLOSED_CIRCLE_CHINESE`, `IDEOGRAPH_ENCLOSED_CIRCLE`, `IDEOGRAPH_TRADITIONAL`, `IDEOGRAPH_ZODIAC`, `IDEOGRAPH_ZODIAC_TRADITIONAL`, `TAIWANESE_COUNTING`, `IDEOGRAPH_LEGAL_TRADITIONAL`, `TAIWANESE_COUNTING_THOUSAND`, `TAIWANESE_DIGITAL`, `CHINESE_COUNTING`, `CHINESE_LEGAL_SIMPLIFIED`, `CHINESE_COUNTING_THOUSAND`, `KOREAN_DIGITAL`, `KOREAN_COUNTING`, `KOREAN_LEGAL`, `KOREAN_DIGITAL2`, `VIETNAMESE_COUNTING`, `RUSSIAN_LOWER`, `RUSSIAN_UPPER`, `NONE`, `NUMBER_IN_DASH`, `HEBREW1`, `HEBREW2`, `ARABIC_ALPHA`, `ARABIC_ABJAD`, `HINDI_VOWELS`, `HINDI_CONSONANTS`, `HINDI_NUMBERS`, `HINDI_COUNTING`, `THAI_LETTERS`, `THAI_NUMBERS`, `THAI_COUNTING`, `BAHT_TEXT`, `DOLLAR_TEXT`, `CUSTOM` |
|
||||||
|
| text | `string` | Optional | A unique `string` to describe the shape of the bullet |
|
||||||
|
| alignment | `string` | Required | `START`, `CENTER`, `END`, `BOTH`, `MEDIUM_KASHIDA`, `DISTRIBUTE`, `NUM_TAB`, `HIGH_KASHIDA`, `LOW_KASHIDA`, `THAI_DISTRIBUTE`, `LEFT`, `RIGHT`, `JUSTIFIED` |
|
||||||
|
| style | `string` | Optional | [Sections](usage/styling-with-js.md) |
|
||||||
|
|
||||||
|
## Using ordered lists in `docx`
|
||||||
|
|
||||||
|
Add a `numbering` section to the `Document` to numbering style, define your levels. Use `LevelFormat.UPPER_ROMAN` for the `format` in `levels`:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
topLevelP.setNumbering(concrete, 0);
|
const doc = new Document({
|
||||||
subP.setNumbering(concrete, 1);
|
...
|
||||||
subSubP.setNumbering(concrete, 2);
|
numbering: {
|
||||||
```
|
config: [
|
||||||
|
{
|
||||||
## Unindent numbering
|
reference: "my-numbering",
|
||||||
|
levels: [
|
||||||
Default:1. test
|
{
|
||||||
|
|
||||||
After:1.test
|
|
||||||
|
|
||||||
Use default numbering have indent,If you want unindent numbering
|
|
||||||
|
|
||||||
How to custom number see the demo:
|
|
||||||
https://runkit.com/dolanmiu/docx-demo3
|
|
||||||
|
|
||||||
```ts
|
|
||||||
|
|
||||||
enum LevelSuffix {
|
|
||||||
NOTHING = "nothing",
|
|
||||||
SPACE = "space",
|
|
||||||
TAB = "tab"
|
|
||||||
}
|
|
||||||
|
|
||||||
// custom numbering
|
|
||||||
const levels=[
|
|
||||||
{
|
|
||||||
level: 0,
|
level: 0,
|
||||||
format: "decimal",
|
format: LevelFormat.UPPER_ROMAN,
|
||||||
text: "%1.",
|
text: "%1",
|
||||||
alignment: AlignmentType.START,
|
alignment: AlignmentType.START,
|
||||||
suffix: LevelSuffix.NOTHING, // Cancel intent
|
style: {
|
||||||
}]
|
paragraph: {
|
||||||
|
indent: { left: 2880, hanging: 2420 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
...
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
And then on a `Paragraph`, we can add use the numbering created:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
new Paragraph({
|
||||||
|
text: "Hey you!",
|
||||||
|
numbering: {
|
||||||
|
reference: "my-numbering",
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
```
|
||||||
|
|
||||||
|
## Un-ordered lists / Bullet points
|
||||||
|
|
||||||
|
Add a `numbering` section to the `Document` to numbering style, define your levels. Use `LevelFormat.BULLET` for the `format` in `levels`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const doc = new Document({
|
||||||
|
...
|
||||||
|
numbering: {
|
||||||
|
config: [
|
||||||
|
{
|
||||||
|
reference: "my-bullet-points",
|
||||||
|
levels: [
|
||||||
|
{
|
||||||
|
level: 0,
|
||||||
|
format: LevelFormat.BULLET,
|
||||||
|
text: "\u1F60",
|
||||||
|
alignment: AlignmentType.LEFT,
|
||||||
|
style: {
|
||||||
|
paragraph: {
|
||||||
|
indent: { left: convertInchesToTwip(0.5), hanging: convertInchesToTwip(0.25) },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
...
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
And then on a `Paragraph`, we can add use the numbering created:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
new Paragraph({
|
||||||
|
text: "Hey you!",
|
||||||
|
numbering: {
|
||||||
|
reference: "my-bullet-points",
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
```
|
||||||
|
|
||||||
|
## Disabling numbering inherited from paragraph style
|
||||||
|
|
||||||
|
If the numbering is set on a paragraph style, you may wish to disable it for a specific paragraph:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const doc = new Document({
|
||||||
|
...
|
||||||
|
numbering: {
|
||||||
|
config: [
|
||||||
|
{
|
||||||
|
reference: "my-bullet-points",
|
||||||
|
levels: [
|
||||||
|
{
|
||||||
|
level: 0,
|
||||||
|
format: LevelFormat.BULLET,
|
||||||
|
text: "\u1F60",
|
||||||
|
alignment: AlignmentType.LEFT,
|
||||||
|
style: {
|
||||||
|
paragraph: {
|
||||||
|
indent: { left: convertInchesToTwip(0.5), hanging: convertInchesToTwip(0.25) },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
styles: {
|
||||||
|
paragraphStyles: [
|
||||||
|
{
|
||||||
|
id: 'bullet',
|
||||||
|
name: 'Bullet',
|
||||||
|
basedOn: 'Normal',
|
||||||
|
next: 'Normal',
|
||||||
|
run: {},
|
||||||
|
paragraph: {
|
||||||
|
numbering: {
|
||||||
|
reference: 'my-bullet-points',
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
...
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
new Paragraph({
|
||||||
|
text: "No bullet points!",
|
||||||
|
style: "Bullet",
|
||||||
|
numbering: false,
|
||||||
|
}),
|
||||||
|
```
|
||||||
|
|
||||||
|
## Full Example
|
||||||
|
|
||||||
|
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/3-numbering-and-bullet-points.ts ":include")
|
||||||
|
|
||||||
|
_Source: https://github.com/dolanmiu/docx/blob/master/demo/3-numbering-and-bullet-points.ts_
|
||||||
|
@ -35,6 +35,9 @@ interface Patch {
|
|||||||
| type | `PatchType` | Required | `DOCUMENT`, `PARAGRAPH` |
|
| type | `PatchType` | Required | `DOCUMENT`, `PARAGRAPH` |
|
||||||
| children | `FileChild[] or ParagraphChild[]` | Required | The contents to replace with. A `FileChild` is a `Paragraph` or `Table`, whereas a `ParagraphChild` is typical `Paragraph` children. |
|
| children | `FileChild[] or ParagraphChild[]` | Required | The contents to replace with. A `FileChild` is a `Paragraph` or `Table`, whereas a `ParagraphChild` is typical `Paragraph` children. |
|
||||||
|
|
||||||
|
|
||||||
|
The patcher also takes in a `keepOriginalStyles` boolean, which will preserve the styles of the patched text when set to true.
|
||||||
|
|
||||||
### How to patch existing document
|
### How to patch existing document
|
||||||
|
|
||||||
1. Open your existing word document in your favorite Word Processor
|
1. Open your existing word document in your favorite Word Processor
|
||||||
@ -76,7 +79,7 @@ patchDocument(fs.readFileSync("My Document.docx"), {
|
|||||||
],
|
],
|
||||||
link: "https://www.google.co.uk",
|
link: "https://www.google.co.uk",
|
||||||
}),
|
}),
|
||||||
new ImageRun({ data: fs.readFileSync("./demo/images/dog.png"), transformation: { width: 100, height: 100 } }),
|
new ImageRun({ type: 'png', data: fs.readFileSync("./demo/images/dog.png"), transformation: { width: 100, height: 100 } }),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
@ -126,10 +126,10 @@ const doc = new Document({
|
|||||||
next: "Normal",
|
next: "Normal",
|
||||||
quickFormat: true,
|
quickFormat: true,
|
||||||
run: {
|
run: {
|
||||||
size: 26
|
size: 26,
|
||||||
bold: true,
|
bold: true,
|
||||||
color: "999999",
|
color: "999999",
|
||||||
{
|
underline: {
|
||||||
type: UnderlineType.DOUBLE,
|
type: UnderlineType.DOUBLE,
|
||||||
color: "FF0000",
|
color: "FF0000",
|
||||||
},
|
},
|
||||||
|
@ -9,11 +9,16 @@
|
|||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
*Note*: Font and color selection from the theme are currently not supported.
|
||||||
|
|
||||||
3. You can even create a totally new `Style`:
|
3. You can even create a totally new `Style`:
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
*Note*: When selecting the style type, it is important to consider the component being used.
|
||||||
|
|
||||||
|
|
||||||
4. Save
|
4. Save
|
||||||
5. Re-name the saved `.docx` file to `.zip` and un-zip
|
5. Re-name the saved `.docx` file to `.zip` and un-zip
|
||||||
6. Find `styles.xml`
|
6. Find `styles.xml`
|
||||||
|
@ -22,7 +22,7 @@ Then add the table in the `section`
|
|||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
sections: [{
|
sections: [{
|
||||||
children: [table],
|
children: [table],
|
||||||
}];
|
}],
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
9698
package-lock.json
generated
9698
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
62
package.json
62
package.json
@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "docx",
|
"name": "docx",
|
||||||
"version": "8.2.2",
|
"version": "9.0.1",
|
||||||
"description": "Easily generate .docx files with JS/TS with a nice declarative API. Works for Node and on the Browser.",
|
"description": "Easily generate .docx files with JS/TS with a nice declarative API. Works for Node and on the Browser.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "build/index.umd.js",
|
"main": "build/index.umd.js",
|
||||||
"module": "./build/index.js",
|
"module": "./build/index.mjs",
|
||||||
"types": "./build/index.d.ts",
|
"types": "./build/index.d.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"require": "./build/index.cjs",
|
"require": "./build/index.cjs",
|
||||||
"types": "./build/index.d.ts",
|
"types": "./build/index.d.ts",
|
||||||
"import": "./build/index.js",
|
"import": "./build/index.mjs",
|
||||||
"default": "./build/index.js"
|
"default": "./build/index.mjs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
@ -20,21 +20,21 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build",
|
||||||
"test": "vitest --ui --coverage",
|
"test": "vitest --ui --coverage",
|
||||||
"test.ci": "vitest run --coverage",
|
"test:ci": "vitest run --coverage",
|
||||||
"prepublishOnly": "npm run build --omit=dev",
|
"prepublishOnly": "npm run build --omit=dev",
|
||||||
"lint": "eslint --ext .ts src",
|
"lint": "eslint --ext .ts src",
|
||||||
"predemo": "npm run build",
|
"predemo": "npm run build",
|
||||||
"demo": "ts-node --project demo/tsconfig.json ./demo/index.ts",
|
"demo": "tsx ./demo/index.ts",
|
||||||
"typedoc": "typedoc src/index.ts --tsconfig tsconfig.typedoc.json",
|
"typedoc": "typedoc src/index.ts --tsconfig tsconfig.typedoc.json",
|
||||||
"style": "prettier -l \"{src,scripts,demo}/**/*.{ts,html}\"",
|
"prettier": "prettier -l \"{src,scripts,demo}/**/*.{ts,html}\"",
|
||||||
"style.fix": "npm run style -- --write",
|
"prettier:fix": "npm run prettier -- --write",
|
||||||
"cspell": "cspell \"{src,demo,docs,scripts}/**/*.{ts,scss,html,md}\" && cspell \"./*.*\"",
|
"cspell": "cspell \"{src,demo,docs,scripts}/**/*.{ts,scss,html,md}\" && cspell \"./*.*\"",
|
||||||
"serve.docs": "cd docs && docsify serve",
|
"serve.docs": "cd docs && docsify serve",
|
||||||
"extract": "ts-node scripts/extract-document.ts",
|
"extract": "tsx scripts/extract-document.ts",
|
||||||
"ts-node": "ts-node --project demo/tsconfig.json"
|
"run-ts": "tsx"
|
||||||
},
|
},
|
||||||
"pre-commit": [
|
"pre-commit": [
|
||||||
"style",
|
"prettier",
|
||||||
"lint"
|
"lint"
|
||||||
],
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -54,9 +54,10 @@
|
|||||||
"clippy"
|
"clippy"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "^20.3.1",
|
"@types/node": "^22.7.5",
|
||||||
|
"hash.js": "^1.1.7",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"nanoid": "^4.0.2",
|
"nanoid": "^5.0.4",
|
||||||
"xml": "^1.0.1",
|
"xml": "^1.0.1",
|
||||||
"xml-js": "^1.6.8"
|
"xml-js": "^1.6.8"
|
||||||
},
|
},
|
||||||
@ -67,40 +68,39 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://docx.js.org",
|
"homepage": "https://docx.js.org",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@esbuild/win32-x64": "^0.18.3",
|
|
||||||
"@types/inquirer": "^9.0.3",
|
"@types/inquirer": "^9.0.3",
|
||||||
"@types/prompt": "^1.1.1",
|
"@types/prompt": "^1.1.1",
|
||||||
"@types/unzipper": "^0.10.4",
|
"@types/unzipper": "^0.10.4",
|
||||||
"@types/xml": "^1.0.8",
|
"@types/xml": "^1.0.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.36.1",
|
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||||
"@typescript-eslint/parser": "^5.36.1",
|
"@typescript-eslint/parser": "^8.8.1",
|
||||||
"@vitest/coverage-v8": "^0.33.0",
|
"@vitest/coverage-v8": "^1.1.0",
|
||||||
"@vitest/ui": "^0.33.0",
|
"@vitest/ui": "^1.1.0",
|
||||||
"cspell": "^6.2.2",
|
"cspell": "^8.2.3",
|
||||||
"docsify-cli": "^4.3.0",
|
"docsify-cli": "^4.3.0",
|
||||||
"eslint": "^8.23.0",
|
"eslint": "^8.23.0",
|
||||||
"eslint-plugin-functional": "^5.0.8",
|
"eslint-plugin-functional": "^6.0.0",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.26.0",
|
||||||
"eslint-plugin-jsdoc": "^46.2.6",
|
"eslint-plugin-jsdoc": "^50.3.1",
|
||||||
"eslint-plugin-no-null": "^1.0.2",
|
"eslint-plugin-no-null": "^1.0.2",
|
||||||
"eslint-plugin-prefer-arrow": "^1.2.3",
|
"eslint-plugin-prefer-arrow": "^1.2.3",
|
||||||
"eslint-plugin-unicorn": "^47.0.0",
|
"eslint-plugin-unicorn": "^50.0.1",
|
||||||
"execa": "^7.1.1",
|
"execa": "^8.0.1",
|
||||||
"glob": "^10.2.7",
|
"glob": "^10.2.7",
|
||||||
"inquirer": "^9.2.7",
|
"inquirer": "^9.2.7",
|
||||||
"jsdom": "^22.1.0",
|
"jsdom": "^24.0.0",
|
||||||
"pre-commit": "^1.2.2",
|
"pre-commit": "^1.2.2",
|
||||||
"prettier": "^2.3.1",
|
"prettier": "^3.1.1",
|
||||||
"ts-node": "^10.2.1",
|
|
||||||
"tsconfig-paths": "^4.0.0",
|
"tsconfig-paths": "^4.0.0",
|
||||||
"typedoc": "^0.24.8",
|
"tsx": "^4.7.0",
|
||||||
"typescript": "5.1.6",
|
"typedoc": "^0.25.4",
|
||||||
|
"typescript": "5.3.3",
|
||||||
"unzipper": "^0.10.11",
|
"unzipper": "^0.10.11",
|
||||||
"vite": "^4.3.2",
|
"vite": "^5.0.10",
|
||||||
"vite-plugin-dts": "^3.3.1",
|
"vite-plugin-dts": "^3.3.1",
|
||||||
"vite-plugin-node-polyfills": "^0.9.0",
|
"vite-plugin-node-polyfills": "^0.19.0",
|
||||||
"vite-tsconfig-paths": "^4.2.0",
|
"vite-tsconfig-paths": "^4.2.0",
|
||||||
"vitest": "^0.33.0"
|
"vitest": "^1.1.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
|
@ -12,7 +12,8 @@ describe("ImageReplacer", () => {
|
|||||||
"test {test-image.png} test",
|
"test {test-image.png} test",
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
stream: Buffer.from(""),
|
type: "png",
|
||||||
|
data: Buffer.from(""),
|
||||||
fileName: "test-image.png",
|
fileName: "test-image.png",
|
||||||
transformation: {
|
transformation: {
|
||||||
pixels: {
|
pixels: {
|
||||||
|
@ -36,7 +36,7 @@ describe("Compiler", () => {
|
|||||||
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
|
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
|
||||||
|
|
||||||
expect(fileNames).is.an.instanceof(Array);
|
expect(fileNames).is.an.instanceof(Array);
|
||||||
expect(fileNames).has.length(17);
|
expect(fileNames).has.length(19);
|
||||||
expect(fileNames).to.include("word/document.xml");
|
expect(fileNames).to.include("word/document.xml");
|
||||||
expect(fileNames).to.include("word/styles.xml");
|
expect(fileNames).to.include("word/styles.xml");
|
||||||
expect(fileNames).to.include("docProps/core.xml");
|
expect(fileNames).to.include("docProps/core.xml");
|
||||||
@ -47,7 +47,9 @@ describe("Compiler", () => {
|
|||||||
expect(fileNames).to.include("word/_rels/footnotes.xml.rels");
|
expect(fileNames).to.include("word/_rels/footnotes.xml.rels");
|
||||||
expect(fileNames).to.include("word/settings.xml");
|
expect(fileNames).to.include("word/settings.xml");
|
||||||
expect(fileNames).to.include("word/comments.xml");
|
expect(fileNames).to.include("word/comments.xml");
|
||||||
|
expect(fileNames).to.include("word/fontTable.xml");
|
||||||
expect(fileNames).to.include("word/_rels/document.xml.rels");
|
expect(fileNames).to.include("word/_rels/document.xml.rels");
|
||||||
|
expect(fileNames).to.include("word/_rels/fontTable.xml.rels");
|
||||||
expect(fileNames).to.include("[Content_Types].xml");
|
expect(fileNames).to.include("[Content_Types].xml");
|
||||||
expect(fileNames).to.include("_rels/.rels");
|
expect(fileNames).to.include("_rels/.rels");
|
||||||
},
|
},
|
||||||
@ -94,7 +96,7 @@ describe("Compiler", () => {
|
|||||||
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
|
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
|
||||||
|
|
||||||
expect(fileNames).is.an.instanceof(Array);
|
expect(fileNames).is.an.instanceof(Array);
|
||||||
expect(fileNames).has.length(25);
|
expect(fileNames).has.length(27);
|
||||||
|
|
||||||
expect(fileNames).to.include("word/header1.xml");
|
expect(fileNames).to.include("word/header1.xml");
|
||||||
expect(fileNames).to.include("word/_rels/header1.xml.rels");
|
expect(fileNames).to.include("word/_rels/header1.xml.rels");
|
||||||
@ -127,12 +129,10 @@ describe("Compiler", () => {
|
|||||||
const spy = vi.spyOn(compiler["formatter"], "format");
|
const spy = vi.spyOn(compiler["formatter"], "format");
|
||||||
|
|
||||||
compiler.compile(file);
|
compiler.compile(file);
|
||||||
expect(spy).toBeCalledTimes(13);
|
expect(spy).toBeCalledTimes(15);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should work with media datas", () => {
|
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 file = new File({
|
const file = new File({
|
||||||
sections: [
|
sections: [
|
||||||
{
|
{
|
||||||
@ -150,12 +150,25 @@ describe("Compiler", () => {
|
|||||||
new Paragraph({
|
new Paragraph({
|
||||||
children: [
|
children: [
|
||||||
new ImageRun({
|
new ImageRun({
|
||||||
|
type: "png",
|
||||||
data: Buffer.from("", "base64"),
|
data: Buffer.from("", "base64"),
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
new ImageRun({
|
||||||
|
type: "svg",
|
||||||
|
data: Buffer.from("", "base64"),
|
||||||
|
transformation: {
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
},
|
||||||
|
fallback: {
|
||||||
|
type: "png",
|
||||||
|
data: Buffer.from("", "base64"),
|
||||||
|
},
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@ -165,7 +178,8 @@ describe("Compiler", () => {
|
|||||||
|
|
||||||
vi.spyOn(compiler["imageReplacer"], "getMediaData").mockReturnValue([
|
vi.spyOn(compiler["imageReplacer"], "getMediaData").mockReturnValue([
|
||||||
{
|
{
|
||||||
stream: Buffer.from(""),
|
type: "png",
|
||||||
|
data: Buffer.from(""),
|
||||||
fileName: "test",
|
fileName: "test",
|
||||||
transformation: {
|
transformation: {
|
||||||
pixels: {
|
pixels: {
|
||||||
@ -178,9 +192,48 @@ describe("Compiler", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "svg",
|
||||||
|
data: Buffer.from(""),
|
||||||
|
fileName: "test",
|
||||||
|
transformation: {
|
||||||
|
pixels: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
emus: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fallback: {
|
||||||
|
type: "png",
|
||||||
|
data: Buffer.from(""),
|
||||||
|
fileName: "test",
|
||||||
|
transformation: {
|
||||||
|
pixels: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
emus: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
compiler.compile(file);
|
compiler.compile(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should work with fonts", () => {
|
||||||
|
const file = new File({
|
||||||
|
sections: [],
|
||||||
|
fonts: [{ name: "Pacifico", data: Buffer.from("") }],
|
||||||
|
});
|
||||||
|
|
||||||
|
compiler.compile(file);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -2,6 +2,7 @@ import JSZip from "jszip";
|
|||||||
import xml from "xml";
|
import xml from "xml";
|
||||||
|
|
||||||
import { File } from "@file/file";
|
import { File } from "@file/file";
|
||||||
|
import { obfuscate } from "@file/fonts/obfuscate-ttf-to-odttf";
|
||||||
|
|
||||||
import { Formatter } from "../formatter";
|
import { Formatter } from "../formatter";
|
||||||
import { ImageReplacer } from "./image-replacer";
|
import { ImageReplacer } from "./image-replacer";
|
||||||
@ -31,6 +32,8 @@ interface IXmlifyedFileMapping {
|
|||||||
readonly FootNotesRelationships: IXmlifyedFile;
|
readonly FootNotesRelationships: IXmlifyedFile;
|
||||||
readonly Settings: IXmlifyedFile;
|
readonly Settings: IXmlifyedFile;
|
||||||
readonly Comments?: IXmlifyedFile;
|
readonly Comments?: IXmlifyedFile;
|
||||||
|
readonly FontTable?: IXmlifyedFile;
|
||||||
|
readonly FontTableRelationships?: IXmlifyedFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Compiler {
|
export class Compiler {
|
||||||
@ -44,7 +47,7 @@ export class Compiler {
|
|||||||
this.numberingReplacer = new NumberingReplacer();
|
this.numberingReplacer = new NumberingReplacer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public compile(file: File, prettifyXml?: PrettifyType): JSZip {
|
public compile(file: File, prettifyXml?: (typeof PrettifyType)[keyof typeof PrettifyType]): JSZip {
|
||||||
const zip = new JSZip();
|
const zip = new JSZip();
|
||||||
const xmlifiedFileMapping = this.xmlifyFile(file, prettifyXml);
|
const xmlifiedFileMapping = this.xmlifyFile(file, prettifyXml);
|
||||||
const map = new Map<string, IXmlifyedFile | readonly IXmlifyedFile[]>(Object.entries(xmlifiedFileMapping));
|
const map = new Map<string, IXmlifyedFile | readonly IXmlifyedFile[]>(Object.entries(xmlifiedFileMapping));
|
||||||
@ -59,14 +62,24 @@ export class Compiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const { stream, fileName } of file.Media.Array) {
|
for (const data of file.Media.Array) {
|
||||||
zip.file(`word/media/${fileName}`, stream);
|
if (data.type !== "svg") {
|
||||||
|
zip.file(`word/media/${data.fileName}`, data.data);
|
||||||
|
} else {
|
||||||
|
zip.file(`word/media/${data.fileName}`, data.data);
|
||||||
|
zip.file(`word/media/${data.fallback.fileName}`, data.fallback.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const { data: buffer, name, fontKey } of file.FontTable.fontOptionsWithKey) {
|
||||||
|
const [nameWithoutExtension] = name.split(".");
|
||||||
|
zip.file(`word/fonts/${nameWithoutExtension}.odttf`, obfuscate(buffer, fontKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
return zip;
|
return zip;
|
||||||
}
|
}
|
||||||
|
|
||||||
private xmlifyFile(file: File, prettify?: PrettifyType): IXmlifyedFileMapping {
|
private xmlifyFile(file: File, prettify?: (typeof PrettifyType)[keyof typeof PrettifyType]): IXmlifyedFileMapping {
|
||||||
const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
|
const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
|
||||||
|
|
||||||
const documentXmlData = xml(
|
const documentXmlData = xml(
|
||||||
@ -439,6 +452,40 @@ export class Compiler {
|
|||||||
),
|
),
|
||||||
path: "word/comments.xml",
|
path: "word/comments.xml",
|
||||||
},
|
},
|
||||||
|
FontTable: {
|
||||||
|
data: xml(
|
||||||
|
this.formatter.format(file.FontTable.View, {
|
||||||
|
viewWrapper: file.Document,
|
||||||
|
file,
|
||||||
|
stack: [],
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
standalone: "yes",
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
path: "word/fontTable.xml",
|
||||||
|
},
|
||||||
|
FontTableRelationships: {
|
||||||
|
data: (() =>
|
||||||
|
xml(
|
||||||
|
this.formatter.format(file.FontTable.Relationships, {
|
||||||
|
viewWrapper: file.Document,
|
||||||
|
file,
|
||||||
|
stack: [],
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
))(),
|
||||||
|
path: "word/_rels/fontTable.xml.rels",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,18 +6,21 @@ import { Compiler } from "./next-compiler";
|
|||||||
/**
|
/**
|
||||||
* Use blanks to prettify
|
* Use blanks to prettify
|
||||||
*/
|
*/
|
||||||
export enum PrettifyType {
|
export const PrettifyType = {
|
||||||
NONE = "",
|
NONE: "",
|
||||||
WITH_2_BLANKS = " ",
|
WITH_2_BLANKS: " ",
|
||||||
WITH_4_BLANKS = " ",
|
WITH_4_BLANKS: " ",
|
||||||
WITH_TAB = "\t",
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
}
|
WITH_TAB: "\t",
|
||||||
|
} as const;
|
||||||
|
|
||||||
const convertPrettifyType = (prettify?: boolean | PrettifyType): PrettifyType | undefined =>
|
const convertPrettifyType = (
|
||||||
|
prettify?: boolean | (typeof PrettifyType)[keyof typeof PrettifyType],
|
||||||
|
): (typeof PrettifyType)[keyof typeof PrettifyType] | undefined =>
|
||||||
prettify === true ? PrettifyType.WITH_2_BLANKS : prettify === false ? undefined : prettify;
|
prettify === true ? PrettifyType.WITH_2_BLANKS : prettify === false ? undefined : prettify;
|
||||||
|
|
||||||
export class Packer {
|
export class Packer {
|
||||||
public static async toString(file: File, prettify?: boolean | PrettifyType): Promise<string> {
|
public static async toString(file: File, prettify?: boolean | (typeof PrettifyType)[keyof typeof PrettifyType]): Promise<string> {
|
||||||
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
||||||
const zipData = await zip.generateAsync({
|
const zipData = await zip.generateAsync({
|
||||||
type: "string",
|
type: "string",
|
||||||
@ -28,7 +31,7 @@ export class Packer {
|
|||||||
return zipData;
|
return zipData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async toBuffer(file: File, prettify?: boolean | PrettifyType): Promise<Buffer> {
|
public static async toBuffer(file: File, prettify?: boolean | (typeof PrettifyType)[keyof typeof PrettifyType]): Promise<Buffer> {
|
||||||
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
||||||
const zipData = await zip.generateAsync({
|
const zipData = await zip.generateAsync({
|
||||||
type: "nodebuffer",
|
type: "nodebuffer",
|
||||||
@ -39,7 +42,7 @@ export class Packer {
|
|||||||
return zipData;
|
return zipData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async toBase64String(file: File, prettify?: boolean | PrettifyType): Promise<string> {
|
public static async toBase64String(file: File, prettify?: boolean | (typeof PrettifyType)[keyof typeof PrettifyType]): Promise<string> {
|
||||||
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
||||||
const zipData = await zip.generateAsync({
|
const zipData = await zip.generateAsync({
|
||||||
type: "base64",
|
type: "base64",
|
||||||
@ -50,7 +53,7 @@ export class Packer {
|
|||||||
return zipData;
|
return zipData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async toBlob(file: File, prettify?: boolean | PrettifyType): Promise<Blob> {
|
public static async toBlob(file: File, prettify?: boolean | (typeof PrettifyType)[keyof typeof PrettifyType]): Promise<Blob> {
|
||||||
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
||||||
const zipData = await zip.generateAsync({
|
const zipData = await zip.generateAsync({
|
||||||
type: "blob",
|
type: "blob",
|
||||||
@ -61,7 +64,7 @@ export class Packer {
|
|||||||
return zipData;
|
return zipData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static toStream(file: File, prettify?: boolean | PrettifyType): Stream {
|
public static toStream(file: File, prettify?: boolean | (typeof PrettifyType)[keyof typeof PrettifyType]): Stream {
|
||||||
const stream = new Stream();
|
const stream = new Stream();
|
||||||
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
|||||||
import { eighthPointMeasureValue, hexColorValue, pointMeasureValue } from "@util/values";
|
import { eighthPointMeasureValue, hexColorValue, pointMeasureValue } from "@util/values";
|
||||||
|
|
||||||
export interface IBorderOptions {
|
export interface IBorderOptions {
|
||||||
readonly style: BorderStyle;
|
readonly style: (typeof BorderStyle)[keyof typeof BorderStyle];
|
||||||
/** Border color, in hex (eg 'FF00AA') */
|
/** Border color, in hex (eg 'FF00AA') */
|
||||||
readonly color?: string;
|
readonly color?: string;
|
||||||
/** Size of the border in 1/8 pt */
|
/** Size of the border in 1/8 pt */
|
||||||
@ -55,32 +55,34 @@ class BordersAttributes extends XmlAttributeComponent<IBorderOptions> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum BorderStyle {
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
SINGLE = "single",
|
export const BorderStyle = {
|
||||||
DASH_DOT_STROKED = "dashDotStroked",
|
SINGLE: "single",
|
||||||
DASHED = "dashed",
|
DASH_DOT_STROKED: "dashDotStroked",
|
||||||
DASH_SMALL_GAP = "dashSmallGap",
|
DASHED: "dashed",
|
||||||
DOT_DASH = "dotDash",
|
DASH_SMALL_GAP: "dashSmallGap",
|
||||||
DOT_DOT_DASH = "dotDotDash",
|
DOT_DASH: "dotDash",
|
||||||
DOTTED = "dotted",
|
DOT_DOT_DASH: "dotDotDash",
|
||||||
DOUBLE = "double",
|
DOTTED: "dotted",
|
||||||
DOUBLE_WAVE = "doubleWave",
|
DOUBLE: "double",
|
||||||
INSET = "inset",
|
DOUBLE_WAVE: "doubleWave",
|
||||||
NIL = "nil",
|
INSET: "inset",
|
||||||
NONE = "none",
|
NIL: "nil",
|
||||||
OUTSET = "outset",
|
NONE: "none",
|
||||||
THICK = "thick",
|
OUTSET: "outset",
|
||||||
THICK_THIN_LARGE_GAP = "thickThinLargeGap",
|
THICK: "thick",
|
||||||
THICK_THIN_MEDIUM_GAP = "thickThinMediumGap",
|
THICK_THIN_LARGE_GAP: "thickThinLargeGap",
|
||||||
THICK_THIN_SMALL_GAP = "thickThinSmallGap",
|
THICK_THIN_MEDIUM_GAP: "thickThinMediumGap",
|
||||||
THIN_THICK_LARGE_GAP = "thinThickLargeGap",
|
THICK_THIN_SMALL_GAP: "thickThinSmallGap",
|
||||||
THIN_THICK_MEDIUM_GAP = "thinThickMediumGap",
|
THIN_THICK_LARGE_GAP: "thinThickLargeGap",
|
||||||
THIN_THICK_SMALL_GAP = "thinThickSmallGap",
|
THIN_THICK_MEDIUM_GAP: "thinThickMediumGap",
|
||||||
THIN_THICK_THIN_LARGE_GAP = "thinThickThinLargeGap",
|
THIN_THICK_SMALL_GAP: "thinThickSmallGap",
|
||||||
THIN_THICK_THIN_MEDIUM_GAP = "thinThickThinMediumGap",
|
THIN_THICK_THIN_LARGE_GAP: "thinThickThinLargeGap",
|
||||||
THIN_THICK_THIN_SMALL_GAP = "thinThickThinSmallGap",
|
THIN_THICK_THIN_MEDIUM_GAP: "thinThickThinMediumGap",
|
||||||
THREE_D_EMBOSS = "threeDEmboss",
|
THIN_THICK_THIN_SMALL_GAP: "thinThickThinSmallGap",
|
||||||
THREE_D_ENGRAVE = "threeDEngrave",
|
THREE_D_EMBOSS: "threeDEmboss",
|
||||||
TRIPLE = "triple",
|
THREE_D_ENGRAVE: "threeDEngrave",
|
||||||
WAVE = "wave",
|
TRIPLE: "triple",
|
||||||
}
|
WAVE: "wave",
|
||||||
|
} as const;
|
||||||
|
/* eslint-enable */
|
||||||
|
@ -25,11 +25,21 @@ describe("ContentTypes", () => {
|
|||||||
expect(tree["Types"][3]).to.deep.equal({ Default: { _attr: { ContentType: "image/jpeg", Extension: "jpg" } } });
|
expect(tree["Types"][3]).to.deep.equal({ Default: { _attr: { ContentType: "image/jpeg", Extension: "jpg" } } });
|
||||||
expect(tree["Types"][4]).to.deep.equal({ Default: { _attr: { ContentType: "image/bmp", Extension: "bmp" } } });
|
expect(tree["Types"][4]).to.deep.equal({ Default: { _attr: { ContentType: "image/bmp", Extension: "bmp" } } });
|
||||||
expect(tree["Types"][5]).to.deep.equal({ Default: { _attr: { ContentType: "image/gif", Extension: "gif" } } });
|
expect(tree["Types"][5]).to.deep.equal({ Default: { _attr: { ContentType: "image/gif", Extension: "gif" } } });
|
||||||
expect(tree["Types"][6]).to.deep.equal({
|
expect(tree["Types"][6]).to.deep.equal({ Default: { _attr: { ContentType: "image/svg+xml", Extension: "svg" } } });
|
||||||
|
expect(tree["Types"][7]).to.deep.equal({
|
||||||
Default: { _attr: { ContentType: "application/vnd.openxmlformats-package.relationships+xml", Extension: "rels" } },
|
Default: { _attr: { ContentType: "application/vnd.openxmlformats-package.relationships+xml", Extension: "rels" } },
|
||||||
});
|
});
|
||||||
expect(tree["Types"][7]).to.deep.equal({ Default: { _attr: { ContentType: "application/xml", Extension: "xml" } } });
|
expect(tree["Types"][8]).to.deep.equal({ Default: { _attr: { ContentType: "application/xml", Extension: "xml" } } });
|
||||||
expect(tree["Types"][8]).to.deep.equal({
|
|
||||||
|
expect(tree["Types"][9]).to.deep.equal({
|
||||||
|
Default: {
|
||||||
|
_attr: {
|
||||||
|
ContentType: "application/vnd.openxmlformats-officedocument.obfuscatedFont",
|
||||||
|
Extension: "odttf",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(tree["Types"][10]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
|
||||||
@ -37,7 +47,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][9]).to.deep.equal({
|
expect(tree["Types"][11]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
|
||||||
@ -45,7 +55,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][10]).to.deep.equal({
|
expect(tree["Types"][12]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-package.core-properties+xml",
|
ContentType: "application/vnd.openxmlformats-package.core-properties+xml",
|
||||||
@ -53,7 +63,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][11]).to.deep.equal({
|
expect(tree["Types"][13]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.custom-properties+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.custom-properties+xml",
|
||||||
@ -61,7 +71,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][12]).to.deep.equal({
|
expect(tree["Types"][14]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.extended-properties+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.extended-properties+xml",
|
||||||
@ -69,7 +79,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][13]).to.deep.equal({
|
expect(tree["Types"][15]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
|
||||||
@ -77,7 +87,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][14]).to.deep.equal({
|
expect(tree["Types"][16]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml",
|
||||||
@ -85,7 +95,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][15]).to.deep.equal({
|
expect(tree["Types"][17]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
|
||||||
@ -102,7 +112,7 @@ describe("ContentTypes", () => {
|
|||||||
contentTypes.addFooter(102);
|
contentTypes.addFooter(102);
|
||||||
const tree = new Formatter().format(contentTypes);
|
const tree = new Formatter().format(contentTypes);
|
||||||
|
|
||||||
expect(tree["Types"][17]).to.deep.equal({
|
expect(tree["Types"][20]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml",
|
||||||
@ -111,7 +121,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(tree["Types"][18]).to.deep.equal({
|
expect(tree["Types"][21]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml",
|
||||||
@ -128,7 +138,7 @@ describe("ContentTypes", () => {
|
|||||||
contentTypes.addHeader(202);
|
contentTypes.addHeader(202);
|
||||||
const tree = new Formatter().format(contentTypes);
|
const tree = new Formatter().format(contentTypes);
|
||||||
|
|
||||||
expect(tree["Types"][17]).to.deep.equal({
|
expect(tree["Types"][20]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
|
||||||
@ -137,7 +147,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(tree["Types"][18]).to.deep.equal({
|
expect(tree["Types"][21]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
|
||||||
|
@ -18,8 +18,10 @@ export class ContentTypes extends XmlComponent {
|
|||||||
this.root.push(new Default("image/jpeg", "jpg"));
|
this.root.push(new Default("image/jpeg", "jpg"));
|
||||||
this.root.push(new Default("image/bmp", "bmp"));
|
this.root.push(new Default("image/bmp", "bmp"));
|
||||||
this.root.push(new Default("image/gif", "gif"));
|
this.root.push(new Default("image/gif", "gif"));
|
||||||
|
this.root.push(new Default("image/svg+xml", "svg"));
|
||||||
this.root.push(new Default("application/vnd.openxmlformats-package.relationships+xml", "rels"));
|
this.root.push(new Default("application/vnd.openxmlformats-package.relationships+xml", "rels"));
|
||||||
this.root.push(new Default("application/xml", "xml"));
|
this.root.push(new Default("application/xml", "xml"));
|
||||||
|
this.root.push(new Default("application/vnd.openxmlformats-officedocument.obfuscatedFont", "odttf"));
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "/word/document.xml"),
|
new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "/word/document.xml"),
|
||||||
@ -33,6 +35,7 @@ export class ContentTypes extends XmlComponent {
|
|||||||
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", "/word/footnotes.xml"));
|
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", "/word/footnotes.xml"));
|
||||||
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", "/word/settings.xml"));
|
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", "/word/settings.xml"));
|
||||||
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml", "/word/comments.xml"));
|
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml", "/word/comments.xml"));
|
||||||
|
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml", "/word/fontTable.xml"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public addFooter(index: number): void {
|
public addFooter(index: number): void {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { ICommentsOptions } from "@file/paragraph/run/comment-run";
|
import { ICommentsOptions } from "@file/paragraph/run/comment-run";
|
||||||
import { ICompatibilityOptions } from "@file/settings/compatibility";
|
import { ICompatibilityOptions } from "@file/settings/compatibility";
|
||||||
|
import { FontOptions } from "@file/fonts/font-table";
|
||||||
import { StringContainer, XmlComponent } from "@file/xml-components";
|
import { StringContainer, XmlComponent } from "@file/xml-components";
|
||||||
import { dateTimeValue } from "@util/values";
|
import { dateTimeValue } from "@util/values";
|
||||||
|
|
||||||
@ -39,6 +40,8 @@ export interface IPropertiesOptions {
|
|||||||
readonly compatibility?: ICompatibilityOptions;
|
readonly compatibility?: ICompatibilityOptions;
|
||||||
readonly customProperties?: readonly ICustomPropertyOptions[];
|
readonly customProperties?: readonly ICustomPropertyOptions[];
|
||||||
readonly evenAndOddHeaderAndFooters?: boolean;
|
readonly evenAndOddHeaderAndFooters?: boolean;
|
||||||
|
readonly defaultTabStop?: number;
|
||||||
|
readonly fonts?: readonly FontOptions[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// <xs:element name="coreProperties" type="CT_CoreProperties"/>
|
// <xs:element name="coreProperties" type="CT_CoreProperties"/>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { XmlComponent } from "./xml-components";
|
||||||
import { Document, IDocumentOptions } from "./document";
|
import { Document, IDocumentOptions } from "./document";
|
||||||
import { Footer } from "./footer/footer";
|
import { Footer } from "./footer/footer";
|
||||||
import { FootNotes } from "./footnotes";
|
import { FootNotes } from "./footnotes";
|
||||||
@ -5,7 +6,7 @@ import { Header } from "./header/header";
|
|||||||
import { Relationships } from "./relationships";
|
import { Relationships } from "./relationships";
|
||||||
|
|
||||||
export interface IViewWrapper {
|
export interface IViewWrapper {
|
||||||
readonly View: Document | Footer | Header | FootNotes;
|
readonly View: Document | Footer | Header | FootNotes | XmlComponent;
|
||||||
readonly Relationships: Relationships;
|
readonly Relationships: Relationships;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,14 +17,17 @@ import { decimalNumber } from "@util/values";
|
|||||||
// <xsd:attribute name="charSpace" type="ST_DecimalNumber"/>
|
// <xsd:attribute name="charSpace" type="ST_DecimalNumber"/>
|
||||||
// </xsd:complexType>
|
// </xsd:complexType>
|
||||||
|
|
||||||
export enum DocumentGridType {
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
DEFAULT = "default",
|
export const DocumentGridType = {
|
||||||
LINES = "lines",
|
DEFAULT: "default",
|
||||||
LINES_AND_CHARS = "linesAndChars",
|
LINES: "lines",
|
||||||
SNAP_TO_CHARS = "snapToChars",
|
LINES_AND_CHARS: "linesAndChars",
|
||||||
}
|
SNAP_TO_CHARS: "snapToChars",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/* eslint-enable */
|
||||||
export interface IDocGridAttributesProperties {
|
export interface IDocGridAttributesProperties {
|
||||||
readonly type?: DocumentGridType;
|
readonly type?: (typeof DocumentGridType)[keyof typeof DocumentGridType];
|
||||||
readonly linePitch?: number;
|
readonly linePitch?: number;
|
||||||
readonly charSpace?: number;
|
readonly charSpace?: number;
|
||||||
}
|
}
|
||||||
@ -38,7 +41,7 @@ export class DocGridAttributes extends XmlAttributeComponent<IDocGridAttributesP
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class DocumentGrid extends XmlComponent {
|
export class DocumentGrid extends XmlComponent {
|
||||||
public constructor(linePitch: number, charSpace?: number, type?: DocumentGridType) {
|
public constructor(linePitch: number, charSpace?: number, type?: (typeof DocumentGridType)[keyof typeof DocumentGridType]) {
|
||||||
super("w:docGrid");
|
super("w:docGrid");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
|
@ -7,11 +7,11 @@ import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
|||||||
// <xsd:enumeration value="first"/>
|
// <xsd:enumeration value="first"/>
|
||||||
// </xsd:restriction>
|
// </xsd:restriction>
|
||||||
// </xsd:simpleType>
|
// </xsd:simpleType>
|
||||||
export enum HeaderFooterReferenceType {
|
export const HeaderFooterReferenceType = {
|
||||||
DEFAULT = "default",
|
DEFAULT: "default",
|
||||||
FIRST = "first",
|
FIRST: "first",
|
||||||
EVEN = "even",
|
EVEN: "even",
|
||||||
}
|
} as const;
|
||||||
|
|
||||||
// </xsd:complexType>
|
// </xsd:complexType>
|
||||||
// <xsd:group name="EG_HdrFtrReferences">
|
// <xsd:group name="EG_HdrFtrReferences">
|
||||||
@ -33,12 +33,12 @@ export enum HeaderFooterReferenceType {
|
|||||||
// </xsd:complexType>
|
// </xsd:complexType>
|
||||||
|
|
||||||
export interface IHeaderFooterOptions {
|
export interface IHeaderFooterOptions {
|
||||||
readonly type?: HeaderFooterReferenceType;
|
readonly type?: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType];
|
||||||
readonly id?: number;
|
readonly id?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
class FooterReferenceAttributes extends XmlAttributeComponent<{
|
class FooterReferenceAttributes extends XmlAttributeComponent<{
|
||||||
readonly type: HeaderFooterReferenceType;
|
readonly type: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType];
|
||||||
readonly id: string;
|
readonly id: string;
|
||||||
}> {
|
}> {
|
||||||
protected readonly xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
@ -47,12 +47,13 @@ class FooterReferenceAttributes extends XmlAttributeComponent<{
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum HeaderFooterType {
|
export const HeaderFooterType = {
|
||||||
HEADER = "w:headerReference",
|
HEADER: "w:headerReference",
|
||||||
FOOTER = "w:footerReference",
|
FOOTER: "w:footerReference",
|
||||||
}
|
} as const;
|
||||||
|
|
||||||
export class HeaderFooterReference extends XmlComponent {
|
export class HeaderFooterReference extends XmlComponent {
|
||||||
public constructor(type: HeaderFooterType, options: IHeaderFooterOptions) {
|
public constructor(type: (typeof HeaderFooterType)[keyof typeof HeaderFooterType], options: IHeaderFooterOptions) {
|
||||||
super(type);
|
super(type);
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// http://officeopenxml.com/WPsectionLineNumbering.php
|
// http://officeopenxml.com/WPsectionLineNumbering.php
|
||||||
import { NextAttributeComponent, XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
import { decimalNumber, PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
|
import { decimalNumber, PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
|
||||||
|
|
||||||
// <xsd:simpleType name="ST_LineNumberRestart">
|
// <xsd:simpleType name="ST_LineNumberRestart">
|
||||||
@ -9,11 +9,14 @@ import { decimalNumber, PositiveUniversalMeasure, twipsMeasureValue } from "@uti
|
|||||||
// <xsd:enumeration value="continuous"/>
|
// <xsd:enumeration value="continuous"/>
|
||||||
// </xsd:restriction>
|
// </xsd:restriction>
|
||||||
// </xsd:simpleType>
|
// </xsd:simpleType>
|
||||||
export enum LineNumberRestartFormat {
|
|
||||||
NEW_PAGE = "newPage",
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
NEW_SECTION = "newSection",
|
export const LineNumberRestartFormat = {
|
||||||
CONTINUOUS = "continuous",
|
NEW_PAGE: "newPage",
|
||||||
}
|
NEW_SECTION: "newSection",
|
||||||
|
CONTINUOUS: "continuous",
|
||||||
|
} as const;
|
||||||
|
/* eslint-enable */
|
||||||
|
|
||||||
// <xsd:complexType name="CT_LineNumber">
|
// <xsd:complexType name="CT_LineNumber">
|
||||||
// <xsd:attribute name="countBy" type="ST_DecimalNumber" use="optional"/>
|
// <xsd:attribute name="countBy" type="ST_DecimalNumber" use="optional"/>
|
||||||
@ -22,28 +25,23 @@ export enum LineNumberRestartFormat {
|
|||||||
// <xsd:attribute name="restart" type="ST_LineNumberRestart" use="optional" default="newPage"/>
|
// <xsd:attribute name="restart" type="ST_LineNumberRestart" use="optional" default="newPage"/>
|
||||||
// </xsd:complexType>
|
// </xsd:complexType>
|
||||||
|
|
||||||
export interface ILineNumberAttributes {
|
export type ILineNumberAttributes = {
|
||||||
readonly countBy?: number;
|
readonly countBy?: number;
|
||||||
readonly start?: number;
|
readonly start?: number;
|
||||||
readonly restart?: LineNumberRestartFormat;
|
readonly restart?: (typeof LineNumberRestartFormat)[keyof typeof LineNumberRestartFormat];
|
||||||
readonly distance?: number | PositiveUniversalMeasure;
|
readonly distance?: number | PositiveUniversalMeasure;
|
||||||
}
|
};
|
||||||
|
|
||||||
export class LineNumberType extends XmlComponent {
|
export const createLineNumberType = ({ countBy, start, restart, distance }: ILineNumberAttributes): XmlComponent =>
|
||||||
public constructor({ countBy, start, restart, distance }: ILineNumberAttributes) {
|
new BuilderElement<ILineNumberAttributes>({
|
||||||
super("w:lnNumType");
|
name: "w:lnNumType",
|
||||||
this.root.push(
|
attributes: {
|
||||||
new NextAttributeComponent<{
|
|
||||||
readonly countBy?: number;
|
|
||||||
readonly start?: number;
|
|
||||||
readonly restart?: LineNumberRestartFormat;
|
|
||||||
readonly distance?: number | PositiveUniversalMeasure;
|
|
||||||
}>({
|
|
||||||
countBy: { key: "w:countBy", value: countBy === undefined ? undefined : decimalNumber(countBy) },
|
countBy: { key: "w:countBy", value: countBy === undefined ? undefined : decimalNumber(countBy) },
|
||||||
start: { key: "w:start", value: start === undefined ? undefined : decimalNumber(start) },
|
start: { key: "w:start", value: start === undefined ? undefined : decimalNumber(start) },
|
||||||
restart: { key: "w:restart", value: restart },
|
restart: { key: "w:restart", value: restart },
|
||||||
distance: { key: "w:distance", value: distance === undefined ? undefined : twipsMeasureValue(distance) },
|
distance: {
|
||||||
}),
|
key: "w:distance",
|
||||||
);
|
value: distance === undefined ? undefined : twipsMeasureValue(distance),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
});
|
||||||
|
@ -9,11 +9,14 @@ import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent } from "@file/xml-comp
|
|||||||
// <xsd:enumeration value="notFirstPage"/>
|
// <xsd:enumeration value="notFirstPage"/>
|
||||||
// </xsd:restriction>
|
// </xsd:restriction>
|
||||||
// </xsd:simpleType>
|
// </xsd:simpleType>
|
||||||
export enum PageBorderDisplay {
|
|
||||||
ALL_PAGES = "allPages",
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
FIRST_PAGE = "firstPage",
|
export const PageBorderDisplay = {
|
||||||
NOT_FIRST_PAGE = "notFirstPage",
|
ALL_PAGES: "allPages",
|
||||||
}
|
FIRST_PAGE: "firstPage",
|
||||||
|
NOT_FIRST_PAGE: "notFirstPage",
|
||||||
|
} as const;
|
||||||
|
/* eslint-enable */
|
||||||
|
|
||||||
// <xsd:simpleType name="ST_PageBorderOffset">
|
// <xsd:simpleType name="ST_PageBorderOffset">
|
||||||
// <xsd:restriction base="xsd:string">
|
// <xsd:restriction base="xsd:string">
|
||||||
@ -21,10 +24,10 @@ export enum PageBorderDisplay {
|
|||||||
// <xsd:enumeration value="text"/>
|
// <xsd:enumeration value="text"/>
|
||||||
// </xsd:restriction>
|
// </xsd:restriction>
|
||||||
// </xsd:simpleType>
|
// </xsd:simpleType>
|
||||||
export enum PageBorderOffsetFrom {
|
export const PageBorderOffsetFrom = {
|
||||||
PAGE = "page",
|
PAGE: "page",
|
||||||
TEXT = "text",
|
TEXT: "text",
|
||||||
}
|
} as const;
|
||||||
|
|
||||||
// <xsd:simpleType name="ST_PageBorderZOrder">
|
// <xsd:simpleType name="ST_PageBorderZOrder">
|
||||||
// <xsd:restriction base="xsd:string">
|
// <xsd:restriction base="xsd:string">
|
||||||
@ -32,15 +35,15 @@ export enum PageBorderOffsetFrom {
|
|||||||
// <xsd:enumeration value="back"/>
|
// <xsd:enumeration value="back"/>
|
||||||
// </xsd:restriction>
|
// </xsd:restriction>
|
||||||
// </xsd:simpleType>
|
// </xsd:simpleType>
|
||||||
export enum PageBorderZOrder {
|
export const PageBorderZOrder = {
|
||||||
BACK = "back",
|
BACK: "back",
|
||||||
FRONT = "front",
|
FRONT: "front",
|
||||||
}
|
} as const;
|
||||||
|
|
||||||
export interface IPageBorderAttributes {
|
export interface IPageBorderAttributes {
|
||||||
readonly display?: PageBorderDisplay;
|
readonly display?: (typeof PageBorderDisplay)[keyof typeof PageBorderDisplay];
|
||||||
readonly offsetFrom?: PageBorderOffsetFrom;
|
readonly offsetFrom?: (typeof PageBorderOffsetFrom)[keyof typeof PageBorderOffsetFrom];
|
||||||
readonly zOrder?: PageBorderZOrder;
|
readonly zOrder?: (typeof PageBorderZOrder)[keyof typeof PageBorderZOrder];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPageBordersOptions {
|
export interface IPageBordersOptions {
|
||||||
|
@ -12,18 +12,22 @@ import { decimalNumber } from "@util/values";
|
|||||||
// <xsd:enumeration value="enDash"/>
|
// <xsd:enumeration value="enDash"/>
|
||||||
// </xsd:restriction>
|
// </xsd:restriction>
|
||||||
// </xsd:simpleType>
|
// </xsd:simpleType>
|
||||||
export enum PageNumberSeparator {
|
|
||||||
HYPHEN = "hyphen",
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
PERIOD = "period",
|
export const PageNumberSeparator = {
|
||||||
COLON = "colon",
|
HYPHEN: "hyphen",
|
||||||
EM_DASH = "emDash",
|
PERIOD: "period",
|
||||||
EN_DASH = "endash",
|
COLON: "colon",
|
||||||
}
|
EM_DASH: "emDash",
|
||||||
|
EN_DASH: "endash",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/* eslint-enable */
|
||||||
|
|
||||||
export interface IPageNumberTypeAttributes {
|
export interface IPageNumberTypeAttributes {
|
||||||
readonly start?: number;
|
readonly start?: number;
|
||||||
readonly formatType?: NumberFormat;
|
readonly formatType?: (typeof NumberFormat)[keyof typeof NumberFormat];
|
||||||
readonly separator?: PageNumberSeparator;
|
readonly separator?: (typeof PageNumberSeparator)[keyof typeof PageNumberSeparator];
|
||||||
}
|
}
|
||||||
|
|
||||||
// <xsd:complexType name="CT_PageNumber">
|
// <xsd:complexType name="CT_PageNumber">
|
||||||
@ -40,6 +44,7 @@ export class PageNumberTypeAttributes extends XmlAttributeComponent<IPageNumberT
|
|||||||
separator: "w:chapSep",
|
separator: "w:chapSep",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PageNumberType extends XmlComponent {
|
export class PageNumberType extends XmlComponent {
|
||||||
public constructor({ start, formatType, separator }: IPageNumberTypeAttributes) {
|
public constructor({ start, formatType, separator }: IPageNumberTypeAttributes) {
|
||||||
super("w:pgNumType");
|
super("w:pgNumType");
|
||||||
|
@ -7,10 +7,10 @@ import { PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
|
|||||||
// <xsd:enumeration value="landscape"/>
|
// <xsd:enumeration value="landscape"/>
|
||||||
// </xsd:restriction>
|
// </xsd:restriction>
|
||||||
// </xsd:simpleType>
|
// </xsd:simpleType>
|
||||||
export enum PageOrientation {
|
export const PageOrientation = {
|
||||||
PORTRAIT = "portrait",
|
PORTRAIT: "portrait",
|
||||||
LANDSCAPE = "landscape",
|
LANDSCAPE: "landscape",
|
||||||
}
|
} as const;
|
||||||
|
|
||||||
// <xsd:complexType name="CT_PageSz">
|
// <xsd:complexType name="CT_PageSz">
|
||||||
// <xsd:attribute name="w" type="s:ST_TwipsMeasure"/>
|
// <xsd:attribute name="w" type="s:ST_TwipsMeasure"/>
|
||||||
@ -21,11 +21,15 @@ export enum PageOrientation {
|
|||||||
export type IPageSizeAttributes = {
|
export type IPageSizeAttributes = {
|
||||||
readonly width?: number | PositiveUniversalMeasure;
|
readonly width?: number | PositiveUniversalMeasure;
|
||||||
readonly height?: number | PositiveUniversalMeasure;
|
readonly height?: number | PositiveUniversalMeasure;
|
||||||
readonly orientation?: PageOrientation;
|
readonly orientation?: (typeof PageOrientation)[keyof typeof PageOrientation];
|
||||||
};
|
};
|
||||||
|
|
||||||
export class PageSize extends XmlComponent {
|
export class PageSize extends XmlComponent {
|
||||||
public constructor(width: number | PositiveUniversalMeasure, height: number | PositiveUniversalMeasure, orientation: PageOrientation) {
|
public constructor(
|
||||||
|
width: number | PositiveUniversalMeasure,
|
||||||
|
height: number | PositiveUniversalMeasure,
|
||||||
|
orientation: (typeof PageOrientation)[keyof typeof PageOrientation],
|
||||||
|
) {
|
||||||
super("w:pgSz");
|
super("w:pgSz");
|
||||||
|
|
||||||
const flip = orientation === PageOrientation.LANDSCAPE;
|
const flip = orientation === PageOrientation.LANDSCAPE;
|
||||||
|
@ -1,16 +1,21 @@
|
|||||||
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
export enum PageTextDirectionType {
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
LEFT_TO_RIGHT_TOP_TO_BOTTOM = "lrTb",
|
export const PageTextDirectionType = {
|
||||||
TOP_TO_BOTTOM_RIGHT_TO_LEFT = "tbRl",
|
LEFT_TO_RIGHT_TOP_TO_BOTTOM: "lrTb",
|
||||||
}
|
TOP_TO_BOTTOM_RIGHT_TO_LEFT: "tbRl",
|
||||||
|
} as const;
|
||||||
|
|
||||||
class PageTextDirectionAttributes extends XmlAttributeComponent<{ readonly val: PageTextDirectionType }> {
|
/* eslint-enable */
|
||||||
|
|
||||||
|
class PageTextDirectionAttributes extends XmlAttributeComponent<{
|
||||||
|
readonly val: (typeof PageTextDirectionType)[keyof typeof PageTextDirectionType];
|
||||||
|
}> {
|
||||||
protected readonly xmlKeys = { val: "w:val" };
|
protected readonly xmlKeys = { val: "w:val" };
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PageTextDirection extends XmlComponent {
|
export class PageTextDirection extends XmlComponent {
|
||||||
public constructor(value: PageTextDirectionType) {
|
public constructor(value: (typeof PageTextDirectionType)[keyof typeof PageTextDirectionType]) {
|
||||||
super("w:textDirection");
|
super("w:textDirection");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
|
@ -10,19 +10,22 @@ import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
|||||||
// <xsd:enumeration value="oddPage"/>
|
// <xsd:enumeration value="oddPage"/>
|
||||||
// </xsd:restriction>
|
// </xsd:restriction>
|
||||||
// </xsd:simpleType>
|
// </xsd:simpleType>
|
||||||
export enum SectionType {
|
|
||||||
NEXT_PAGE = "nextPage",
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
NEXT_COLUMN = "nextColumn",
|
export const SectionType = {
|
||||||
CONTINUOUS = "continuous",
|
NEXT_PAGE: "nextPage",
|
||||||
EVEN_PAGE = "evenPage",
|
NEXT_COLUMN: "nextColumn",
|
||||||
ODD_PAGE = "oddPage",
|
CONTINUOUS: "continuous",
|
||||||
}
|
EVEN_PAGE: "evenPage",
|
||||||
|
ODD_PAGE: "oddPage",
|
||||||
|
} as const;
|
||||||
|
/* eslint-enable */
|
||||||
|
|
||||||
// <xsd:complexType name="CT_SectType">
|
// <xsd:complexType name="CT_SectType">
|
||||||
// <xsd:attribute name="val" type="ST_SectionMark"/>
|
// <xsd:attribute name="val" type="ST_SectionMark"/>
|
||||||
// </xsd:complexType>
|
// </xsd:complexType>
|
||||||
export class SectionTypeAttributes extends XmlAttributeComponent<{
|
export class SectionTypeAttributes extends XmlAttributeComponent<{
|
||||||
readonly val: SectionType;
|
readonly val: (typeof SectionType)[keyof typeof SectionType];
|
||||||
}> {
|
}> {
|
||||||
protected readonly xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
val: "w:val",
|
val: "w:val",
|
||||||
@ -30,7 +33,7 @@ export class SectionTypeAttributes extends XmlAttributeComponent<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Type extends XmlComponent {
|
export class Type extends XmlComponent {
|
||||||
public constructor(value: SectionType) {
|
public constructor(value: (typeof SectionType)[keyof typeof SectionType]) {
|
||||||
super("w:type");
|
super("w:type");
|
||||||
this.root.push(new SectionTypeAttributes({ val: value }));
|
this.root.push(new SectionTypeAttributes({ val: value }));
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,11 @@ import { FooterWrapper } from "@file/footer-wrapper";
|
|||||||
import { HeaderWrapper } from "@file/header-wrapper";
|
import { HeaderWrapper } from "@file/header-wrapper";
|
||||||
import { VerticalAlign, VerticalAlignElement } from "@file/vertical-align";
|
import { VerticalAlign, VerticalAlignElement } from "@file/vertical-align";
|
||||||
import { OnOffElement, XmlComponent } from "@file/xml-components";
|
import { OnOffElement, XmlComponent } from "@file/xml-components";
|
||||||
import { PositiveUniversalMeasure, UniversalMeasure } from "@util/values";
|
|
||||||
|
|
||||||
import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./properties/header-footer-reference";
|
import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./properties/header-footer-reference";
|
||||||
import { Columns, IColumnsAttributes } from "./properties/columns";
|
import { Columns, IColumnsAttributes } from "./properties/columns";
|
||||||
import { DocumentGrid, IDocGridAttributesProperties } from "./properties/doc-grid";
|
import { DocumentGrid, IDocGridAttributesProperties } from "./properties/doc-grid";
|
||||||
import { ILineNumberAttributes, LineNumberType } from "./properties/line-number";
|
import { ILineNumberAttributes, createLineNumberType } from "./properties/line-number";
|
||||||
import { IPageBordersOptions, PageBorders } from "./properties/page-borders";
|
import { IPageBordersOptions, PageBorders } from "./properties/page-borders";
|
||||||
import { IPageMarginAttributes, PageMargin } from "./properties/page-margin";
|
import { IPageMarginAttributes, PageMargin } from "./properties/page-margin";
|
||||||
import { IPageNumberTypeAttributes, PageNumberType } from "./properties/page-number";
|
import { IPageNumberTypeAttributes, PageNumberType } from "./properties/page-number";
|
||||||
@ -30,16 +29,16 @@ export interface ISectionPropertiesOptions {
|
|||||||
readonly margin?: IPageMarginAttributes;
|
readonly margin?: IPageMarginAttributes;
|
||||||
readonly pageNumbers?: IPageNumberTypeAttributes;
|
readonly pageNumbers?: IPageNumberTypeAttributes;
|
||||||
readonly borders?: IPageBordersOptions;
|
readonly borders?: IPageBordersOptions;
|
||||||
readonly textDirection?: PageTextDirectionType;
|
readonly textDirection?: (typeof PageTextDirectionType)[keyof typeof PageTextDirectionType];
|
||||||
};
|
};
|
||||||
readonly grid?: IDocGridAttributesProperties;
|
readonly grid?: IDocGridAttributesProperties;
|
||||||
readonly headerWrapperGroup?: IHeaderFooterGroup<HeaderWrapper>;
|
readonly headerWrapperGroup?: IHeaderFooterGroup<HeaderWrapper>;
|
||||||
readonly footerWrapperGroup?: IHeaderFooterGroup<FooterWrapper>;
|
readonly footerWrapperGroup?: IHeaderFooterGroup<FooterWrapper>;
|
||||||
readonly lineNumbers?: ILineNumberAttributes;
|
readonly lineNumbers?: ILineNumberAttributes;
|
||||||
readonly titlePage?: boolean;
|
readonly titlePage?: boolean;
|
||||||
readonly verticalAlign?: VerticalAlign;
|
readonly verticalAlign?: (typeof VerticalAlign)[keyof typeof VerticalAlign];
|
||||||
readonly column?: IColumnsAttributes;
|
readonly column?: IColumnsAttributes;
|
||||||
readonly type?: SectionType;
|
readonly type?: (typeof SectionType)[keyof typeof SectionType];
|
||||||
}
|
}
|
||||||
|
|
||||||
// <xsd:complexType name="CT_SectPr">
|
// <xsd:complexType name="CT_SectPr">
|
||||||
@ -76,10 +75,10 @@ export interface ISectionPropertiesOptions {
|
|||||||
// </xsd:group>
|
// </xsd:group>
|
||||||
|
|
||||||
export const sectionMarginDefaults = {
|
export const sectionMarginDefaults = {
|
||||||
TOP: "1in" as UniversalMeasure,
|
TOP: 1440,
|
||||||
RIGHT: "1in" as PositiveUniversalMeasure,
|
RIGHT: 1440,
|
||||||
BOTTOM: "1in" as UniversalMeasure,
|
BOTTOM: 1440,
|
||||||
LEFT: "1in" as PositiveUniversalMeasure,
|
LEFT: 1440,
|
||||||
HEADER: 708,
|
HEADER: 708,
|
||||||
FOOTER: 708,
|
FOOTER: 708,
|
||||||
GUTTER: 0,
|
GUTTER: 0,
|
||||||
@ -138,7 +137,7 @@ export class SectionProperties extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lineNumbers) {
|
if (lineNumbers) {
|
||||||
this.root.push(new LineNumberType(lineNumbers));
|
this.root.push(createLineNumberType(lineNumbers));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.root.push(new PageNumberType(pageNumbers));
|
this.root.push(new PageNumberType(pageNumbers));
|
||||||
@ -163,7 +162,7 @@ export class SectionProperties extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private addHeaderFooterGroup(
|
private addHeaderFooterGroup(
|
||||||
type: HeaderFooterType,
|
type: (typeof HeaderFooterType)[keyof typeof HeaderFooterType],
|
||||||
group: IHeaderFooterGroup<HeaderWrapper> | IHeaderFooterGroup<FooterWrapper>,
|
group: IHeaderFooterGroup<HeaderWrapper> | IHeaderFooterGroup<FooterWrapper>,
|
||||||
): void {
|
): void {
|
||||||
if (group.default) {
|
if (group.default) {
|
||||||
|
@ -80,6 +80,7 @@ export class Document extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public add(item: Paragraph | Table | TableOfContents | ConcreteHyperlink): Document {
|
public add(item: Paragraph | Table | TableOfContents | ConcreteHyperlink): Document {
|
||||||
|
// eslint-disable-next-line functional/immutable-data
|
||||||
this.body.push(item);
|
this.body.push(item);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,11 @@ import { TextWrappingType } from "../text-wrap";
|
|||||||
import { Anchor } from "./anchor";
|
import { Anchor } from "./anchor";
|
||||||
|
|
||||||
const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
||||||
new Anchor(
|
new Anchor({
|
||||||
{
|
mediaData: {
|
||||||
|
type: "png",
|
||||||
fileName: "test.png",
|
fileName: "test.png",
|
||||||
stream: new Buffer(""),
|
data: Buffer.from(""),
|
||||||
transformation: {
|
transformation: {
|
||||||
pixels: {
|
pixels: {
|
||||||
x: 0,
|
x: 0,
|
||||||
@ -24,7 +25,7 @@ const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
transform: {
|
||||||
pixels: {
|
pixels: {
|
||||||
x: 100,
|
x: 100,
|
||||||
y: 100,
|
y: 100,
|
||||||
@ -35,7 +36,7 @@ const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
drawingOptions,
|
drawingOptions,
|
||||||
);
|
});
|
||||||
|
|
||||||
describe("Anchor", () => {
|
describe("Anchor", () => {
|
||||||
let anchor: Anchor;
|
let anchor: Anchor;
|
||||||
|
@ -6,7 +6,7 @@ import { HorizontalPosition, IFloating, SimplePos, VerticalPosition } from "../f
|
|||||||
import { Graphic } from "../inline/graphic";
|
import { Graphic } from "../inline/graphic";
|
||||||
import { TextWrappingType, WrapNone, WrapSquare, WrapTight, WrapTopAndBottom } from "../text-wrap";
|
import { TextWrappingType, WrapNone, WrapSquare, WrapTight, WrapTopAndBottom } from "../text-wrap";
|
||||||
import { DocProperties } from "./../doc-properties/doc-properties";
|
import { DocProperties } from "./../doc-properties/doc-properties";
|
||||||
import { EffectExtent } from "./../effect-extent/effect-extent";
|
import { createEffectExtent } from "./../effect-extent/effect-extent";
|
||||||
import { Extent } from "./../extent/extent";
|
import { Extent } from "./../extent/extent";
|
||||||
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
||||||
import { AnchorAttributes } from "./anchor-attributes";
|
import { AnchorAttributes } from "./anchor-attributes";
|
||||||
@ -37,7 +37,15 @@ import { AnchorAttributes } from "./anchor-attributes";
|
|||||||
// <xsd:attribute name="allowOverlap" type="xsd:boolean" use="required"/>
|
// <xsd:attribute name="allowOverlap" type="xsd:boolean" use="required"/>
|
||||||
// </xsd:complexType>
|
// </xsd:complexType>
|
||||||
export class Anchor extends XmlComponent {
|
export class Anchor extends XmlComponent {
|
||||||
public constructor(mediaData: IMediaData, transform: IMediaDataTransformation, drawingOptions: IDrawingOptions) {
|
public constructor({
|
||||||
|
mediaData,
|
||||||
|
transform,
|
||||||
|
drawingOptions,
|
||||||
|
}: {
|
||||||
|
readonly mediaData: IMediaData;
|
||||||
|
readonly transform: IMediaDataTransformation;
|
||||||
|
readonly drawingOptions: IDrawingOptions;
|
||||||
|
}) {
|
||||||
super("wp:anchor");
|
super("wp:anchor");
|
||||||
|
|
||||||
const floating: IFloating = {
|
const floating: IFloating = {
|
||||||
@ -69,7 +77,7 @@ export class Anchor extends XmlComponent {
|
|||||||
this.root.push(new HorizontalPosition(floating.horizontalPosition));
|
this.root.push(new HorizontalPosition(floating.horizontalPosition));
|
||||||
this.root.push(new VerticalPosition(floating.verticalPosition));
|
this.root.push(new VerticalPosition(floating.verticalPosition));
|
||||||
this.root.push(new Extent(transform.emus.x, transform.emus.y));
|
this.root.push(new Extent(transform.emus.x, transform.emus.y));
|
||||||
this.root.push(new EffectExtent());
|
this.root.push(createEffectExtent({ top: 0, right: 0, bottom: 0, left: 0 }));
|
||||||
|
|
||||||
if (drawingOptions.floating !== undefined && drawingOptions.floating.wrap !== undefined) {
|
if (drawingOptions.floating !== undefined && drawingOptions.floating.wrap !== undefined) {
|
||||||
switch (drawingOptions.floating.wrap.type) {
|
switch (drawingOptions.floating.wrap.type) {
|
||||||
@ -92,6 +100,6 @@ export class Anchor extends XmlComponent {
|
|||||||
|
|
||||||
this.root.push(new DocProperties(drawingOptions.docProperties));
|
this.root.push(new DocProperties(drawingOptions.docProperties));
|
||||||
this.root.push(new GraphicFrameProperties());
|
this.root.push(new GraphicFrameProperties());
|
||||||
this.root.push(new Graphic(mediaData, transform));
|
this.root.push(new Graphic({ mediaData, transform, outline: drawingOptions.outline }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,9 @@ const imageBase64Data = `iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAACzVBMVEU
|
|||||||
const createDrawing = (drawingOptions?: IDrawingOptions): Drawing =>
|
const createDrawing = (drawingOptions?: IDrawingOptions): Drawing =>
|
||||||
new Drawing(
|
new Drawing(
|
||||||
{
|
{
|
||||||
|
type: "jpg",
|
||||||
fileName: "test.jpg",
|
fileName: "test.jpg",
|
||||||
stream: Buffer.from(imageBase64Data, "base64"),
|
data: Buffer.from(imageBase64Data, "base64"),
|
||||||
transformation: {
|
transformation: {
|
||||||
pixels: {
|
pixels: {
|
||||||
x: 100,
|
x: 100,
|
||||||
|
@ -4,18 +4,20 @@ import { XmlComponent } from "@file/xml-components";
|
|||||||
import { Anchor } from "./anchor";
|
import { Anchor } from "./anchor";
|
||||||
import { DocPropertiesOptions } from "./doc-properties/doc-properties";
|
import { DocPropertiesOptions } from "./doc-properties/doc-properties";
|
||||||
import { IFloating } from "./floating";
|
import { IFloating } from "./floating";
|
||||||
import { Inline } from "./inline";
|
import { createInline } from "./inline";
|
||||||
|
import { OutlineOptions } from "./inline/graphic/graphic-data/pic/shape-properties/outline/outline";
|
||||||
|
|
||||||
export interface IDistance {
|
export type IDistance = {
|
||||||
readonly distT?: number;
|
readonly distT?: number;
|
||||||
readonly distB?: number;
|
readonly distB?: number;
|
||||||
readonly distL?: number;
|
readonly distL?: number;
|
||||||
readonly distR?: number;
|
readonly distR?: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface IDrawingOptions {
|
export interface IDrawingOptions {
|
||||||
readonly floating?: IFloating;
|
readonly floating?: IFloating;
|
||||||
readonly docProperties?: DocPropertiesOptions;
|
readonly docProperties?: DocPropertiesOptions;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <xsd:complexType name="CT_Drawing">
|
// <xsd:complexType name="CT_Drawing">
|
||||||
@ -30,14 +32,16 @@ export class Drawing extends XmlComponent {
|
|||||||
super("w:drawing");
|
super("w:drawing");
|
||||||
|
|
||||||
if (!drawingOptions.floating) {
|
if (!drawingOptions.floating) {
|
||||||
const inline = new Inline({
|
this.root.push(
|
||||||
|
createInline({
|
||||||
mediaData: imageData,
|
mediaData: imageData,
|
||||||
transform: imageData.transformation,
|
transform: imageData.transformation,
|
||||||
docProperties: drawingOptions.docProperties,
|
docProperties: drawingOptions.docProperties,
|
||||||
});
|
outline: drawingOptions.outline,
|
||||||
this.root.push(inline);
|
}),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.root.push(new Anchor(imageData, imageData.transformation, drawingOptions));
|
this.root.push(new Anchor({ mediaData: imageData, transform: imageData.transformation, drawingOptions }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
import { XmlAttributeComponent } from "@file/xml-components";
|
|
||||||
|
|
||||||
export class EffectExtentAttributes extends XmlAttributeComponent<{
|
|
||||||
readonly b?: number;
|
|
||||||
readonly l?: number;
|
|
||||||
readonly r?: number;
|
|
||||||
readonly t?: number;
|
|
||||||
}> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
b: "b",
|
|
||||||
l: "l",
|
|
||||||
r: "r",
|
|
||||||
t: "t",
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,17 +1,37 @@
|
|||||||
import { XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
import { EffectExtentAttributes } from "./effect-extent-attributes";
|
|
||||||
|
|
||||||
export class EffectExtent extends XmlComponent {
|
export type EffectExtentAttributes = {
|
||||||
public constructor() {
|
readonly top: number;
|
||||||
super("wp:effectExtent");
|
readonly right: number;
|
||||||
|
readonly bottom: number;
|
||||||
|
readonly left: number;
|
||||||
|
};
|
||||||
|
|
||||||
this.root.push(
|
// <xsd:complexType name="CT_EffectExtent">
|
||||||
new EffectExtentAttributes({
|
// <xsd:attribute name="l" type="a:ST_Coordinate" use="required"/>
|
||||||
b: 0,
|
// <xsd:attribute name="t" type="a:ST_Coordinate" use="required"/>
|
||||||
l: 0,
|
// <xsd:attribute name="r" type="a:ST_Coordinate" use="required"/>
|
||||||
r: 0,
|
// <xsd:attribute name="b" type="a:ST_Coordinate" use="required"/>
|
||||||
t: 0,
|
// </xsd:complexType>
|
||||||
}),
|
export const createEffectExtent = ({ top, right, bottom, left }: EffectExtentAttributes): XmlComponent =>
|
||||||
);
|
new BuilderElement<EffectExtentAttributes>({
|
||||||
}
|
name: "wp:effectExtent",
|
||||||
}
|
attributes: {
|
||||||
|
top: {
|
||||||
|
key: "t",
|
||||||
|
value: top,
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
key: "r",
|
||||||
|
value: right,
|
||||||
|
},
|
||||||
|
bottom: {
|
||||||
|
key: "b",
|
||||||
|
value: bottom,
|
||||||
|
},
|
||||||
|
left: {
|
||||||
|
key: "l",
|
||||||
|
value: left,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
@ -3,7 +3,11 @@ import { HorizontalPositionAlign, VerticalPositionAlign } from "@file/shared/ali
|
|||||||
import { XmlComponent } from "@file/xml-components";
|
import { XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
export class Align extends XmlComponent {
|
export class Align extends XmlComponent {
|
||||||
public constructor(value: HorizontalPositionAlign | VerticalPositionAlign) {
|
public constructor(
|
||||||
|
value:
|
||||||
|
| (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign]
|
||||||
|
| (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign],
|
||||||
|
) {
|
||||||
super("wp:align");
|
super("wp:align");
|
||||||
this.root.push(value);
|
this.root.push(value);
|
||||||
}
|
}
|
||||||
|
@ -4,37 +4,39 @@ import { HorizontalPositionAlign, VerticalPositionAlign } from "@file/shared/ali
|
|||||||
|
|
||||||
import { ITextWrapping } from "../text-wrap";
|
import { ITextWrapping } from "../text-wrap";
|
||||||
|
|
||||||
export enum HorizontalPositionRelativeFrom {
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
CHARACTER = "character",
|
export const HorizontalPositionRelativeFrom = {
|
||||||
COLUMN = "column",
|
CHARACTER: "character",
|
||||||
INSIDE_MARGIN = "insideMargin",
|
COLUMN: "column",
|
||||||
LEFT_MARGIN = "leftMargin",
|
INSIDE_MARGIN: "insideMargin",
|
||||||
MARGIN = "margin",
|
LEFT_MARGIN: "leftMargin",
|
||||||
OUTSIDE_MARGIN = "outsideMargin",
|
MARGIN: "margin",
|
||||||
PAGE = "page",
|
OUTSIDE_MARGIN: "outsideMargin",
|
||||||
RIGHT_MARGIN = "rightMargin",
|
PAGE: "page",
|
||||||
}
|
RIGHT_MARGIN: "rightMargin",
|
||||||
|
} as const;
|
||||||
|
|
||||||
export enum VerticalPositionRelativeFrom {
|
export const VerticalPositionRelativeFrom = {
|
||||||
BOTTOM_MARGIN = "bottomMargin",
|
BOTTOM_MARGIN: "bottomMargin",
|
||||||
INSIDE_MARGIN = "insideMargin",
|
INSIDE_MARGIN: "insideMargin",
|
||||||
LINE = "line",
|
LINE: "line",
|
||||||
MARGIN = "margin",
|
MARGIN: "margin",
|
||||||
OUTSIDE_MARGIN = "outsideMargin",
|
OUTSIDE_MARGIN: "outsideMargin",
|
||||||
PAGE = "page",
|
PAGE: "page",
|
||||||
PARAGRAPH = "paragraph",
|
PARAGRAPH: "paragraph",
|
||||||
TOP_MARGIN = "topMargin",
|
TOP_MARGIN: "topMargin",
|
||||||
}
|
} as const;
|
||||||
|
|
||||||
|
/* eslint-enable */
|
||||||
export interface IHorizontalPositionOptions {
|
export interface IHorizontalPositionOptions {
|
||||||
readonly relative?: HorizontalPositionRelativeFrom;
|
readonly relative?: (typeof HorizontalPositionRelativeFrom)[keyof typeof HorizontalPositionRelativeFrom];
|
||||||
readonly align?: HorizontalPositionAlign;
|
readonly align?: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign];
|
||||||
readonly offset?: number;
|
readonly offset?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IVerticalPositionOptions {
|
export interface IVerticalPositionOptions {
|
||||||
readonly relative?: VerticalPositionRelativeFrom;
|
readonly relative?: (typeof VerticalPositionRelativeFrom)[keyof typeof VerticalPositionRelativeFrom];
|
||||||
readonly align?: VerticalPositionAlign;
|
readonly align?: (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign];
|
||||||
readonly offset?: number;
|
readonly offset?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { HorizontalPositionRelativeFrom, IHorizontalPositionOptions } from "./fl
|
|||||||
import { PositionOffset } from "./position-offset";
|
import { PositionOffset } from "./position-offset";
|
||||||
|
|
||||||
class HorizontalPositionAttributes extends XmlAttributeComponent<{
|
class HorizontalPositionAttributes extends XmlAttributeComponent<{
|
||||||
readonly relativeFrom: HorizontalPositionRelativeFrom;
|
readonly relativeFrom: (typeof HorizontalPositionRelativeFrom)[keyof typeof HorizontalPositionRelativeFrom];
|
||||||
}> {
|
}> {
|
||||||
protected readonly xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
relativeFrom: "relativeFrom",
|
relativeFrom: "relativeFrom",
|
||||||
|
@ -5,7 +5,7 @@ import { IVerticalPositionOptions, VerticalPositionRelativeFrom } from "./floati
|
|||||||
import { PositionOffset } from "./position-offset";
|
import { PositionOffset } from "./position-offset";
|
||||||
|
|
||||||
class VerticalPositionAttributes extends XmlAttributeComponent<{
|
class VerticalPositionAttributes extends XmlAttributeComponent<{
|
||||||
readonly relativeFrom: VerticalPositionRelativeFrom;
|
readonly relativeFrom: (typeof VerticalPositionRelativeFrom)[keyof typeof VerticalPositionRelativeFrom];
|
||||||
}> {
|
}> {
|
||||||
protected readonly xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
relativeFrom: "relativeFrom",
|
relativeFrom: "relativeFrom",
|
||||||
|
@ -3,11 +3,20 @@ import { XmlComponent } from "@file/xml-components";
|
|||||||
|
|
||||||
import { GraphicDataAttributes } from "./graphic-data-attribute";
|
import { GraphicDataAttributes } from "./graphic-data-attribute";
|
||||||
import { Pic } from "./pic";
|
import { Pic } from "./pic";
|
||||||
|
import { OutlineOptions } from "./pic/shape-properties/outline/outline";
|
||||||
|
|
||||||
export class GraphicData extends XmlComponent {
|
export class GraphicData extends XmlComponent {
|
||||||
private readonly pic: Pic;
|
private readonly pic: Pic;
|
||||||
|
|
||||||
public constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
public constructor({
|
||||||
|
mediaData,
|
||||||
|
transform,
|
||||||
|
outline,
|
||||||
|
}: {
|
||||||
|
readonly mediaData: IMediaData;
|
||||||
|
readonly transform: IMediaDataTransformation;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
|
}) {
|
||||||
super("a:graphicData");
|
super("a:graphicData");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
@ -16,7 +25,7 @@ export class GraphicData extends XmlComponent {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.pic = new Pic(mediaData, transform);
|
this.pic = new Pic({ mediaData, transform, outline });
|
||||||
|
|
||||||
this.root.push(this.pic);
|
this.root.push(this.pic);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
import { IMediaData } from "@file/media";
|
||||||
|
|
||||||
|
const createSvgBlip = (mediaData: IMediaData): XmlComponent =>
|
||||||
|
new BuilderElement({
|
||||||
|
name: "asvg:svgBlip",
|
||||||
|
attributes: {
|
||||||
|
asvg: {
|
||||||
|
key: "xmlns:asvg",
|
||||||
|
value: "http://schemas.microsoft.com/office/drawing/2016/SVG/main",
|
||||||
|
},
|
||||||
|
embed: {
|
||||||
|
key: "r:embed",
|
||||||
|
value: `rId{${mediaData.fileName}}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const createExtention = (mediaData: IMediaData): XmlComponent =>
|
||||||
|
new BuilderElement({
|
||||||
|
name: "a:ext",
|
||||||
|
attributes: {
|
||||||
|
uri: {
|
||||||
|
key: "uri",
|
||||||
|
value: "{96DAC541-7B7A-43D3-8B79-37D633B846F1}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [createSvgBlip(mediaData)],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createExtentionList = (mediaData: IMediaData): XmlComponent =>
|
||||||
|
new BuilderElement({
|
||||||
|
name: "a:extLst",
|
||||||
|
children: [createExtention(mediaData)],
|
||||||
|
});
|
@ -1,7 +1,7 @@
|
|||||||
import { IMediaData } from "@file/media";
|
import { IMediaData } from "@file/media";
|
||||||
import { XmlComponent } from "@file/xml-components";
|
import { XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
import { Blip } from "./blip";
|
import { createBlip } from "./blip";
|
||||||
import { SourceRectangle } from "./source-rectangle";
|
import { SourceRectangle } from "./source-rectangle";
|
||||||
import { Stretch } from "./stretch";
|
import { Stretch } from "./stretch";
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ export class BlipFill extends XmlComponent {
|
|||||||
public constructor(mediaData: IMediaData) {
|
public constructor(mediaData: IMediaData) {
|
||||||
super("pic:blipFill");
|
super("pic:blipFill");
|
||||||
|
|
||||||
this.root.push(new Blip(mediaData));
|
this.root.push(createBlip(mediaData));
|
||||||
this.root.push(new SourceRectangle());
|
this.root.push(new SourceRectangle());
|
||||||
this.root.push(new Stretch());
|
this.root.push(new Stretch());
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
import { IMediaData } from "@file/media";
|
import { IMediaData } from "@file/media";
|
||||||
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
import { createExtentionList } from "./blip-extentions";
|
||||||
|
|
||||||
class BlipAttributes extends XmlAttributeComponent<{
|
type BlipAttributes = {
|
||||||
readonly embed: string;
|
readonly embed: string;
|
||||||
readonly cstate: string;
|
readonly cstate: string;
|
||||||
}> {
|
};
|
||||||
protected readonly xmlKeys = {
|
|
||||||
embed: "r:embed",
|
|
||||||
cstate: "cstate",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Blip extends XmlComponent {
|
export const createBlip = (mediaData: IMediaData): XmlComponent =>
|
||||||
public constructor(mediaData: IMediaData) {
|
new BuilderElement<BlipAttributes>({
|
||||||
super("a:blip");
|
name: "a:blip",
|
||||||
this.root.push(
|
attributes: {
|
||||||
new BlipAttributes({
|
embed: {
|
||||||
embed: `rId{${mediaData.fileName}}`,
|
key: "r:embed",
|
||||||
cstate: "none",
|
value: `rId{${mediaData.type === "svg" ? mediaData.fallback.fileName : mediaData.fileName}}`,
|
||||||
}),
|
},
|
||||||
);
|
cstate: {
|
||||||
}
|
key: "cstate",
|
||||||
}
|
value: "none",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: mediaData.type === "svg" ? [createExtentionList(mediaData)] : [],
|
||||||
|
});
|
||||||
|
@ -6,9 +6,18 @@ import { BlipFill } from "./blip/blip-fill";
|
|||||||
import { NonVisualPicProperties } from "./non-visual-pic-properties/non-visual-pic-properties";
|
import { NonVisualPicProperties } from "./non-visual-pic-properties/non-visual-pic-properties";
|
||||||
import { PicAttributes } from "./pic-attributes";
|
import { PicAttributes } from "./pic-attributes";
|
||||||
import { ShapeProperties } from "./shape-properties/shape-properties";
|
import { ShapeProperties } from "./shape-properties/shape-properties";
|
||||||
|
import { OutlineOptions } from "./shape-properties/outline/outline";
|
||||||
|
|
||||||
export class Pic extends XmlComponent {
|
export class Pic extends XmlComponent {
|
||||||
public constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
public constructor({
|
||||||
|
mediaData,
|
||||||
|
transform,
|
||||||
|
outline,
|
||||||
|
}: {
|
||||||
|
readonly mediaData: IMediaData;
|
||||||
|
readonly transform: IMediaDataTransformation;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
|
}) {
|
||||||
super("pic:pic");
|
super("pic:pic");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
@ -19,6 +28,6 @@ export class Pic extends XmlComponent {
|
|||||||
|
|
||||||
this.root.push(new NonVisualPicProperties());
|
this.root.push(new NonVisualPicProperties());
|
||||||
this.root.push(new BlipFill(mediaData));
|
this.root.push(new BlipFill(mediaData));
|
||||||
this.root.push(new ShapeProperties(transform));
|
this.root.push(new ShapeProperties({ transform, outline }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,12 @@ import { describe, expect, it } from "vitest";
|
|||||||
|
|
||||||
import { Formatter } from "@export/formatter";
|
import { Formatter } from "@export/formatter";
|
||||||
|
|
||||||
import { NoFill } from "./no-fill";
|
import { createNoFill } from "./no-fill";
|
||||||
|
|
||||||
describe("NoFill", () => {
|
describe("NoFill", () => {
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
it("should create", () => {
|
it("should create", () => {
|
||||||
const tree = new Formatter().format(new NoFill());
|
const tree = new Formatter().format(createNoFill());
|
||||||
expect(tree).to.deep.equal({
|
expect(tree).to.deep.equal({
|
||||||
"a:noFill": {},
|
"a:noFill": {},
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
import { XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
export class NoFill extends XmlComponent {
|
export const createNoFill = (): XmlComponent => new BuilderElement({ name: "a:noFill" });
|
||||||
public constructor() {
|
|
||||||
super("a:noFill");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,19 +1,66 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
import { Formatter } from "@export/formatter";
|
import { Formatter } from "@export/formatter";
|
||||||
import { Outline } from "./outline";
|
|
||||||
|
|
||||||
describe("Outline", () => {
|
import { createOutline } from "./outline";
|
||||||
describe("#constructor()", () => {
|
import { SchemeColor } from "./scheme-color";
|
||||||
it("should create", () => {
|
|
||||||
const tree = new Formatter().format(new Outline());
|
describe("createOutline", () => {
|
||||||
|
it("should create no fill", () => {
|
||||||
|
const tree = new Formatter().format(createOutline({ type: "noFill" }));
|
||||||
expect(tree).to.deep.equal({
|
expect(tree).to.deep.equal({
|
||||||
"a:ln": [
|
"a:ln": [
|
||||||
|
{
|
||||||
|
_attr: {},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"a:noFill": {},
|
"a:noFill": {},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should create solid rgb fill", () => {
|
||||||
|
const tree = new Formatter().format(createOutline({ type: "solidFill", solidFillType: "rgb", value: "FFFFFF" }));
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"a:ln": [
|
||||||
|
{
|
||||||
|
_attr: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:solidFill": [
|
||||||
|
{
|
||||||
|
"a:srgbClr": {
|
||||||
|
_attr: {
|
||||||
|
val: "FFFFFF",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create solid scheme fill", () => {
|
||||||
|
const tree = new Formatter().format(createOutline({ type: "solidFill", solidFillType: "scheme", value: SchemeColor.ACCENT1 }));
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"a:ln": [
|
||||||
|
{
|
||||||
|
_attr: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:solidFill": [
|
||||||
|
{
|
||||||
|
"a:schemeClr": {
|
||||||
|
_attr: {
|
||||||
|
val: "accent1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,130 @@
|
|||||||
// http://officeopenxml.com/drwSp-outline.php
|
// http://officeopenxml.com/drwSp-outline.php
|
||||||
import { XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
import { NoFill } from "./no-fill";
|
import { createNoFill } from "./no-fill";
|
||||||
|
import { createSolidFill } from "./solid-fill";
|
||||||
|
import { SchemeColor } from "./scheme-color";
|
||||||
|
|
||||||
export class Outline extends XmlComponent {
|
// <xsd:complexType name="CT_TextOutlineEffect">
|
||||||
public constructor() {
|
// <xsd:sequence>
|
||||||
super("a:ln");
|
// <xsd:group ref="EG_FillProperties" minOccurs="0"/>
|
||||||
|
// <xsd:group ref="EG_LineDashProperties" minOccurs="0"/>
|
||||||
|
// <xsd:group ref="EG_LineJoinProperties" minOccurs="0"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// <xsd:attribute name="w" use="optional" type="a:ST_LineWidth"/>
|
||||||
|
// <xsd:attribute name="cap" use="optional" type="ST_LineCap"/>
|
||||||
|
// <xsd:attribute name="cmpd" use="optional" type="ST_CompoundLine"/>
|
||||||
|
// <xsd:attribute name="algn" use="optional" type="ST_PenAlignment"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
|
||||||
this.root.push(new NoFill());
|
// <xsd:simpleType name="ST_LineCap">
|
||||||
}
|
// <xsd:restriction base="xsd:string">
|
||||||
}
|
// <xsd:enumeration value="rnd"/>
|
||||||
|
// <xsd:enumeration value="sq"/>
|
||||||
|
// <xsd:enumeration value="flat"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export const LineCap = {
|
||||||
|
ROUND: "rnd",
|
||||||
|
SQUARE: "sq",
|
||||||
|
FLAT: "flat",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_CompoundLine">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="sng"/>
|
||||||
|
// <xsd:enumeration value="dbl"/>
|
||||||
|
// <xsd:enumeration value="thickThin"/>
|
||||||
|
// <xsd:enumeration value="thinThick"/>
|
||||||
|
// <xsd:enumeration value="tri"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export const CompoundLine = {
|
||||||
|
SINGLE: "sng",
|
||||||
|
DOUBLE: "dbl",
|
||||||
|
THICK_THIN: "thickThin",
|
||||||
|
THIN_THICK: "thinThick",
|
||||||
|
TRI: "tri",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_PenAlignment">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="ctr"/>
|
||||||
|
// <xsd:enumeration value="in"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export const PenAlignment = {
|
||||||
|
CENTER: "ctr",
|
||||||
|
INSET: "in",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type OutlineAttributes = {
|
||||||
|
readonly width?: number;
|
||||||
|
readonly cap?: keyof typeof LineCap;
|
||||||
|
readonly compoundLine?: keyof typeof CompoundLine;
|
||||||
|
readonly align?: keyof typeof PenAlignment;
|
||||||
|
};
|
||||||
|
|
||||||
|
type OutlineNoFill = {
|
||||||
|
readonly type: "noFill";
|
||||||
|
};
|
||||||
|
|
||||||
|
type OutlineRgbSolidFill = {
|
||||||
|
readonly type: "solidFill";
|
||||||
|
readonly solidFillType: "rgb";
|
||||||
|
readonly value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type OutlineSchemeSolidFill = {
|
||||||
|
readonly type: "solidFill";
|
||||||
|
readonly solidFillType: "scheme";
|
||||||
|
readonly value: (typeof SchemeColor)[keyof typeof SchemeColor];
|
||||||
|
};
|
||||||
|
|
||||||
|
type OutlineSolidFill = OutlineRgbSolidFill | OutlineSchemeSolidFill;
|
||||||
|
|
||||||
|
// <xsd:group name="EG_FillProperties">
|
||||||
|
// <xsd:choice>
|
||||||
|
// <xsd:element name="noFill" type="w:CT_Empty"/>
|
||||||
|
// <xsd:element name="solidFill" type="CT_SolidColorFillProperties"/>
|
||||||
|
// <xsd:element name="gradFill" type="CT_GradientFillProperties"/>
|
||||||
|
// </xsd:choice>
|
||||||
|
// </xsd:group>
|
||||||
|
type OutlineFillProperties = OutlineNoFill | OutlineSolidFill;
|
||||||
|
|
||||||
|
export type OutlineOptions = OutlineAttributes & OutlineFillProperties;
|
||||||
|
|
||||||
|
export const createOutline = (options: OutlineOptions): XmlComponent =>
|
||||||
|
new BuilderElement<OutlineAttributes>({
|
||||||
|
name: "a:ln",
|
||||||
|
attributes: {
|
||||||
|
width: {
|
||||||
|
key: "w",
|
||||||
|
value: options.width,
|
||||||
|
},
|
||||||
|
cap: {
|
||||||
|
key: "cap",
|
||||||
|
value: options.cap,
|
||||||
|
},
|
||||||
|
compoundLine: {
|
||||||
|
key: "cmpd",
|
||||||
|
value: options.compoundLine,
|
||||||
|
},
|
||||||
|
align: {
|
||||||
|
key: "algn",
|
||||||
|
value: options.align,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
options.type === "noFill"
|
||||||
|
? createNoFill()
|
||||||
|
: options.solidFillType === "rgb"
|
||||||
|
? createSolidFill({
|
||||||
|
type: "rgb",
|
||||||
|
value: options.value,
|
||||||
|
})
|
||||||
|
: createSolidFill({
|
||||||
|
type: "scheme",
|
||||||
|
value: options.value,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
type SolidRgbColorOptions = {
|
||||||
|
readonly value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_SRgbColor">
|
||||||
|
// <xsd:sequence>
|
||||||
|
// <xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// <xsd:attribute name="val" type="s:ST_HexColorRGB" use="required"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
export const createSolidRgbColor = (options: SolidRgbColorOptions): XmlComponent =>
|
||||||
|
new BuilderElement<SolidRgbColorOptions>({
|
||||||
|
name: "a:srgbClr",
|
||||||
|
attributes: {
|
||||||
|
value: {
|
||||||
|
key: "val",
|
||||||
|
value: options.value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
@ -0,0 +1,65 @@
|
|||||||
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
type SchemeColorOptions = {
|
||||||
|
readonly value: (typeof SchemeColor)[keyof typeof SchemeColor];
|
||||||
|
};
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_SchemeColorVal">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="bg1"/>
|
||||||
|
// <xsd:enumeration value="tx1"/>
|
||||||
|
// <xsd:enumeration value="bg2"/>
|
||||||
|
// <xsd:enumeration value="tx2"/>
|
||||||
|
// <xsd:enumeration value="accent1"/>
|
||||||
|
// <xsd:enumeration value="accent2"/>
|
||||||
|
// <xsd:enumeration value="accent3"/>
|
||||||
|
// <xsd:enumeration value="accent4"/>
|
||||||
|
// <xsd:enumeration value="accent5"/>
|
||||||
|
// <xsd:enumeration value="accent6"/>
|
||||||
|
// <xsd:enumeration value="hlink"/>
|
||||||
|
// <xsd:enumeration value="folHlink"/>
|
||||||
|
// <xsd:enumeration value="dk1"/>
|
||||||
|
// <xsd:enumeration value="lt1"/>
|
||||||
|
// <xsd:enumeration value="dk2"/>
|
||||||
|
// <xsd:enumeration value="lt2"/>
|
||||||
|
// <xsd:enumeration value="phClr"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
|
||||||
|
// cspell:ignore folHlink, phClr, hlink
|
||||||
|
export const SchemeColor = {
|
||||||
|
BG1: "bg1",
|
||||||
|
TX1: "tx1",
|
||||||
|
BG2: "bg2",
|
||||||
|
TX2: "tx2",
|
||||||
|
ACCENT1: "accent1",
|
||||||
|
ACCENT2: "accent2",
|
||||||
|
ACCENT3: "accent3",
|
||||||
|
ACCENT4: "accent4",
|
||||||
|
ACCENT5: "accent5",
|
||||||
|
ACCENT6: "accent6",
|
||||||
|
HLINK: "hlink",
|
||||||
|
FOLHLINK: "folHlink",
|
||||||
|
DK1: "dk1",
|
||||||
|
LT1: "lt1",
|
||||||
|
DK2: "dk2",
|
||||||
|
LT2: "lt2",
|
||||||
|
PHCLR: "phClr",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_SchemeColor">
|
||||||
|
// <xsd:sequence>
|
||||||
|
// <xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// <xsd:attribute name="val" type="ST_SchemeColorVal" use="required"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
export const createSchemeColor = (options: SchemeColorOptions): XmlComponent =>
|
||||||
|
new BuilderElement<SchemeColorOptions>({
|
||||||
|
name: "a:schemeClr",
|
||||||
|
attributes: {
|
||||||
|
value: {
|
||||||
|
key: "val",
|
||||||
|
value: options.value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
@ -0,0 +1,38 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { Formatter } from "@export/formatter";
|
||||||
|
|
||||||
|
import { createSolidFill } from "./solid-fill";
|
||||||
|
import { SchemeColor } from "./scheme-color";
|
||||||
|
|
||||||
|
describe("createSolidFill", () => {
|
||||||
|
it("should create of rgb", () => {
|
||||||
|
const tree = new Formatter().format(createSolidFill({ type: "rgb", value: "FFFFFF" }));
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"a:solidFill": [
|
||||||
|
{
|
||||||
|
"a:srgbClr": {
|
||||||
|
_attr: {
|
||||||
|
val: "FFFFFF",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create of scheme", () => {
|
||||||
|
const tree = new Formatter().format(createSolidFill({ type: "scheme", value: SchemeColor.TX1 }));
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"a:solidFill": [
|
||||||
|
{
|
||||||
|
"a:schemeClr": {
|
||||||
|
_attr: {
|
||||||
|
val: "tx1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,22 @@
|
|||||||
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
import { createSchemeColor, SchemeColor } from "./scheme-color";
|
||||||
|
import { createSolidRgbColor } from "./rgb-color";
|
||||||
|
|
||||||
|
export type RgbColorOptions = {
|
||||||
|
readonly type: "rgb";
|
||||||
|
readonly value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SchemeColorOptions = {
|
||||||
|
readonly type: "scheme";
|
||||||
|
readonly value: (typeof SchemeColor)[keyof typeof SchemeColor];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SolidFillOptions = RgbColorOptions | SchemeColorOptions;
|
||||||
|
|
||||||
|
export const createSolidFill = (options: SolidFillOptions): XmlComponent =>
|
||||||
|
new BuilderElement({
|
||||||
|
name: "a:solidFill",
|
||||||
|
children: [options.type === "rgb" ? createSolidRgbColor(options) : createSchemeColor(options)],
|
||||||
|
});
|
@ -2,15 +2,15 @@
|
|||||||
import { IMediaDataTransformation } from "@file/media";
|
import { IMediaDataTransformation } from "@file/media";
|
||||||
import { XmlComponent } from "@file/xml-components";
|
import { XmlComponent } from "@file/xml-components";
|
||||||
import { Form } from "./form";
|
import { Form } from "./form";
|
||||||
// import { NoFill } from "./no-fill";
|
import { OutlineOptions, createOutline } from "./outline/outline";
|
||||||
// import { Outline } from "./outline/outline";
|
|
||||||
import { PresetGeometry } from "./preset-geometry/preset-geometry";
|
import { PresetGeometry } from "./preset-geometry/preset-geometry";
|
||||||
import { ShapePropertiesAttributes } from "./shape-properties-attributes";
|
import { ShapePropertiesAttributes } from "./shape-properties-attributes";
|
||||||
|
import { createNoFill } from "./outline/no-fill";
|
||||||
|
|
||||||
export class ShapeProperties extends XmlComponent {
|
export class ShapeProperties extends XmlComponent {
|
||||||
private readonly form: Form;
|
private readonly form: Form;
|
||||||
|
|
||||||
public constructor(transform: IMediaDataTransformation) {
|
public constructor({ outline, transform }: { readonly outline?: OutlineOptions; readonly transform: IMediaDataTransformation }) {
|
||||||
super("pic:spPr");
|
super("pic:spPr");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
@ -23,7 +23,10 @@ export class ShapeProperties extends XmlComponent {
|
|||||||
|
|
||||||
this.root.push(this.form);
|
this.root.push(this.form);
|
||||||
this.root.push(new PresetGeometry());
|
this.root.push(new PresetGeometry());
|
||||||
// this.root.push(new NoFill());
|
|
||||||
// this.root.push(new Outline());
|
if (outline) {
|
||||||
|
this.root.push(createNoFill());
|
||||||
|
this.root.push(createOutline(outline));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import { IMediaData, IMediaDataTransformation } from "@file/media";
|
|||||||
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
import { GraphicData } from "./graphic-data";
|
import { GraphicData } from "./graphic-data";
|
||||||
|
import { OutlineOptions } from "./graphic-data/pic/shape-properties/outline/outline";
|
||||||
|
|
||||||
class GraphicAttributes extends XmlAttributeComponent<{
|
class GraphicAttributes extends XmlAttributeComponent<{
|
||||||
readonly a: string;
|
readonly a: string;
|
||||||
@ -14,7 +15,15 @@ class GraphicAttributes extends XmlAttributeComponent<{
|
|||||||
export class Graphic extends XmlComponent {
|
export class Graphic extends XmlComponent {
|
||||||
private readonly data: GraphicData;
|
private readonly data: GraphicData;
|
||||||
|
|
||||||
public constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
public constructor({
|
||||||
|
mediaData,
|
||||||
|
transform,
|
||||||
|
outline,
|
||||||
|
}: {
|
||||||
|
readonly mediaData: IMediaData;
|
||||||
|
readonly transform: IMediaDataTransformation;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
|
}) {
|
||||||
super("a:graphic");
|
super("a:graphic");
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new GraphicAttributes({
|
new GraphicAttributes({
|
||||||
@ -22,7 +31,7 @@ export class Graphic extends XmlComponent {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.data = new GraphicData(mediaData, transform);
|
this.data = new GraphicData({ mediaData, transform, outline });
|
||||||
|
|
||||||
this.root.push(this.data);
|
this.root.push(this.data);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import { XmlAttributeComponent } from "@file/xml-components";
|
|
||||||
import { IDistance } from "../drawing";
|
|
||||||
|
|
||||||
// distT, distB etc have no effect on inline images, only floating
|
|
||||||
export class InlineAttributes extends XmlAttributeComponent<IDistance> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
distT: "distT",
|
|
||||||
distB: "distB",
|
|
||||||
distL: "distL",
|
|
||||||
distR: "distR",
|
|
||||||
};
|
|
||||||
}
|
|
59
src/file/drawing/inline/inline.spec.ts
Normal file
59
src/file/drawing/inline/inline.spec.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { Formatter } from "@export/formatter";
|
||||||
|
import { createInline } from "./inline";
|
||||||
|
|
||||||
|
describe("Inline", () => {
|
||||||
|
it("should create with default effect extent", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createInline({
|
||||||
|
mediaData: {
|
||||||
|
type: "png",
|
||||||
|
fileName: "test.png",
|
||||||
|
data: Buffer.from(""),
|
||||||
|
transformation: {
|
||||||
|
pixels: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
emus: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
transform: {
|
||||||
|
pixels: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
emus: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
docProperties: {
|
||||||
|
name: "test",
|
||||||
|
description: "test",
|
||||||
|
title: "test",
|
||||||
|
},
|
||||||
|
outline: { type: "solidFill", solidFillType: "rgb", value: "FFFFFF" },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"wp:inline": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"wp:effectExtent": {
|
||||||
|
_attr: {
|
||||||
|
b: 19050,
|
||||||
|
l: 19050,
|
||||||
|
r: 19050,
|
||||||
|
t: 19050,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,18 +1,19 @@
|
|||||||
// http://officeopenxml.com/drwPicInline.php
|
// http://officeopenxml.com/drwPicInline.php
|
||||||
import { IMediaData, IMediaDataTransformation } from "@file/media";
|
import { IMediaData, IMediaDataTransformation } from "@file/media";
|
||||||
import { XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
import { DocProperties, DocPropertiesOptions } from "./../doc-properties/doc-properties";
|
import { DocProperties, DocPropertiesOptions } from "./../doc-properties/doc-properties";
|
||||||
import { EffectExtent } from "./../effect-extent/effect-extent";
|
import { createEffectExtent } from "./../effect-extent/effect-extent";
|
||||||
import { Extent } from "./../extent/extent";
|
import { Extent } from "./../extent/extent";
|
||||||
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
||||||
import { Graphic } from "./../inline/graphic";
|
import { Graphic } from "./../inline/graphic";
|
||||||
import { InlineAttributes } from "./inline-attributes";
|
import { OutlineOptions } from "./graphic/graphic-data/pic/shape-properties/outline/outline";
|
||||||
|
|
||||||
interface InlineOptions {
|
type InlineOptions = {
|
||||||
readonly mediaData: IMediaData;
|
readonly mediaData: IMediaData;
|
||||||
readonly transform: IMediaDataTransformation;
|
readonly transform: IMediaDataTransformation;
|
||||||
readonly docProperties?: DocPropertiesOptions;
|
readonly docProperties?: DocPropertiesOptions;
|
||||||
}
|
readonly outline?: OutlineOptions;
|
||||||
|
};
|
||||||
|
|
||||||
// <xsd:complexType name="CT_Inline">
|
// <xsd:complexType name="CT_Inline">
|
||||||
// <xsd:sequence>
|
// <xsd:sequence>
|
||||||
@ -28,29 +29,41 @@ interface InlineOptions {
|
|||||||
// <xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
|
// <xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
|
||||||
// <xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
|
// <xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
|
||||||
// </xsd:complexType>
|
// </xsd:complexType>
|
||||||
export class Inline extends XmlComponent {
|
export const createInline = ({ mediaData, transform, docProperties, outline }: InlineOptions): XmlComponent =>
|
||||||
private readonly extent: Extent;
|
new BuilderElement({
|
||||||
private readonly graphic: Graphic;
|
name: "wp:inline",
|
||||||
|
attributes: {
|
||||||
public constructor({ mediaData, transform, docProperties }: InlineOptions) {
|
distanceTop: {
|
||||||
super("wp:inline");
|
key: "distT",
|
||||||
|
value: 0,
|
||||||
this.root.push(
|
},
|
||||||
new InlineAttributes({
|
distanceBottom: {
|
||||||
distT: 0,
|
key: "distB",
|
||||||
distB: 0,
|
value: 0,
|
||||||
distL: 0,
|
},
|
||||||
distR: 0,
|
distanceLeft: {
|
||||||
}),
|
key: "distL",
|
||||||
);
|
value: 0,
|
||||||
|
},
|
||||||
this.extent = new Extent(transform.emus.x, transform.emus.y);
|
distanceRight: {
|
||||||
this.graphic = new Graphic(mediaData, transform);
|
key: "distR",
|
||||||
|
value: 0,
|
||||||
this.root.push(this.extent);
|
},
|
||||||
this.root.push(new EffectExtent());
|
},
|
||||||
this.root.push(new DocProperties(docProperties));
|
children: [
|
||||||
this.root.push(new GraphicFrameProperties());
|
new Extent(transform.emus.x, transform.emus.y),
|
||||||
this.root.push(this.graphic);
|
createEffectExtent(
|
||||||
|
outline
|
||||||
|
? {
|
||||||
|
top: (outline.width ?? 9525) * 2,
|
||||||
|
right: (outline.width ?? 9525) * 2,
|
||||||
|
bottom: (outline.width ?? 9525) * 2,
|
||||||
|
left: (outline.width ?? 9525) * 2,
|
||||||
}
|
}
|
||||||
}
|
: { top: 0, right: 0, bottom: 0, left: 0 },
|
||||||
|
),
|
||||||
|
new DocProperties(docProperties),
|
||||||
|
new GraphicFrameProperties(),
|
||||||
|
new Graphic({ mediaData, transform, outline }),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
@ -1,22 +1,25 @@
|
|||||||
// http://officeopenxml.com/drwPicFloating-textWrap.php
|
// http://officeopenxml.com/drwPicFloating-textWrap.php
|
||||||
import { IDistance } from "../drawing";
|
import { IDistance } from "../drawing";
|
||||||
|
|
||||||
export enum TextWrappingType {
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
NONE,
|
export const TextWrappingType = {
|
||||||
SQUARE,
|
NONE: 0,
|
||||||
TIGHT,
|
SQUARE: 1,
|
||||||
TOP_AND_BOTTOM,
|
TIGHT: 2,
|
||||||
}
|
TOP_AND_BOTTOM: 3,
|
||||||
|
} as const;
|
||||||
|
|
||||||
export enum TextWrappingSide {
|
export const TextWrappingSide = {
|
||||||
BOTH_SIDES = "bothSides",
|
BOTH_SIDES: "bothSides",
|
||||||
LEFT = "left",
|
LEFT: "left",
|
||||||
RIGHT = "right",
|
RIGHT: "right",
|
||||||
LARGEST = "largest",
|
LARGEST: "largest",
|
||||||
}
|
} as const;
|
||||||
|
|
||||||
|
/* eslint-enable */
|
||||||
|
|
||||||
export interface ITextWrapping {
|
export interface ITextWrapping {
|
||||||
readonly type: TextWrappingType;
|
readonly type: (typeof TextWrappingType)[keyof typeof TextWrappingType];
|
||||||
readonly side?: TextWrappingSide;
|
readonly side?: (typeof TextWrappingSide)[keyof typeof TextWrappingSide];
|
||||||
readonly margins?: IDistance;
|
readonly margins?: IDistance;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import { IMargins } from "../floating";
|
|||||||
import { ITextWrapping, TextWrappingSide } from "./text-wrapping";
|
import { ITextWrapping, TextWrappingSide } from "./text-wrapping";
|
||||||
|
|
||||||
interface IWrapSquareAttributes extends IDistance {
|
interface IWrapSquareAttributes extends IDistance {
|
||||||
readonly wrapText?: TextWrappingSide;
|
readonly wrapText?: (typeof TextWrappingSide)[keyof typeof TextWrappingSide];
|
||||||
}
|
}
|
||||||
|
|
||||||
class WrapSquareAttributes extends XmlAttributeComponent<IWrapSquareAttributes> {
|
class WrapSquareAttributes extends XmlAttributeComponent<IWrapSquareAttributes> {
|
||||||
|
@ -436,7 +436,44 @@ describe("File", () => {
|
|||||||
it("should work with external styles", () => {
|
it("should work with external styles", () => {
|
||||||
const doc = new File({
|
const doc = new File({
|
||||||
sections: [],
|
sections: [],
|
||||||
externalStyles: "",
|
externalStyles: `
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<w:styles xmlns:mc="first" xmlns:r="second">
|
||||||
|
<w:docDefaults>
|
||||||
|
<w:rPrDefault>
|
||||||
|
<w:rPr>
|
||||||
|
<w:rFonts w:ascii="Arial" w:eastAsiaTheme="minorHAnsi" w:hAnsi="Arial" w:cstheme="minorHAnsi"/>
|
||||||
|
<w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA"/>
|
||||||
|
</w:rPr>
|
||||||
|
</w:rPrDefault>
|
||||||
|
<w:pPrDefault>
|
||||||
|
<w:pPr>
|
||||||
|
<w:spacing w:after="160" w:line="259" w:lineRule="auto"/>
|
||||||
|
</w:pPr>
|
||||||
|
</w:pPrDefault>
|
||||||
|
</w:docDefaults>
|
||||||
|
|
||||||
|
<w:latentStyles w:defLockedState="1" w:defUIPriority="99">
|
||||||
|
</w:latentStyles>
|
||||||
|
|
||||||
|
<w:style w:type="paragraph" w:default="1" w:styleId="Normal">
|
||||||
|
<w:name w:val="Normal"/>
|
||||||
|
<w:qFormat/>
|
||||||
|
</w:style>
|
||||||
|
|
||||||
|
<w:style w:type="paragraph" w:styleId="Heading1">
|
||||||
|
<w:name w:val="heading 1"/>
|
||||||
|
<w:basedOn w:val="Normal"/>
|
||||||
|
<w:pPr>
|
||||||
|
<w:keepNext/>
|
||||||
|
<w:keepLines/>
|
||||||
|
|
||||||
|
<w:pBdr>
|
||||||
|
<w:bottom w:val="single" w:sz="4" w:space="1" w:color="auto"/>
|
||||||
|
</w:pBdr>
|
||||||
|
</w:pPr>
|
||||||
|
</w:style>
|
||||||
|
</w:styles>`,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(doc.Styles).to.not.be.undefined;
|
expect(doc.Styles).to.not.be.undefined;
|
||||||
|
@ -17,6 +17,7 @@ import { Styles } from "./styles";
|
|||||||
import { ExternalStylesFactory } from "./styles/external-styles-factory";
|
import { ExternalStylesFactory } from "./styles/external-styles-factory";
|
||||||
import { DefaultStylesFactory } from "./styles/factory";
|
import { DefaultStylesFactory } from "./styles/factory";
|
||||||
import { FileChild } from "./file-child";
|
import { FileChild } from "./file-child";
|
||||||
|
import { FontWrapper } from "./fonts/font-wrapper";
|
||||||
|
|
||||||
export interface ISectionOptions {
|
export interface ISectionOptions {
|
||||||
readonly headers?: {
|
readonly headers?: {
|
||||||
@ -53,6 +54,7 @@ export class File {
|
|||||||
private readonly appProperties: AppProperties;
|
private readonly appProperties: AppProperties;
|
||||||
private readonly styles: Styles;
|
private readonly styles: Styles;
|
||||||
private readonly comments: Comments;
|
private readonly comments: Comments;
|
||||||
|
private readonly fontWrapper: FontWrapper;
|
||||||
|
|
||||||
public constructor(options: IPropertiesOptions) {
|
public constructor(options: IPropertiesOptions) {
|
||||||
this.coreProperties = new CoreProperties({
|
this.coreProperties = new CoreProperties({
|
||||||
@ -77,11 +79,12 @@ export class File {
|
|||||||
evenAndOddHeaders: options.evenAndOddHeaderAndFooters ? true : false,
|
evenAndOddHeaders: options.evenAndOddHeaderAndFooters ? true : false,
|
||||||
trackRevisions: options.features?.trackRevisions,
|
trackRevisions: options.features?.trackRevisions,
|
||||||
updateFields: options.features?.updateFields,
|
updateFields: options.features?.updateFields,
|
||||||
|
defaultTabStop: options.defaultTabStop,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.media = new Media();
|
this.media = new Media();
|
||||||
|
|
||||||
if (options.externalStyles) {
|
if (options.externalStyles !== undefined) {
|
||||||
const stylesFactory = new ExternalStylesFactory();
|
const stylesFactory = new ExternalStylesFactory();
|
||||||
this.styles = stylesFactory.newInstance(options.externalStyles);
|
this.styles = stylesFactory.newInstance(options.externalStyles);
|
||||||
} else if (options.styles) {
|
} else if (options.styles) {
|
||||||
@ -108,6 +111,8 @@ export class File {
|
|||||||
this.footnotesWrapper.View.createFootNote(parseFloat(key), options.footnotes[key].children);
|
this.footnotesWrapper.View.createFootNote(parseFloat(key), options.footnotes[key].children);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.fontWrapper = new FontWrapper(options.fonts ?? []);
|
||||||
}
|
}
|
||||||
|
|
||||||
private addSection({ headers = {}, footers = {}, children, properties }: ISectionOptions): void {
|
private addSection({ headers = {}, footers = {}, children, properties }: ISectionOptions): void {
|
||||||
@ -154,7 +159,10 @@ export class File {
|
|||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private addHeaderToDocument(header: HeaderWrapper, type: HeaderFooterReferenceType = HeaderFooterReferenceType.DEFAULT): void {
|
private addHeaderToDocument(
|
||||||
|
header: HeaderWrapper,
|
||||||
|
type: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType] = HeaderFooterReferenceType.DEFAULT,
|
||||||
|
): void {
|
||||||
// eslint-disable-next-line functional/immutable-data
|
// eslint-disable-next-line functional/immutable-data
|
||||||
this.headers.push({ header, type });
|
this.headers.push({ header, type });
|
||||||
this.documentWrapper.Relationships.createRelationship(
|
this.documentWrapper.Relationships.createRelationship(
|
||||||
@ -165,7 +173,10 @@ export class File {
|
|||||||
this.contentTypes.addHeader(this.headers.length);
|
this.contentTypes.addHeader(this.headers.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private addFooterToDocument(footer: FooterWrapper, type: HeaderFooterReferenceType = HeaderFooterReferenceType.DEFAULT): void {
|
private addFooterToDocument(
|
||||||
|
footer: FooterWrapper,
|
||||||
|
type: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType] = HeaderFooterReferenceType.DEFAULT,
|
||||||
|
): void {
|
||||||
// eslint-disable-next-line functional/immutable-data
|
// eslint-disable-next-line functional/immutable-data
|
||||||
this.footers.push({ footer, type });
|
this.footers.push({ footer, type });
|
||||||
this.documentWrapper.Relationships.createRelationship(
|
this.documentWrapper.Relationships.createRelationship(
|
||||||
@ -285,4 +296,8 @@ export class File {
|
|||||||
public get Comments(): Comments {
|
public get Comments(): Comments {
|
||||||
return this.comments;
|
return this.comments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get FontTable(): FontWrapper {
|
||||||
|
return this.fontWrapper;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
33
src/file/fonts/create-regular-font.ts
Normal file
33
src/file/fonts/create-regular-font.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
import { CharacterSet, createFont } from "./font";
|
||||||
|
|
||||||
|
export const createRegularFont = ({
|
||||||
|
name,
|
||||||
|
index,
|
||||||
|
fontKey,
|
||||||
|
characterSet,
|
||||||
|
}: {
|
||||||
|
readonly name: string;
|
||||||
|
readonly index: number;
|
||||||
|
readonly fontKey: string;
|
||||||
|
readonly characterSet?: (typeof CharacterSet)[keyof typeof CharacterSet];
|
||||||
|
}): XmlComponent =>
|
||||||
|
createFont({
|
||||||
|
name,
|
||||||
|
sig: {
|
||||||
|
usb0: "E0002AFF",
|
||||||
|
usb1: "C000247B",
|
||||||
|
usb2: "00000009",
|
||||||
|
usb3: "00000000",
|
||||||
|
csb0: "000001FF",
|
||||||
|
csb1: "00000000",
|
||||||
|
},
|
||||||
|
charset: characterSet,
|
||||||
|
family: "auto",
|
||||||
|
pitch: "variable",
|
||||||
|
embedRegular: {
|
||||||
|
fontKey,
|
||||||
|
id: `rId${index}`,
|
||||||
|
},
|
||||||
|
});
|
44
src/file/fonts/font-table.ts
Normal file
44
src/file/fonts/font-table.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
import { createRegularFont } from "./create-regular-font";
|
||||||
|
import { FontOptionsWithKey } from "./font-wrapper";
|
||||||
|
import { CharacterSet } from "./font";
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_FontsList">
|
||||||
|
// <xsd:sequence>
|
||||||
|
// <xsd:element name="font" type="CT_Font" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// </xsd:complexType>
|
||||||
|
|
||||||
|
export type FontOptions = {
|
||||||
|
readonly name: string;
|
||||||
|
readonly data: Buffer;
|
||||||
|
readonly characterSet?: (typeof CharacterSet)[keyof typeof CharacterSet];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createFontTable = (fonts: readonly FontOptionsWithKey[]): XmlComponent =>
|
||||||
|
// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_Font_topic_ID0ERNCU.html
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_fonts.html
|
||||||
|
new BuilderElement({
|
||||||
|
name: "w:fonts",
|
||||||
|
attributes: {
|
||||||
|
mc: { key: "xmlns:mc", value: "http://schemas.openxmlformats.org/markup-compatibility/2006" },
|
||||||
|
r: { key: "xmlns:r", value: "http://schemas.openxmlformats.org/officeDocument/2006/relationships" },
|
||||||
|
w: { key: "xmlns:w", value: "http://schemas.openxmlformats.org/wordprocessingml/2006/main" },
|
||||||
|
w14: { key: "xmlns:w14", value: "http://schemas.microsoft.com/office/word/2010/wordml" },
|
||||||
|
w15: { key: "xmlns:w15", value: "http://schemas.microsoft.com/office/word/2012/wordml" },
|
||||||
|
w16cex: { key: "xmlns:w16cex", value: "http://schemas.microsoft.com/office/word/2018/wordml/cex" },
|
||||||
|
w16cid: { key: "xmlns:w16cid", value: "http://schemas.microsoft.com/office/word/2016/wordml/cid" },
|
||||||
|
w16: { key: "xmlns:w16", value: "http://schemas.microsoft.com/office/word/2018/wordml" },
|
||||||
|
w16sdtdh: { key: "xmlns:w16sdtdh", value: "http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" },
|
||||||
|
w16se: { key: "xmlns:w16se", value: "http://schemas.microsoft.com/office/word/2015/wordml/symex" },
|
||||||
|
Ignorable: { key: "mc:Ignorable", value: "w14 w15 w16se w16cid w16 w16cex w16sdtdh" },
|
||||||
|
},
|
||||||
|
children: fonts.map((font, i) =>
|
||||||
|
createRegularFont({
|
||||||
|
name: font.name,
|
||||||
|
index: i + 1,
|
||||||
|
fontKey: font.fontKey,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
});
|
36
src/file/fonts/font-wrapper.ts
Normal file
36
src/file/fonts/font-wrapper.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { IViewWrapper } from "@file/document-wrapper";
|
||||||
|
import { Relationships } from "@file/relationships";
|
||||||
|
import { XmlComponent } from "@file/xml-components";
|
||||||
|
import { uniqueUuid } from "@util/convenience-functions";
|
||||||
|
|
||||||
|
import { FontOptions, createFontTable } from "./font-table";
|
||||||
|
|
||||||
|
export type FontOptionsWithKey = FontOptions & { readonly fontKey: string };
|
||||||
|
|
||||||
|
export class FontWrapper implements IViewWrapper {
|
||||||
|
private readonly fontTable: XmlComponent;
|
||||||
|
private readonly relationships: Relationships;
|
||||||
|
public readonly fontOptionsWithKey: readonly FontOptionsWithKey[] = [];
|
||||||
|
|
||||||
|
public constructor(public readonly options: readonly FontOptions[]) {
|
||||||
|
this.fontOptionsWithKey = options.map((o) => ({ ...o, fontKey: uniqueUuid() }));
|
||||||
|
this.fontTable = createFontTable(this.fontOptionsWithKey);
|
||||||
|
this.relationships = new Relationships();
|
||||||
|
|
||||||
|
for (let i = 0; i < options.length; i++) {
|
||||||
|
this.relationships.createRelationship(
|
||||||
|
i + 1,
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/font",
|
||||||
|
`fonts/${options[i].name}.odttf`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get View(): XmlComponent {
|
||||||
|
return this.fontTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get Relationships(): Relationships {
|
||||||
|
return this.relationships;
|
||||||
|
}
|
||||||
|
}
|
223
src/file/fonts/font.spec.ts
Normal file
223
src/file/fonts/font.spec.ts
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { Formatter } from "@export/formatter";
|
||||||
|
|
||||||
|
import { createFont } from "./font";
|
||||||
|
|
||||||
|
describe("font", () => {
|
||||||
|
it("should work", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
altName: "Times New Roman",
|
||||||
|
family: "roman",
|
||||||
|
charset: "00",
|
||||||
|
panose1: "02020603050405020304",
|
||||||
|
pitch: "variable",
|
||||||
|
embedRegular: {
|
||||||
|
id: "rId0",
|
||||||
|
fontKey: "00000000-0000-0000-0000-000000000000",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:font": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"w:name": "Times New Roman",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:altName": {
|
||||||
|
_attr: {
|
||||||
|
"w:val": "Times New Roman",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:panose1": {
|
||||||
|
_attr: {
|
||||||
|
"w:val": "02020603050405020304",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:charset": {
|
||||||
|
_attr: {
|
||||||
|
"w:val": "00",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:family": {
|
||||||
|
_attr: {
|
||||||
|
"w:val": "roman",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:pitch": {
|
||||||
|
_attr: {
|
||||||
|
"w:val": "variable",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:embedRegular": {
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId0",
|
||||||
|
"w:fontKey": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work for embedBold", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
embedBold: {
|
||||||
|
id: "rId0",
|
||||||
|
fontKey: "00000000-0000-0000-0000-000000000000",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"w:font": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"w:embedBold": {
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId0",
|
||||||
|
"w:fontKey": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work for embedBoldItalic", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
embedBoldItalic: {
|
||||||
|
id: "rId0",
|
||||||
|
fontKey: "00000000-0000-0000-0000-000000000000",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"w:font": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"w:embedBoldItalic": {
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId0",
|
||||||
|
"w:fontKey": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work for embedItalic", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
embedItalic: {
|
||||||
|
id: "rId0",
|
||||||
|
fontKey: "00000000-0000-0000-0000-000000000000",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"w:font": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"w:embedItalic": {
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId0",
|
||||||
|
"w:fontKey": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work for notTrueType", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
embedRegular: {
|
||||||
|
id: "rId0",
|
||||||
|
fontKey: "00000000-0000-0000-0000-000000000000",
|
||||||
|
subsetted: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"w:font": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"w:embedRegular": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId0",
|
||||||
|
"w:fontKey": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:subsetted": {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work for subsetted", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
notTrueType: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"w:font": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"w:notTrueType": {},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work without fontKey", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
embedItalic: {
|
||||||
|
id: "rId0",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"w:font": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"w:embedItalic": {
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
156
src/file/fonts/font.ts
Normal file
156
src/file/fonts/font.ts
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
import { BuilderElement, createStringElement, OnOffElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_Font">
|
||||||
|
// <xsd:sequence>
|
||||||
|
// <xsd:element name="altName" type="CT_String" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="panose1" type="CT_Panose" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="charset" type="CT_Charset" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="family" type="CT_FontFamily" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="notTrueType" type="CT_OnOff" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="pitch" type="CT_Pitch" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="sig" type="CT_FontSig" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="embedRegular" type="CT_FontRel" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="embedBold" type="CT_FontRel" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="embedItalic" type="CT_FontRel" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="embedBoldItalic" type="CT_FontRel" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// <xsd:attribute name="name" type="s:ST_String" use="required"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_FontRel">
|
||||||
|
// <xsd:complexContent>
|
||||||
|
// <xsd:extension base="CT_Rel">
|
||||||
|
// <xsd:attribute name="fontKey" type="s:ST_Guid" />
|
||||||
|
// <xsd:attribute name="subsetted" type="s:ST_OnOff" />
|
||||||
|
// </xsd:extension>
|
||||||
|
// </xsd:complexContent>
|
||||||
|
// </xsd:complexType>
|
||||||
|
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_embedRegular-1.html
|
||||||
|
export interface IFontRelationshipOptions {
|
||||||
|
/**
|
||||||
|
* Relationship to Part
|
||||||
|
*/
|
||||||
|
readonly id: string;
|
||||||
|
/**
|
||||||
|
* Embedded Font Obfuscation Key
|
||||||
|
*/
|
||||||
|
readonly fontKey?: string;
|
||||||
|
/**
|
||||||
|
* Embedded Font Is Subsetted
|
||||||
|
*/
|
||||||
|
readonly subsetted?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CharacterSet = {
|
||||||
|
ANSI: "00",
|
||||||
|
DEFAULT: "01",
|
||||||
|
SYMBOL: "02",
|
||||||
|
MAC: "4D",
|
||||||
|
JIS: "80",
|
||||||
|
HANGUL: "81",
|
||||||
|
JOHAB: "82",
|
||||||
|
GB_2312: "86",
|
||||||
|
CHINESEBIG5: "88",
|
||||||
|
GREEK: "A1",
|
||||||
|
TURKISH: "A2",
|
||||||
|
VIETNAMESE: "A3",
|
||||||
|
HEBREW: "B1",
|
||||||
|
ARABIC: "B2",
|
||||||
|
BALTIC: "BA",
|
||||||
|
RUSSIAN: "CC",
|
||||||
|
THAI: "DE",
|
||||||
|
EASTEUROPE: "EE",
|
||||||
|
OEM: "FF",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type FontOptions = {
|
||||||
|
readonly name: string;
|
||||||
|
readonly altName?: string;
|
||||||
|
readonly panose1?: string;
|
||||||
|
readonly charset?: (typeof CharacterSet)[keyof typeof CharacterSet];
|
||||||
|
readonly family?: string;
|
||||||
|
readonly notTrueType?: boolean;
|
||||||
|
readonly pitch?: string;
|
||||||
|
readonly sig?: {
|
||||||
|
readonly usb0: string;
|
||||||
|
readonly usb1: string;
|
||||||
|
readonly usb2: string;
|
||||||
|
readonly usb3: string;
|
||||||
|
readonly csb0: string;
|
||||||
|
readonly csb1: string;
|
||||||
|
};
|
||||||
|
readonly embedRegular?: IFontRelationshipOptions;
|
||||||
|
readonly embedBold?: IFontRelationshipOptions;
|
||||||
|
readonly embedItalic?: IFontRelationshipOptions;
|
||||||
|
readonly embedBoldItalic?: IFontRelationshipOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFontRelationship = ({ id, fontKey, subsetted }: IFontRelationshipOptions, name: string): XmlComponent =>
|
||||||
|
new BuilderElement({
|
||||||
|
name,
|
||||||
|
attributes: {
|
||||||
|
id: { key: "r:id", value: id },
|
||||||
|
...(fontKey ? { fontKey: { key: "w:fontKey", value: `{${fontKey}}` } } : {}),
|
||||||
|
},
|
||||||
|
children: [...(subsetted ? [new OnOffElement("w:subsetted", subsetted)] : [])],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createFont = ({
|
||||||
|
name,
|
||||||
|
altName,
|
||||||
|
panose1,
|
||||||
|
charset,
|
||||||
|
family,
|
||||||
|
notTrueType,
|
||||||
|
pitch,
|
||||||
|
sig,
|
||||||
|
embedRegular,
|
||||||
|
embedBold,
|
||||||
|
embedItalic,
|
||||||
|
embedBoldItalic,
|
||||||
|
}: FontOptions): XmlComponent =>
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_font-1.html
|
||||||
|
new BuilderElement({
|
||||||
|
name: "w:font",
|
||||||
|
attributes: {
|
||||||
|
name: { key: "w:name", value: name },
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_altName-1.html
|
||||||
|
...(altName ? [createStringElement("w:altName", altName)] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_panose1-1.html
|
||||||
|
...(panose1 ? [createStringElement("w:panose1", panose1)] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_charset-1.html
|
||||||
|
...(charset ? [createStringElement("w:charset", charset)] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_family-1.html
|
||||||
|
...(family ? [createStringElement("w:family", family)] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_notTrueType-1.html
|
||||||
|
...(notTrueType ? [new OnOffElement("w:notTrueType", notTrueType)] : []),
|
||||||
|
...(pitch ? [createStringElement("w:pitch", pitch)] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_sig-1.html
|
||||||
|
...(sig
|
||||||
|
? [
|
||||||
|
new BuilderElement({
|
||||||
|
name: "w:sig",
|
||||||
|
attributes: {
|
||||||
|
usb0: { key: "w:usb0", value: sig.usb0 },
|
||||||
|
usb1: { key: "w:usb1", value: sig.usb1 },
|
||||||
|
usb2: { key: "w:usb2", value: sig.usb2 },
|
||||||
|
usb3: { key: "w:usb3", value: sig.usb3 },
|
||||||
|
csb0: { key: "w:csb0", value: sig.csb0 },
|
||||||
|
csb1: { key: "w:csb1", value: sig.csb1 },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_embedRegular-1.html
|
||||||
|
...(embedRegular ? [createFontRelationship(embedRegular, "w:embedRegular")] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_embedBold-1.html
|
||||||
|
...(embedBold ? [createFontRelationship(embedBold, "w:embedBold")] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_embedItalic-1.html
|
||||||
|
...(embedItalic ? [createFontRelationship(embedItalic, "w:embedItalic")] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_embedBoldItalic-1.html
|
||||||
|
...(embedBoldItalic ? [createFontRelationship(embedBoldItalic, "w:embedBoldItalic")] : []),
|
||||||
|
],
|
||||||
|
});
|
1
src/file/fonts/index.ts
Normal file
1
src/file/fonts/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { CharacterSet } from "./font";
|
22
src/file/fonts/obfuscate-ttf-to-odttf.ts
Normal file
22
src/file/fonts/obfuscate-ttf-to-odttf.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
const obfuscatedStartOffset = 0;
|
||||||
|
const obfuscatedEndOffset = 32;
|
||||||
|
const guidSize = 32;
|
||||||
|
|
||||||
|
export const obfuscate = (buf: Buffer, fontKey: string): Buffer => {
|
||||||
|
const guid = fontKey.replace(/-/g, "");
|
||||||
|
if (guid.length !== guidSize) {
|
||||||
|
throw new Error(`Error: Cannot extract GUID from font filename: ${fontKey}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hexStrings = guid.replace(/(..)/g, "$1 ").trim().split(" ");
|
||||||
|
const hexNumbers = hexStrings.map((hexString) => parseInt(hexString, 16));
|
||||||
|
// eslint-disable-next-line functional/immutable-data
|
||||||
|
hexNumbers.reverse();
|
||||||
|
|
||||||
|
const bytesToObfuscate = buf.slice(obfuscatedStartOffset, obfuscatedEndOffset);
|
||||||
|
// eslint-disable-next-line no-bitwise
|
||||||
|
const obfuscatedBytes = bytesToObfuscate.map((byte, i) => byte ^ hexNumbers[i % hexNumbers.length]);
|
||||||
|
|
||||||
|
const out = Buffer.concat([buf.slice(0, obfuscatedStartOffset), obfuscatedBytes, buf.slice(obfuscatedEndOffset)]);
|
||||||
|
return out;
|
||||||
|
};
|
14
src/file/fonts/obsfuscate-ttf-to-odtts.spec.ts
Normal file
14
src/file/fonts/obsfuscate-ttf-to-odtts.spec.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { obfuscate } from "./obfuscate-ttf-to-odttf";
|
||||||
|
|
||||||
|
describe("obfuscate", () => {
|
||||||
|
it("should work", () => {
|
||||||
|
const buffer = obfuscate(Buffer.from(""), "00000000-0000-0000-0000-000000000000");
|
||||||
|
expect(buffer).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw error if uuid is not correct", () => {
|
||||||
|
expect(() => obfuscate(Buffer.from(""), "bad-uuid")).toThrowError();
|
||||||
|
});
|
||||||
|
});
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user