Compare commits
92 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 |
@ -17,9 +17,11 @@
|
||||
"dolan",
|
||||
"execa",
|
||||
"falsey",
|
||||
"horz",
|
||||
"iife",
|
||||
"Initializable",
|
||||
"iroha",
|
||||
"JOHAB",
|
||||
"jsonify",
|
||||
"jszip",
|
||||
"NUMPAGES",
|
||||
@ -53,7 +55,8 @@
|
||||
"\\.to\\.include\\.members\\(\\[[^\\]]+]\\)",
|
||||
"/new [a-zA-Z]+\\({[^£]+}\\)/g",
|
||||
"/<element name=\"[a-z]+\"/gi",
|
||||
"/<attribute name=\"[a-z]+\"/gi"
|
||||
"/<attribute name=\"[a-z]+\"/gi",
|
||||
"/key: \".+\"/"
|
||||
],
|
||||
"ignorePaths": ["package.json", "docs/api", "*.docx", "build"],
|
||||
"allowCompoundWords": true,
|
||||
|
@ -7,7 +7,6 @@ parser: "@typescript-eslint/parser"
|
||||
parserOptions:
|
||||
project:
|
||||
- tsconfig.json
|
||||
- demo/tsconfig.json
|
||||
sourceType: module
|
||||
plugins:
|
||||
- eslint-plugin-import
|
||||
@ -93,6 +92,7 @@ rules:
|
||||
format:
|
||||
- camelCase
|
||||
- PascalCase
|
||||
- UPPER_CASE # for constants
|
||||
filter:
|
||||
regex: (^[a-z]+:.+)|_attr|[0-9]
|
||||
match: false
|
||||
@ -214,8 +214,7 @@ rules:
|
||||
valid-typeof: "off"
|
||||
functional/immutable-data:
|
||||
- error
|
||||
- assumeTypes: true
|
||||
ignoreImmediateMutation: true
|
||||
- ignoreImmediateMutation: true
|
||||
ignoreAccessorPattern:
|
||||
- "**.root*"
|
||||
- "**.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
|
9
.github/workflows/default.yml
vendored
9
.github/workflows/default.yml
vendored
@ -14,10 +14,7 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@master
|
||||
- name: Install Dependencies
|
||||
run: npm ci --force
|
||||
- name: Build
|
||||
run: npm run build
|
||||
- uses: "./.github/actions/install-and-build"
|
||||
- name: Archive Production Artifact
|
||||
uses: actions/upload-artifact@master
|
||||
with:
|
||||
@ -32,7 +29,7 @@ jobs:
|
||||
- name: Install Dependencies
|
||||
run: npm ci --force
|
||||
- name: Test
|
||||
run: npm run test.ci
|
||||
run: npm run test:ci
|
||||
- name: Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
@ -57,7 +54,7 @@ jobs:
|
||||
- name: Install Dependencies
|
||||
run: npm ci --force
|
||||
- name: Prettier
|
||||
run: npm run style
|
||||
run: npm run prettier
|
||||
cspell:
|
||||
name: CSpell
|
||||
runs-on: ubuntu-latest
|
||||
|
943
.github/workflows/demos.yml
vendored
943
.github/workflows/demos.yml
vendored
@ -8,792 +8,189 @@ on:
|
||||
- master
|
||||
|
||||
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:
|
||||
name: Run Demos and Validate
|
||||
needs: [build]
|
||||
name: Demos
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@master
|
||||
- name: Install Dependencies
|
||||
run: npm ci --force
|
||||
- name: Download Artifact
|
||||
uses: actions/download-artifact@master
|
||||
with:
|
||||
name: build
|
||||
path: build
|
||||
- name: Run Demo
|
||||
run: npm run ts-node -- ./demo/1-basic.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/2-declaritive-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/3-numbering-and-bullet-points.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/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
|
||||
- uses: actions/checkout@master
|
||||
- uses: "./.github/actions/install-and-build"
|
||||
- name: Run Demos
|
||||
run: npm run run-ts -- ./demo/1-basic.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/2-declaritive-styles.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/3-numbering-and-bullet-points.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/4-basic-table.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/5-images.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/6-page-borders.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/7-landscape.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/8-header-footer.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/9-images-in-header-and-footer.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/10-my-cv.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/11-declaritive-styles-2.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/12-scaling-images.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/13-xml-styles.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/14-page-numbers.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/15-page-break-before.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/16-multiple-sections.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/17-footnotes.ts
|
||||
# element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected.
|
||||
# - 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/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
|
||||
# - uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/18-image-from-buffer.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/19-export-to-base64.ts
|
||||
# Base 64 No longer works, abruptly. Node issue?
|
||||
# - 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/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
|
||||
# - uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/20-table-cell-borders.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/21-bookmarks.ts
|
||||
# Bad ID - need numeric ID
|
||||
# - 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/22-right-to-left-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/23-base64-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/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
|
||||
# - uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/22-right-to-left-text.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/23-base64-images.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/24-images-to-table-cell.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/25-table-xml-styles.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/26-paragraph-borders.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/27-declaritive-styles-3.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/28-table-of-contents.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/29-numbered-lists.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/31-tables.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/32-merge-and-shade-table-cells.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/33-sequential-captions.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/34-floating-tables.ts
|
||||
# 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.
|
||||
# - 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/35-hyperlinks.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/36-image-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/37-images-to-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/38-text-wrapping.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/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
|
||||
# - uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/35-hyperlinks.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/36-image-to-table-cell.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/37-images-to-header-and-footer.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/38-text-wrapping.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/39-page-numbers.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/40-line-numbers.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/41-merge-table-cells-2.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/42-restart-page-numbers.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/43-images-to-table-cell-2.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/44-multiple-columns.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/45-highlighting-text.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/46-shading-text.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/47-number-of-total-pages-section.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/48-vertical-align.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/49-table-borders.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/50-readme-demo.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/51-character-styles.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/52-japanese.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/53-chinese.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/54-custom-properties.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/55-math.ts
|
||||
#: 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}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 ).
|
||||
# - 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/56-background-color.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/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
|
||||
# - uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/56-background-color.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/57-add-parent-numbered-lists.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/58-section-types.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/59-header-footer-margins.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/60-track-revisions.ts
|
||||
# element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected.
|
||||
# - 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/61-text-frame.ts
|
||||
- name: Extract Word Document
|
||||
run: npm run extract
|
||||
# - uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/61-text-frame.ts
|
||||
# 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: 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/62-paragraph-spacing.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/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
|
||||
# - uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/62-paragraph-spacing.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/63-odd-even-header-footer.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/64-complex-numbering-text.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/65-page-sizes.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/66-fields.ts
|
||||
# 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'.
|
||||
# - 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/67-column-break.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/68-numbering-instances-and-starting-number.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/69-different-width-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/70-line-numbers-suppression.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/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
|
||||
# - uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/67-column-break.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/68-numbering-instances-and-starting-number.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/69-different-width-columns.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/70-line-numbers-suppression.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/71-page-borders-2.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/72-word-wrap.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/73-comments.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/74-nodejs-stream.ts
|
||||
# - uses: "./.github/actions/validate-docx"
|
||||
# run: npm run run-ts -- ./demo/75-tab-stops.ts
|
||||
# - uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/76-compatibility.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/77-side-by-side-tables.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/78-thai-distributed.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/79-table-from-data-source.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/80-thai-distributed.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/81-continuous-header.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/82-new-headers-new-section.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/83-setting-languages.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
- run: npm run run-ts -- ./demo/84-positional-tabs.ts
|
||||
- uses: "./.github/actions/validate-docx"
|
||||
|
16
.vscode/launch.json
vendored
16
.vscode/launch.json
vendored
@ -1,18 +1,4 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"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"
|
||||
}
|
||||
]
|
||||
"configurations": []
|
||||
}
|
||||
|
20
.vscode/tasks.json
vendored
20
.vscode/tasks.json
vendored
@ -2,23 +2,5 @@
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "typescript",
|
||||
"tsconfig": "tsconfig.json",
|
||||
"option": "watch",
|
||||
"problemMatcher": [
|
||||
"$tsc-watch"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "ts-node",
|
||||
"problemMatcher": [],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
}
|
||||
]
|
||||
"tasks": []
|
||||
}
|
@ -45,7 +45,7 @@ const doc = new Document({
|
||||
children: [
|
||||
new TextRun("My Title "),
|
||||
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 {
|
||||
convertMillimetersToTwip,
|
||||
Document,
|
||||
HorizontalPositionAlign,
|
||||
HorizontalPositionRelativeFrom,
|
||||
@ -20,6 +21,7 @@ const doc = new Document({
|
||||
new Paragraph({
|
||||
children: [
|
||||
new ImageRun({
|
||||
type: "jpg",
|
||||
data: fs.readFileSync("./demo/images/image1.jpeg"),
|
||||
transformation: {
|
||||
width: 100,
|
||||
@ -36,17 +38,24 @@ const doc = new Document({
|
||||
new Paragraph({
|
||||
children: [
|
||||
new ImageRun({
|
||||
type: "png",
|
||||
data: fs.readFileSync("./demo/images/dog.png").toString("base64"),
|
||||
transformation: {
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
outline: {
|
||||
type: "solidFill",
|
||||
solidFillType: "rgb",
|
||||
value: "FF0000",
|
||||
},
|
||||
}),
|
||||
],
|
||||
}),
|
||||
new Paragraph({
|
||||
children: [
|
||||
new ImageRun({
|
||||
type: "jpg",
|
||||
data: fs.readFileSync("./demo/images/cat.jpg"),
|
||||
transformation: {
|
||||
width: 100,
|
||||
@ -55,12 +64,19 @@ const doc = new Document({
|
||||
vertical: true,
|
||||
},
|
||||
},
|
||||
outline: {
|
||||
type: "solidFill",
|
||||
solidFillType: "rgb",
|
||||
value: "0000FF",
|
||||
width: convertMillimetersToTwip(600),
|
||||
},
|
||||
}),
|
||||
],
|
||||
}),
|
||||
new Paragraph({
|
||||
children: [
|
||||
new ImageRun({
|
||||
type: "bmp",
|
||||
data: fs.readFileSync("./demo/images/parrots.bmp"),
|
||||
transformation: {
|
||||
width: 150,
|
||||
@ -76,6 +92,7 @@ const doc = new Document({
|
||||
new Paragraph({
|
||||
children: [
|
||||
new ImageRun({
|
||||
type: "gif",
|
||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||
transformation: {
|
||||
width: 200,
|
||||
@ -91,6 +108,7 @@ const doc = new Document({
|
||||
new Paragraph({
|
||||
children: [
|
||||
new ImageRun({
|
||||
type: "gif",
|
||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||
transformation: {
|
||||
width: 200,
|
||||
@ -112,6 +130,7 @@ const doc = new Document({
|
||||
new Paragraph({
|
||||
children: [
|
||||
new ImageRun({
|
||||
type: "jpg",
|
||||
data: fs.readFileSync("./demo/images/cat.jpg"),
|
||||
transformation: {
|
||||
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,
|
||||
Paragraph,
|
||||
TextRun,
|
||||
MathLimitLower,
|
||||
MathLimitUpper,
|
||||
} from "docx";
|
||||
|
||||
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 {
|
||||
AlignmentType,
|
||||
BorderStyle,
|
||||
Document,
|
||||
FrameAnchorType,
|
||||
@ -20,6 +21,7 @@ const doc = new Document({
|
||||
children: [
|
||||
new Paragraph({
|
||||
frame: {
|
||||
type: "absolute",
|
||||
position: {
|
||||
x: 1000,
|
||||
y: 3000,
|
||||
@ -30,6 +32,54 @@ const doc = new Document({
|
||||
horizontal: 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: {
|
||||
x: HorizontalPositionAlign.CENTER,
|
||||
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
|
||||
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 doc = new Document({
|
||||
defaultTabStop: 0,
|
||||
sections: [
|
||||
{
|
||||
properties: {},
|
||||
|
@ -16,7 +16,9 @@ import {
|
||||
VerticalAlign,
|
||||
} from "docx";
|
||||
|
||||
patchDocument(fs.readFileSync("demo/assets/simple-template.docx"), {
|
||||
patchDocument({
|
||||
outputType: "nodebuffer",
|
||||
data: fs.readFileSync("demo/assets/simple-template.docx"),
|
||||
patches: {
|
||||
name: {
|
||||
type: PatchType.PARAGRAPH,
|
||||
@ -56,7 +58,11 @@ patchDocument(fs.readFileSync("demo/assets/simple-template.docx"), {
|
||||
],
|
||||
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: {
|
||||
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: {
|
||||
type: PatchType.DOCUMENT,
|
||||
|
@ -3,7 +3,9 @@
|
||||
import * as fs from "fs";
|
||||
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: {
|
||||
name: {
|
||||
type: PatchType.PARAGRAPH,
|
||||
|
@ -24,7 +24,9 @@ const patches = getPatches({
|
||||
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,
|
||||
}).then((doc) => {
|
||||
fs.writeFileSync("My Document.docx", doc);
|
||||
|
@ -22,8 +22,11 @@ const patches = getPatches({
|
||||
"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,
|
||||
keepOriginalStyles: true,
|
||||
}).then((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);
|
||||
});
|
BIN
demo/assets/Pacifico.ttf
Normal file
BIN
demo/assets/Pacifico.ttf
Normal file
Binary file not shown.
Binary file not shown.
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]);
|
||||
|
||||
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("Successfully created document!");
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
- Simple, declarative API
|
||||
- 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)
|
||||
[Get Started](#Welcome)
|
||||
|
@ -6,6 +6,7 @@ To create a `floating` image on top of text:
|
||||
|
||||
```ts
|
||||
const image = new ImageRun({
|
||||
type: 'gif',
|
||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||
transformation: {
|
||||
width: 200,
|
||||
@ -26,6 +27,7 @@ By default with no arguments, its an `inline` image:
|
||||
|
||||
```ts
|
||||
const image = new ImageRun({
|
||||
type: 'gif',
|
||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||
transformation: {
|
||||
width: 100,
|
||||
@ -59,6 +61,7 @@ const doc = new Document({
|
||||
new Paragraph({
|
||||
children: [
|
||||
new ImageRun({
|
||||
type: [IMAGE_TYPE],
|
||||
data: [IMAGE_BUFFER],
|
||||
transformation: {
|
||||
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
|
||||
const image = new ImageRun({
|
||||
type: 'png',
|
||||
data: buffer,
|
||||
transformation: {
|
||||
width: 903,
|
||||
@ -115,6 +119,7 @@ const image = new ImageRun({
|
||||
|
||||
```ts
|
||||
const image = new ImageRun({
|
||||
type: 'png',
|
||||
data: buffer,
|
||||
transformation: {
|
||||
width: 903,
|
||||
@ -180,6 +185,7 @@ For example:
|
||||
|
||||
```ts
|
||||
const image = new ImageRun({
|
||||
type: 'gif',
|
||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||
transformation: {
|
||||
width: 200,
|
||||
@ -228,6 +234,7 @@ For example:
|
||||
|
||||
```ts
|
||||
const image = new ImageRun({
|
||||
type: 'gif',
|
||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||
transformation: {
|
||||
width: 200,
|
||||
@ -258,6 +265,7 @@ Specifies common non-visual DrawingML properties. A name, title and description
|
||||
|
||||
```ts
|
||||
const image = new ImageRun({
|
||||
type: 'gif',
|
||||
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||
altText: {
|
||||
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")],
|
||||
}),
|
||||
```
|
||||
|
@ -130,6 +130,62 @@ new Paragraph({
|
||||
}),
|
||||
```
|
||||
|
||||
## 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")
|
||||
|
@ -35,6 +35,9 @@ interface Patch {
|
||||
| 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. |
|
||||
|
||||
|
||||
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
|
||||
|
||||
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",
|
||||
}),
|
||||
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 } }),
|
||||
],
|
||||
}),
|
||||
],
|
||||
|
@ -22,7 +22,7 @@ Then add the table in the `section`
|
||||
const doc = new Document({
|
||||
sections: [{
|
||||
children: [table],
|
||||
}];
|
||||
}],
|
||||
});
|
||||
```
|
||||
|
||||
|
7840
package-lock.json
generated
7840
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
48
package.json
48
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docx",
|
||||
"version": "8.2.4",
|
||||
"version": "8.6.0",
|
||||
"description": "Easily generate .docx files with JS/TS with a nice declarative API. Works for Node and on the Browser.",
|
||||
"type": "module",
|
||||
"main": "build/index.umd.js",
|
||||
@ -20,21 +20,21 @@
|
||||
"scripts": {
|
||||
"build": "tsc && vite build",
|
||||
"test": "vitest --ui --coverage",
|
||||
"test.ci": "vitest run --coverage",
|
||||
"test:ci": "vitest run --coverage",
|
||||
"prepublishOnly": "npm run build --omit=dev",
|
||||
"lint": "eslint --ext .ts src",
|
||||
"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",
|
||||
"style": "prettier -l \"{src,scripts,demo}/**/*.{ts,html}\"",
|
||||
"style.fix": "npm run style -- --write",
|
||||
"prettier": "prettier -l \"{src,scripts,demo}/**/*.{ts,html}\"",
|
||||
"prettier:fix": "npm run prettier -- --write",
|
||||
"cspell": "cspell \"{src,demo,docs,scripts}/**/*.{ts,scss,html,md}\" && cspell \"./*.*\"",
|
||||
"serve.docs": "cd docs && docsify serve",
|
||||
"extract": "ts-node scripts/extract-document.ts",
|
||||
"ts-node": "ts-node --project demo/tsconfig.json"
|
||||
"extract": "tsx scripts/extract-document.ts",
|
||||
"run-ts": "tsx"
|
||||
},
|
||||
"pre-commit": [
|
||||
"style",
|
||||
"prettier",
|
||||
"lint"
|
||||
],
|
||||
"repository": {
|
||||
@ -56,7 +56,7 @@
|
||||
"dependencies": {
|
||||
"@types/node": "^20.3.1",
|
||||
"jszip": "^3.10.1",
|
||||
"nanoid": "^4.0.2",
|
||||
"nanoid": "^5.0.4",
|
||||
"xml": "^1.0.1",
|
||||
"xml-js": "^1.6.8"
|
||||
},
|
||||
@ -71,35 +71,35 @@
|
||||
"@types/prompt": "^1.1.1",
|
||||
"@types/unzipper": "^0.10.4",
|
||||
"@types/xml": "^1.0.8",
|
||||
"@typescript-eslint/eslint-plugin": "^6.9.1",
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||
"@typescript-eslint/parser": "^6.9.1",
|
||||
"@vitest/coverage-v8": "^0.33.0",
|
||||
"@vitest/ui": "^0.33.0",
|
||||
"cspell": "^7.3.8",
|
||||
"@vitest/coverage-v8": "^1.1.0",
|
||||
"@vitest/ui": "^1.1.0",
|
||||
"cspell": "^8.2.3",
|
||||
"docsify-cli": "^4.3.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-jsdoc": "^46.2.6",
|
||||
"eslint-plugin-jsdoc": "^48.0.2",
|
||||
"eslint-plugin-no-null": "^1.0.2",
|
||||
"eslint-plugin-prefer-arrow": "^1.2.3",
|
||||
"eslint-plugin-unicorn": "^48.0.1",
|
||||
"eslint-plugin-unicorn": "^50.0.1",
|
||||
"execa": "^8.0.1",
|
||||
"glob": "^10.2.7",
|
||||
"inquirer": "^9.2.7",
|
||||
"jsdom": "^22.1.0",
|
||||
"jsdom": "^24.0.0",
|
||||
"pre-commit": "^1.2.2",
|
||||
"prettier": "^3.0.0",
|
||||
"ts-node": "^10.2.1",
|
||||
"prettier": "^3.1.1",
|
||||
"tsconfig-paths": "^4.0.0",
|
||||
"typedoc": "^0.24.8",
|
||||
"typescript": "5.1.6",
|
||||
"tsx": "^4.7.0",
|
||||
"typedoc": "^0.25.4",
|
||||
"typescript": "5.3.3",
|
||||
"unzipper": "^0.10.11",
|
||||
"vite": "^4.3.2",
|
||||
"vite": "^5.0.10",
|
||||
"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",
|
||||
"vitest": "^0.33.0"
|
||||
"vitest": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
|
@ -12,7 +12,8 @@ describe("ImageReplacer", () => {
|
||||
"test {test-image.png} test",
|
||||
[
|
||||
{
|
||||
stream: Buffer.from(""),
|
||||
type: "png",
|
||||
data: Buffer.from(""),
|
||||
fileName: "test-image.png",
|
||||
transformation: {
|
||||
pixels: {
|
||||
|
@ -36,7 +36,7 @@ describe("Compiler", () => {
|
||||
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
|
||||
|
||||
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/styles.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/settings.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/fontTable.xml.rels");
|
||||
expect(fileNames).to.include("[Content_Types].xml");
|
||||
expect(fileNames).to.include("_rels/.rels");
|
||||
},
|
||||
@ -94,7 +96,7 @@ describe("Compiler", () => {
|
||||
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
|
||||
|
||||
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/_rels/header1.xml.rels");
|
||||
@ -127,12 +129,10 @@ describe("Compiler", () => {
|
||||
const spy = vi.spyOn(compiler["formatter"], "format");
|
||||
|
||||
compiler.compile(file);
|
||||
expect(spy).toBeCalledTimes(13);
|
||||
expect(spy).toBeCalledTimes(15);
|
||||
});
|
||||
|
||||
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({
|
||||
sections: [
|
||||
{
|
||||
@ -150,12 +150,25 @@ describe("Compiler", () => {
|
||||
new Paragraph({
|
||||
children: [
|
||||
new ImageRun({
|
||||
type: "png",
|
||||
data: Buffer.from("", "base64"),
|
||||
transformation: {
|
||||
width: 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([
|
||||
{
|
||||
stream: Buffer.from(""),
|
||||
type: "png",
|
||||
data: Buffer.from(""),
|
||||
fileName: "test",
|
||||
transformation: {
|
||||
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);
|
||||
});
|
||||
|
||||
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 { File } from "@file/file";
|
||||
import { obfuscate } from "@file/fonts/obfuscate-ttf-to-odttf";
|
||||
|
||||
import { Formatter } from "../formatter";
|
||||
import { ImageReplacer } from "./image-replacer";
|
||||
@ -31,6 +32,8 @@ interface IXmlifyedFileMapping {
|
||||
readonly FootNotesRelationships: IXmlifyedFile;
|
||||
readonly Settings: IXmlifyedFile;
|
||||
readonly Comments?: IXmlifyedFile;
|
||||
readonly FontTable?: IXmlifyedFile;
|
||||
readonly FontTableRelationships?: IXmlifyedFile;
|
||||
}
|
||||
|
||||
export class Compiler {
|
||||
@ -44,7 +47,7 @@ export class Compiler {
|
||||
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 xmlifiedFileMapping = this.xmlifyFile(file, prettifyXml);
|
||||
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) {
|
||||
zip.file(`word/media/${fileName}`, stream);
|
||||
for (const data of file.Media.Array) {
|
||||
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;
|
||||
}
|
||||
|
||||
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 documentXmlData = xml(
|
||||
@ -439,6 +452,40 @@ export class Compiler {
|
||||
),
|
||||
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
|
||||
*/
|
||||
export enum PrettifyType {
|
||||
NONE = "",
|
||||
WITH_2_BLANKS = " ",
|
||||
WITH_4_BLANKS = " ",
|
||||
WITH_TAB = "\t",
|
||||
}
|
||||
export const PrettifyType = {
|
||||
NONE: "",
|
||||
WITH_2_BLANKS: " ",
|
||||
WITH_4_BLANKS: " ",
|
||||
// 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;
|
||||
|
||||
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 zipData = await zip.generateAsync({
|
||||
type: "string",
|
||||
@ -28,7 +31,7 @@ export class Packer {
|
||||
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 zipData = await zip.generateAsync({
|
||||
type: "nodebuffer",
|
||||
@ -39,7 +42,7 @@ export class Packer {
|
||||
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 zipData = await zip.generateAsync({
|
||||
type: "base64",
|
||||
@ -50,7 +53,7 @@ export class Packer {
|
||||
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 zipData = await zip.generateAsync({
|
||||
type: "blob",
|
||||
@ -61,7 +64,7 @@ export class Packer {
|
||||
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 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";
|
||||
|
||||
export interface IBorderOptions {
|
||||
readonly style: BorderStyle;
|
||||
readonly style: (typeof BorderStyle)[keyof typeof BorderStyle];
|
||||
/** Border color, in hex (eg 'FF00AA') */
|
||||
readonly color?: string;
|
||||
/** Size of the border in 1/8 pt */
|
||||
@ -55,32 +55,34 @@ class BordersAttributes extends XmlAttributeComponent<IBorderOptions> {
|
||||
};
|
||||
}
|
||||
|
||||
export enum BorderStyle {
|
||||
SINGLE = "single",
|
||||
DASH_DOT_STROKED = "dashDotStroked",
|
||||
DASHED = "dashed",
|
||||
DASH_SMALL_GAP = "dashSmallGap",
|
||||
DOT_DASH = "dotDash",
|
||||
DOT_DOT_DASH = "dotDotDash",
|
||||
DOTTED = "dotted",
|
||||
DOUBLE = "double",
|
||||
DOUBLE_WAVE = "doubleWave",
|
||||
INSET = "inset",
|
||||
NIL = "nil",
|
||||
NONE = "none",
|
||||
OUTSET = "outset",
|
||||
THICK = "thick",
|
||||
THICK_THIN_LARGE_GAP = "thickThinLargeGap",
|
||||
THICK_THIN_MEDIUM_GAP = "thickThinMediumGap",
|
||||
THICK_THIN_SMALL_GAP = "thickThinSmallGap",
|
||||
THIN_THICK_LARGE_GAP = "thinThickLargeGap",
|
||||
THIN_THICK_MEDIUM_GAP = "thinThickMediumGap",
|
||||
THIN_THICK_SMALL_GAP = "thinThickSmallGap",
|
||||
THIN_THICK_THIN_LARGE_GAP = "thinThickThinLargeGap",
|
||||
THIN_THICK_THIN_MEDIUM_GAP = "thinThickThinMediumGap",
|
||||
THIN_THICK_THIN_SMALL_GAP = "thinThickThinSmallGap",
|
||||
THREE_D_EMBOSS = "threeDEmboss",
|
||||
THREE_D_ENGRAVE = "threeDEngrave",
|
||||
TRIPLE = "triple",
|
||||
WAVE = "wave",
|
||||
}
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
export const BorderStyle = {
|
||||
SINGLE: "single",
|
||||
DASH_DOT_STROKED: "dashDotStroked",
|
||||
DASHED: "dashed",
|
||||
DASH_SMALL_GAP: "dashSmallGap",
|
||||
DOT_DASH: "dotDash",
|
||||
DOT_DOT_DASH: "dotDotDash",
|
||||
DOTTED: "dotted",
|
||||
DOUBLE: "double",
|
||||
DOUBLE_WAVE: "doubleWave",
|
||||
INSET: "inset",
|
||||
NIL: "nil",
|
||||
NONE: "none",
|
||||
OUTSET: "outset",
|
||||
THICK: "thick",
|
||||
THICK_THIN_LARGE_GAP: "thickThinLargeGap",
|
||||
THICK_THIN_MEDIUM_GAP: "thickThinMediumGap",
|
||||
THICK_THIN_SMALL_GAP: "thickThinSmallGap",
|
||||
THIN_THICK_LARGE_GAP: "thinThickLargeGap",
|
||||
THIN_THICK_MEDIUM_GAP: "thinThickMediumGap",
|
||||
THIN_THICK_SMALL_GAP: "thinThickSmallGap",
|
||||
THIN_THICK_THIN_LARGE_GAP: "thinThickThinLargeGap",
|
||||
THIN_THICK_THIN_MEDIUM_GAP: "thinThickThinMediumGap",
|
||||
THIN_THICK_THIN_SMALL_GAP: "thinThickThinSmallGap",
|
||||
THREE_D_EMBOSS: "threeDEmboss",
|
||||
THREE_D_ENGRAVE: "threeDEngrave",
|
||||
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"][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"][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" } },
|
||||
});
|
||||
expect(tree["Types"][7]).to.deep.equal({ Default: { _attr: { ContentType: "application/xml", Extension: "xml" } } });
|
||||
expect(tree["Types"][8]).to.deep.equal({
|
||||
expect(tree["Types"][8]).to.deep.equal({ Default: { _attr: { ContentType: "application/xml", Extension: "xml" } } });
|
||||
|
||||
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: {
|
||||
_attr: {
|
||||
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: {
|
||||
_attr: {
|
||||
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: {
|
||||
_attr: {
|
||||
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: {
|
||||
_attr: {
|
||||
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: {
|
||||
_attr: {
|
||||
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: {
|
||||
_attr: {
|
||||
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: {
|
||||
_attr: {
|
||||
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: {
|
||||
_attr: {
|
||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
|
||||
@ -102,7 +112,7 @@ describe("ContentTypes", () => {
|
||||
contentTypes.addFooter(102);
|
||||
const tree = new Formatter().format(contentTypes);
|
||||
|
||||
expect(tree["Types"][17]).to.deep.equal({
|
||||
expect(tree["Types"][20]).to.deep.equal({
|
||||
Override: {
|
||||
_attr: {
|
||||
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: {
|
||||
_attr: {
|
||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml",
|
||||
@ -128,7 +138,7 @@ describe("ContentTypes", () => {
|
||||
contentTypes.addHeader(202);
|
||||
const tree = new Formatter().format(contentTypes);
|
||||
|
||||
expect(tree["Types"][17]).to.deep.equal({
|
||||
expect(tree["Types"][20]).to.deep.equal({
|
||||
Override: {
|
||||
_attr: {
|
||||
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: {
|
||||
_attr: {
|
||||
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/bmp", "bmp"));
|
||||
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/xml", "xml"));
|
||||
this.root.push(new Default("application/vnd.openxmlformats-officedocument.obfuscatedFont", "odttf"));
|
||||
|
||||
this.root.push(
|
||||
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.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.fontTable+xml", "/word/fontTable.xml"));
|
||||
}
|
||||
|
||||
public addFooter(index: number): void {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { ICommentsOptions } from "@file/paragraph/run/comment-run";
|
||||
import { ICompatibilityOptions } from "@file/settings/compatibility";
|
||||
import { FontOptions } from "@file/fonts/font-table";
|
||||
import { StringContainer, XmlComponent } from "@file/xml-components";
|
||||
import { dateTimeValue } from "@util/values";
|
||||
|
||||
@ -39,6 +40,8 @@ export interface IPropertiesOptions {
|
||||
readonly compatibility?: ICompatibilityOptions;
|
||||
readonly customProperties?: readonly ICustomPropertyOptions[];
|
||||
readonly evenAndOddHeaderAndFooters?: boolean;
|
||||
readonly defaultTabStop?: number;
|
||||
readonly fonts?: readonly FontOptions[];
|
||||
}
|
||||
|
||||
// <xs:element name="coreProperties" type="CT_CoreProperties"/>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { XmlComponent } from "./xml-components";
|
||||
import { Document, IDocumentOptions } from "./document";
|
||||
import { Footer } from "./footer/footer";
|
||||
import { FootNotes } from "./footnotes";
|
||||
@ -5,7 +6,7 @@ import { Header } from "./header/header";
|
||||
import { Relationships } from "./relationships";
|
||||
|
||||
export interface IViewWrapper {
|
||||
readonly View: Document | Footer | Header | FootNotes;
|
||||
readonly View: Document | Footer | Header | FootNotes | XmlComponent;
|
||||
readonly Relationships: Relationships;
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,17 @@ import { decimalNumber } from "@util/values";
|
||||
// <xsd:attribute name="charSpace" type="ST_DecimalNumber"/>
|
||||
// </xsd:complexType>
|
||||
|
||||
export enum DocumentGridType {
|
||||
DEFAULT = "default",
|
||||
LINES = "lines",
|
||||
LINES_AND_CHARS = "linesAndChars",
|
||||
SNAP_TO_CHARS = "snapToChars",
|
||||
}
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
export const DocumentGridType = {
|
||||
DEFAULT: "default",
|
||||
LINES: "lines",
|
||||
LINES_AND_CHARS: "linesAndChars",
|
||||
SNAP_TO_CHARS: "snapToChars",
|
||||
} as const;
|
||||
|
||||
/* eslint-enable */
|
||||
export interface IDocGridAttributesProperties {
|
||||
readonly type?: DocumentGridType;
|
||||
readonly type?: (typeof DocumentGridType)[keyof typeof DocumentGridType];
|
||||
readonly linePitch?: number;
|
||||
readonly charSpace?: number;
|
||||
}
|
||||
@ -38,7 +41,7 @@ export class DocGridAttributes extends XmlAttributeComponent<IDocGridAttributesP
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
this.root.push(
|
||||
|
@ -7,11 +7,11 @@ import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||
// <xsd:enumeration value="first"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum HeaderFooterReferenceType {
|
||||
DEFAULT = "default",
|
||||
FIRST = "first",
|
||||
EVEN = "even",
|
||||
}
|
||||
export const HeaderFooterReferenceType = {
|
||||
DEFAULT: "default",
|
||||
FIRST: "first",
|
||||
EVEN: "even",
|
||||
} as const;
|
||||
|
||||
// </xsd:complexType>
|
||||
// <xsd:group name="EG_HdrFtrReferences">
|
||||
@ -33,12 +33,12 @@ export enum HeaderFooterReferenceType {
|
||||
// </xsd:complexType>
|
||||
|
||||
export interface IHeaderFooterOptions {
|
||||
readonly type?: HeaderFooterReferenceType;
|
||||
readonly type?: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType];
|
||||
readonly id?: number;
|
||||
}
|
||||
|
||||
class FooterReferenceAttributes extends XmlAttributeComponent<{
|
||||
readonly type: HeaderFooterReferenceType;
|
||||
readonly type: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType];
|
||||
readonly id: string;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
@ -47,12 +47,13 @@ class FooterReferenceAttributes extends XmlAttributeComponent<{
|
||||
};
|
||||
}
|
||||
|
||||
export enum HeaderFooterType {
|
||||
HEADER = "w:headerReference",
|
||||
FOOTER = "w:footerReference",
|
||||
}
|
||||
export const HeaderFooterType = {
|
||||
HEADER: "w:headerReference",
|
||||
FOOTER: "w:footerReference",
|
||||
} as const;
|
||||
|
||||
export class HeaderFooterReference extends XmlComponent {
|
||||
public constructor(type: HeaderFooterType, options: IHeaderFooterOptions) {
|
||||
public constructor(type: (typeof HeaderFooterType)[keyof typeof HeaderFooterType], options: IHeaderFooterOptions) {
|
||||
super(type);
|
||||
|
||||
this.root.push(
|
||||
|
@ -1,5 +1,5 @@
|
||||
// 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";
|
||||
|
||||
// <xsd:simpleType name="ST_LineNumberRestart">
|
||||
@ -9,11 +9,14 @@ import { decimalNumber, PositiveUniversalMeasure, twipsMeasureValue } from "@uti
|
||||
// <xsd:enumeration value="continuous"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum LineNumberRestartFormat {
|
||||
NEW_PAGE = "newPage",
|
||||
NEW_SECTION = "newSection",
|
||||
CONTINUOUS = "continuous",
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
export const LineNumberRestartFormat = {
|
||||
NEW_PAGE: "newPage",
|
||||
NEW_SECTION: "newSection",
|
||||
CONTINUOUS: "continuous",
|
||||
} as const;
|
||||
/* eslint-enable */
|
||||
|
||||
// <xsd:complexType name="CT_LineNumber">
|
||||
// <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:complexType>
|
||||
|
||||
export interface ILineNumberAttributes {
|
||||
export type ILineNumberAttributes = {
|
||||
readonly countBy?: number;
|
||||
readonly start?: number;
|
||||
readonly restart?: LineNumberRestartFormat;
|
||||
readonly restart?: (typeof LineNumberRestartFormat)[keyof typeof LineNumberRestartFormat];
|
||||
readonly distance?: number | PositiveUniversalMeasure;
|
||||
}
|
||||
};
|
||||
|
||||
export class LineNumberType extends XmlComponent {
|
||||
public constructor({ countBy, start, restart, distance }: ILineNumberAttributes) {
|
||||
super("w:lnNumType");
|
||||
this.root.push(
|
||||
new NextAttributeComponent<{
|
||||
readonly countBy?: number;
|
||||
readonly start?: number;
|
||||
readonly restart?: LineNumberRestartFormat;
|
||||
readonly distance?: number | PositiveUniversalMeasure;
|
||||
}>({
|
||||
export const createLineNumberType = ({ countBy, start, restart, distance }: ILineNumberAttributes): XmlComponent =>
|
||||
new BuilderElement<ILineNumberAttributes>({
|
||||
name: "w:lnNumType",
|
||||
attributes: {
|
||||
countBy: { key: "w:countBy", value: countBy === undefined ? undefined : decimalNumber(countBy) },
|
||||
start: { key: "w:start", value: start === undefined ? undefined : decimalNumber(start) },
|
||||
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:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum PageBorderDisplay {
|
||||
ALL_PAGES = "allPages",
|
||||
FIRST_PAGE = "firstPage",
|
||||
NOT_FIRST_PAGE = "notFirstPage",
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
export const PageBorderDisplay = {
|
||||
ALL_PAGES: "allPages",
|
||||
FIRST_PAGE: "firstPage",
|
||||
NOT_FIRST_PAGE: "notFirstPage",
|
||||
} as const;
|
||||
/* eslint-enable */
|
||||
|
||||
// <xsd:simpleType name="ST_PageBorderOffset">
|
||||
// <xsd:restriction base="xsd:string">
|
||||
@ -21,10 +24,10 @@ export enum PageBorderDisplay {
|
||||
// <xsd:enumeration value="text"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum PageBorderOffsetFrom {
|
||||
PAGE = "page",
|
||||
TEXT = "text",
|
||||
}
|
||||
export const PageBorderOffsetFrom = {
|
||||
PAGE: "page",
|
||||
TEXT: "text",
|
||||
} as const;
|
||||
|
||||
// <xsd:simpleType name="ST_PageBorderZOrder">
|
||||
// <xsd:restriction base="xsd:string">
|
||||
@ -32,15 +35,15 @@ export enum PageBorderOffsetFrom {
|
||||
// <xsd:enumeration value="back"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum PageBorderZOrder {
|
||||
BACK = "back",
|
||||
FRONT = "front",
|
||||
}
|
||||
export const PageBorderZOrder = {
|
||||
BACK: "back",
|
||||
FRONT: "front",
|
||||
} as const;
|
||||
|
||||
export interface IPageBorderAttributes {
|
||||
readonly display?: PageBorderDisplay;
|
||||
readonly offsetFrom?: PageBorderOffsetFrom;
|
||||
readonly zOrder?: PageBorderZOrder;
|
||||
readonly display?: (typeof PageBorderDisplay)[keyof typeof PageBorderDisplay];
|
||||
readonly offsetFrom?: (typeof PageBorderOffsetFrom)[keyof typeof PageBorderOffsetFrom];
|
||||
readonly zOrder?: (typeof PageBorderZOrder)[keyof typeof PageBorderZOrder];
|
||||
}
|
||||
|
||||
export interface IPageBordersOptions {
|
||||
|
@ -12,18 +12,22 @@ import { decimalNumber } from "@util/values";
|
||||
// <xsd:enumeration value="enDash"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum PageNumberSeparator {
|
||||
HYPHEN = "hyphen",
|
||||
PERIOD = "period",
|
||||
COLON = "colon",
|
||||
EM_DASH = "emDash",
|
||||
EN_DASH = "endash",
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
export const PageNumberSeparator = {
|
||||
HYPHEN: "hyphen",
|
||||
PERIOD: "period",
|
||||
COLON: "colon",
|
||||
EM_DASH: "emDash",
|
||||
EN_DASH: "endash",
|
||||
} as const;
|
||||
|
||||
/* eslint-enable */
|
||||
|
||||
export interface IPageNumberTypeAttributes {
|
||||
readonly start?: number;
|
||||
readonly formatType?: NumberFormat;
|
||||
readonly separator?: PageNumberSeparator;
|
||||
readonly formatType?: (typeof NumberFormat)[keyof typeof NumberFormat];
|
||||
readonly separator?: (typeof PageNumberSeparator)[keyof typeof PageNumberSeparator];
|
||||
}
|
||||
|
||||
// <xsd:complexType name="CT_PageNumber">
|
||||
@ -40,6 +44,7 @@ export class PageNumberTypeAttributes extends XmlAttributeComponent<IPageNumberT
|
||||
separator: "w:chapSep",
|
||||
};
|
||||
}
|
||||
|
||||
export class PageNumberType extends XmlComponent {
|
||||
public constructor({ start, formatType, separator }: IPageNumberTypeAttributes) {
|
||||
super("w:pgNumType");
|
||||
|
@ -7,10 +7,10 @@ import { PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
|
||||
// <xsd:enumeration value="landscape"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum PageOrientation {
|
||||
PORTRAIT = "portrait",
|
||||
LANDSCAPE = "landscape",
|
||||
}
|
||||
export const PageOrientation = {
|
||||
PORTRAIT: "portrait",
|
||||
LANDSCAPE: "landscape",
|
||||
} as const;
|
||||
|
||||
// <xsd:complexType name="CT_PageSz">
|
||||
// <xsd:attribute name="w" type="s:ST_TwipsMeasure"/>
|
||||
@ -21,11 +21,15 @@ export enum PageOrientation {
|
||||
export type IPageSizeAttributes = {
|
||||
readonly width?: number | PositiveUniversalMeasure;
|
||||
readonly height?: number | PositiveUniversalMeasure;
|
||||
readonly orientation?: PageOrientation;
|
||||
readonly orientation?: (typeof PageOrientation)[keyof typeof PageOrientation];
|
||||
};
|
||||
|
||||
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");
|
||||
|
||||
const flip = orientation === PageOrientation.LANDSCAPE;
|
||||
|
@ -1,16 +1,21 @@
|
||||
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||
|
||||
export enum PageTextDirectionType {
|
||||
LEFT_TO_RIGHT_TOP_TO_BOTTOM = "lrTb",
|
||||
TOP_TO_BOTTOM_RIGHT_TO_LEFT = "tbRl",
|
||||
}
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
export const PageTextDirectionType = {
|
||||
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" };
|
||||
}
|
||||
|
||||
export class PageTextDirection extends XmlComponent {
|
||||
public constructor(value: PageTextDirectionType) {
|
||||
public constructor(value: (typeof PageTextDirectionType)[keyof typeof PageTextDirectionType]) {
|
||||
super("w:textDirection");
|
||||
|
||||
this.root.push(
|
||||
|
@ -10,19 +10,22 @@ import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||
// <xsd:enumeration value="oddPage"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum SectionType {
|
||||
NEXT_PAGE = "nextPage",
|
||||
NEXT_COLUMN = "nextColumn",
|
||||
CONTINUOUS = "continuous",
|
||||
EVEN_PAGE = "evenPage",
|
||||
ODD_PAGE = "oddPage",
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
export const SectionType = {
|
||||
NEXT_PAGE: "nextPage",
|
||||
NEXT_COLUMN: "nextColumn",
|
||||
CONTINUOUS: "continuous",
|
||||
EVEN_PAGE: "evenPage",
|
||||
ODD_PAGE: "oddPage",
|
||||
} as const;
|
||||
/* eslint-enable */
|
||||
|
||||
// <xsd:complexType name="CT_SectType">
|
||||
// <xsd:attribute name="val" type="ST_SectionMark"/>
|
||||
// </xsd:complexType>
|
||||
export class SectionTypeAttributes extends XmlAttributeComponent<{
|
||||
readonly val: SectionType;
|
||||
readonly val: (typeof SectionType)[keyof typeof SectionType];
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
val: "w:val",
|
||||
@ -30,7 +33,7 @@ export class SectionTypeAttributes extends XmlAttributeComponent<{
|
||||
}
|
||||
|
||||
export class Type extends XmlComponent {
|
||||
public constructor(value: SectionType) {
|
||||
public constructor(value: (typeof SectionType)[keyof typeof SectionType]) {
|
||||
super("w:type");
|
||||
this.root.push(new SectionTypeAttributes({ val: value }));
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import { OnOffElement, XmlComponent } from "@file/xml-components";
|
||||
import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./properties/header-footer-reference";
|
||||
import { Columns, IColumnsAttributes } from "./properties/columns";
|
||||
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 { IPageMarginAttributes, PageMargin } from "./properties/page-margin";
|
||||
import { IPageNumberTypeAttributes, PageNumberType } from "./properties/page-number";
|
||||
@ -29,16 +29,16 @@ export interface ISectionPropertiesOptions {
|
||||
readonly margin?: IPageMarginAttributes;
|
||||
readonly pageNumbers?: IPageNumberTypeAttributes;
|
||||
readonly borders?: IPageBordersOptions;
|
||||
readonly textDirection?: PageTextDirectionType;
|
||||
readonly textDirection?: (typeof PageTextDirectionType)[keyof typeof PageTextDirectionType];
|
||||
};
|
||||
readonly grid?: IDocGridAttributesProperties;
|
||||
readonly headerWrapperGroup?: IHeaderFooterGroup<HeaderWrapper>;
|
||||
readonly footerWrapperGroup?: IHeaderFooterGroup<FooterWrapper>;
|
||||
readonly lineNumbers?: ILineNumberAttributes;
|
||||
readonly titlePage?: boolean;
|
||||
readonly verticalAlign?: VerticalAlign;
|
||||
readonly verticalAlign?: (typeof VerticalAlign)[keyof typeof VerticalAlign];
|
||||
readonly column?: IColumnsAttributes;
|
||||
readonly type?: SectionType;
|
||||
readonly type?: (typeof SectionType)[keyof typeof SectionType];
|
||||
}
|
||||
|
||||
// <xsd:complexType name="CT_SectPr">
|
||||
@ -137,7 +137,7 @@ export class SectionProperties extends XmlComponent {
|
||||
}
|
||||
|
||||
if (lineNumbers) {
|
||||
this.root.push(new LineNumberType(lineNumbers));
|
||||
this.root.push(createLineNumberType(lineNumbers));
|
||||
}
|
||||
|
||||
this.root.push(new PageNumberType(pageNumbers));
|
||||
@ -162,7 +162,7 @@ export class SectionProperties extends XmlComponent {
|
||||
}
|
||||
|
||||
private addHeaderFooterGroup(
|
||||
type: HeaderFooterType,
|
||||
type: (typeof HeaderFooterType)[keyof typeof HeaderFooterType],
|
||||
group: IHeaderFooterGroup<HeaderWrapper> | IHeaderFooterGroup<FooterWrapper>,
|
||||
): void {
|
||||
if (group.default) {
|
||||
|
@ -9,10 +9,11 @@ import { TextWrappingType } from "../text-wrap";
|
||||
import { Anchor } from "./anchor";
|
||||
|
||||
const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
||||
new Anchor(
|
||||
{
|
||||
new Anchor({
|
||||
mediaData: {
|
||||
type: "png",
|
||||
fileName: "test.png",
|
||||
stream: new Buffer(""),
|
||||
data: Buffer.from(""),
|
||||
transformation: {
|
||||
pixels: {
|
||||
x: 0,
|
||||
@ -24,7 +25,7 @@ const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
transform: {
|
||||
pixels: {
|
||||
x: 100,
|
||||
y: 100,
|
||||
@ -35,7 +36,7 @@ const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
||||
},
|
||||
},
|
||||
drawingOptions,
|
||||
);
|
||||
});
|
||||
|
||||
describe("Anchor", () => {
|
||||
let anchor: Anchor;
|
||||
|
@ -6,7 +6,7 @@ import { HorizontalPosition, IFloating, SimplePos, VerticalPosition } from "../f
|
||||
import { Graphic } from "../inline/graphic";
|
||||
import { TextWrappingType, WrapNone, WrapSquare, WrapTight, WrapTopAndBottom } from "../text-wrap";
|
||||
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 { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
||||
import { AnchorAttributes } from "./anchor-attributes";
|
||||
@ -37,7 +37,15 @@ import { AnchorAttributes } from "./anchor-attributes";
|
||||
// <xsd:attribute name="allowOverlap" type="xsd:boolean" use="required"/>
|
||||
// </xsd:complexType>
|
||||
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");
|
||||
|
||||
const floating: IFloating = {
|
||||
@ -69,7 +77,7 @@ export class Anchor extends XmlComponent {
|
||||
this.root.push(new HorizontalPosition(floating.horizontalPosition));
|
||||
this.root.push(new VerticalPosition(floating.verticalPosition));
|
||||
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) {
|
||||
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 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 =>
|
||||
new Drawing(
|
||||
{
|
||||
type: "jpg",
|
||||
fileName: "test.jpg",
|
||||
stream: Buffer.from(imageBase64Data, "base64"),
|
||||
data: Buffer.from(imageBase64Data, "base64"),
|
||||
transformation: {
|
||||
pixels: {
|
||||
x: 100,
|
||||
|
@ -4,18 +4,20 @@ import { XmlComponent } from "@file/xml-components";
|
||||
import { Anchor } from "./anchor";
|
||||
import { DocPropertiesOptions } from "./doc-properties/doc-properties";
|
||||
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 distB?: number;
|
||||
readonly distL?: number;
|
||||
readonly distR?: number;
|
||||
}
|
||||
};
|
||||
|
||||
export interface IDrawingOptions {
|
||||
readonly floating?: IFloating;
|
||||
readonly docProperties?: DocPropertiesOptions;
|
||||
readonly outline?: OutlineOptions;
|
||||
}
|
||||
|
||||
// <xsd:complexType name="CT_Drawing">
|
||||
@ -30,14 +32,16 @@ export class Drawing extends XmlComponent {
|
||||
super("w:drawing");
|
||||
|
||||
if (!drawingOptions.floating) {
|
||||
const inline = new Inline({
|
||||
this.root.push(
|
||||
createInline({
|
||||
mediaData: imageData,
|
||||
transform: imageData.transformation,
|
||||
docProperties: drawingOptions.docProperties,
|
||||
});
|
||||
this.root.push(inline);
|
||||
outline: drawingOptions.outline,
|
||||
}),
|
||||
);
|
||||
} 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 { EffectExtentAttributes } from "./effect-extent-attributes";
|
||||
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||
|
||||
export class EffectExtent extends XmlComponent {
|
||||
public constructor() {
|
||||
super("wp:effectExtent");
|
||||
export type EffectExtentAttributes = {
|
||||
readonly top: number;
|
||||
readonly right: number;
|
||||
readonly bottom: number;
|
||||
readonly left: number;
|
||||
};
|
||||
|
||||
this.root.push(
|
||||
new EffectExtentAttributes({
|
||||
b: 0,
|
||||
l: 0,
|
||||
r: 0,
|
||||
t: 0,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
// <xsd:complexType name="CT_EffectExtent">
|
||||
// <xsd:attribute name="l" type="a:ST_Coordinate" use="required"/>
|
||||
// <xsd:attribute name="t" type="a:ST_Coordinate" use="required"/>
|
||||
// <xsd:attribute name="r" type="a:ST_Coordinate" use="required"/>
|
||||
// <xsd:attribute name="b" type="a:ST_Coordinate" use="required"/>
|
||||
// </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";
|
||||
|
||||
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");
|
||||
this.root.push(value);
|
||||
}
|
||||
|
@ -4,37 +4,39 @@ import { HorizontalPositionAlign, VerticalPositionAlign } from "@file/shared/ali
|
||||
|
||||
import { ITextWrapping } from "../text-wrap";
|
||||
|
||||
export enum HorizontalPositionRelativeFrom {
|
||||
CHARACTER = "character",
|
||||
COLUMN = "column",
|
||||
INSIDE_MARGIN = "insideMargin",
|
||||
LEFT_MARGIN = "leftMargin",
|
||||
MARGIN = "margin",
|
||||
OUTSIDE_MARGIN = "outsideMargin",
|
||||
PAGE = "page",
|
||||
RIGHT_MARGIN = "rightMargin",
|
||||
}
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
export const HorizontalPositionRelativeFrom = {
|
||||
CHARACTER: "character",
|
||||
COLUMN: "column",
|
||||
INSIDE_MARGIN: "insideMargin",
|
||||
LEFT_MARGIN: "leftMargin",
|
||||
MARGIN: "margin",
|
||||
OUTSIDE_MARGIN: "outsideMargin",
|
||||
PAGE: "page",
|
||||
RIGHT_MARGIN: "rightMargin",
|
||||
} as const;
|
||||
|
||||
export enum VerticalPositionRelativeFrom {
|
||||
BOTTOM_MARGIN = "bottomMargin",
|
||||
INSIDE_MARGIN = "insideMargin",
|
||||
LINE = "line",
|
||||
MARGIN = "margin",
|
||||
OUTSIDE_MARGIN = "outsideMargin",
|
||||
PAGE = "page",
|
||||
PARAGRAPH = "paragraph",
|
||||
TOP_MARGIN = "topMargin",
|
||||
}
|
||||
export const VerticalPositionRelativeFrom = {
|
||||
BOTTOM_MARGIN: "bottomMargin",
|
||||
INSIDE_MARGIN: "insideMargin",
|
||||
LINE: "line",
|
||||
MARGIN: "margin",
|
||||
OUTSIDE_MARGIN: "outsideMargin",
|
||||
PAGE: "page",
|
||||
PARAGRAPH: "paragraph",
|
||||
TOP_MARGIN: "topMargin",
|
||||
} as const;
|
||||
|
||||
/* eslint-enable */
|
||||
export interface IHorizontalPositionOptions {
|
||||
readonly relative?: HorizontalPositionRelativeFrom;
|
||||
readonly align?: HorizontalPositionAlign;
|
||||
readonly relative?: (typeof HorizontalPositionRelativeFrom)[keyof typeof HorizontalPositionRelativeFrom];
|
||||
readonly align?: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign];
|
||||
readonly offset?: number;
|
||||
}
|
||||
|
||||
export interface IVerticalPositionOptions {
|
||||
readonly relative?: VerticalPositionRelativeFrom;
|
||||
readonly align?: VerticalPositionAlign;
|
||||
readonly relative?: (typeof VerticalPositionRelativeFrom)[keyof typeof VerticalPositionRelativeFrom];
|
||||
readonly align?: (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign];
|
||||
readonly offset?: number;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import { HorizontalPositionRelativeFrom, IHorizontalPositionOptions } from "./fl
|
||||
import { PositionOffset } from "./position-offset";
|
||||
|
||||
class HorizontalPositionAttributes extends XmlAttributeComponent<{
|
||||
readonly relativeFrom: HorizontalPositionRelativeFrom;
|
||||
readonly relativeFrom: (typeof HorizontalPositionRelativeFrom)[keyof typeof HorizontalPositionRelativeFrom];
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
relativeFrom: "relativeFrom",
|
||||
|
@ -5,7 +5,7 @@ import { IVerticalPositionOptions, VerticalPositionRelativeFrom } from "./floati
|
||||
import { PositionOffset } from "./position-offset";
|
||||
|
||||
class VerticalPositionAttributes extends XmlAttributeComponent<{
|
||||
readonly relativeFrom: VerticalPositionRelativeFrom;
|
||||
readonly relativeFrom: (typeof VerticalPositionRelativeFrom)[keyof typeof VerticalPositionRelativeFrom];
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
relativeFrom: "relativeFrom",
|
||||
|
@ -3,11 +3,20 @@ import { XmlComponent } from "@file/xml-components";
|
||||
|
||||
import { GraphicDataAttributes } from "./graphic-data-attribute";
|
||||
import { Pic } from "./pic";
|
||||
import { OutlineOptions } from "./pic/shape-properties/outline/outline";
|
||||
|
||||
export class GraphicData extends XmlComponent {
|
||||
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");
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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 { XmlComponent } from "@file/xml-components";
|
||||
|
||||
import { Blip } from "./blip";
|
||||
import { createBlip } from "./blip";
|
||||
import { SourceRectangle } from "./source-rectangle";
|
||||
import { Stretch } from "./stretch";
|
||||
|
||||
@ -9,7 +9,7 @@ export class BlipFill extends XmlComponent {
|
||||
public constructor(mediaData: IMediaData) {
|
||||
super("pic:blipFill");
|
||||
|
||||
this.root.push(new Blip(mediaData));
|
||||
this.root.push(createBlip(mediaData));
|
||||
this.root.push(new SourceRectangle());
|
||||
this.root.push(new Stretch());
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
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 cstate: string;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
embed: "r:embed",
|
||||
cstate: "cstate",
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export class Blip extends XmlComponent {
|
||||
public constructor(mediaData: IMediaData) {
|
||||
super("a:blip");
|
||||
this.root.push(
|
||||
new BlipAttributes({
|
||||
embed: `rId{${mediaData.fileName}}`,
|
||||
cstate: "none",
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
export const createBlip = (mediaData: IMediaData): XmlComponent =>
|
||||
new BuilderElement<BlipAttributes>({
|
||||
name: "a:blip",
|
||||
attributes: {
|
||||
embed: {
|
||||
key: "r:embed",
|
||||
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 { PicAttributes } from "./pic-attributes";
|
||||
import { ShapeProperties } from "./shape-properties/shape-properties";
|
||||
import { OutlineOptions } from "./shape-properties/outline/outline";
|
||||
|
||||
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");
|
||||
|
||||
this.root.push(
|
||||
@ -19,6 +28,6 @@ export class Pic extends XmlComponent {
|
||||
|
||||
this.root.push(new NonVisualPicProperties());
|
||||
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 { NoFill } from "./no-fill";
|
||||
import { createNoFill } from "./no-fill";
|
||||
|
||||
describe("NoFill", () => {
|
||||
describe("#constructor()", () => {
|
||||
it("should create", () => {
|
||||
const tree = new Formatter().format(new NoFill());
|
||||
const tree = new Formatter().format(createNoFill());
|
||||
expect(tree).to.deep.equal({
|
||||
"a:noFill": {},
|
||||
});
|
||||
|
@ -1,7 +1,3 @@
|
||||
import { XmlComponent } from "@file/xml-components";
|
||||
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||
|
||||
export class NoFill extends XmlComponent {
|
||||
public constructor() {
|
||||
super("a:noFill");
|
||||
}
|
||||
}
|
||||
export const createNoFill = (): XmlComponent => new BuilderElement({ name: "a:noFill" });
|
||||
|
@ -1,19 +1,66 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { Formatter } from "@export/formatter";
|
||||
import { Outline } from "./outline";
|
||||
|
||||
describe("Outline", () => {
|
||||
describe("#constructor()", () => {
|
||||
it("should create", () => {
|
||||
const tree = new Formatter().format(new Outline());
|
||||
import { createOutline } from "./outline";
|
||||
import { SchemeColor } from "./scheme-color";
|
||||
|
||||
describe("createOutline", () => {
|
||||
it("should create no fill", () => {
|
||||
const tree = new Formatter().format(createOutline({ type: "noFill" }));
|
||||
expect(tree).to.deep.equal({
|
||||
"a:ln": [
|
||||
{
|
||||
_attr: {},
|
||||
},
|
||||
{
|
||||
"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
|
||||
import { XmlComponent } from "@file/xml-components";
|
||||
import { NoFill } from "./no-fill";
|
||||
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||
import { createNoFill } from "./no-fill";
|
||||
import { createSolidFill } from "./solid-fill";
|
||||
import { SchemeColor } from "./scheme-color";
|
||||
|
||||
export class Outline extends XmlComponent {
|
||||
public constructor() {
|
||||
super("a:ln");
|
||||
// <xsd:complexType name="CT_TextOutlineEffect">
|
||||
// <xsd:sequence>
|
||||
// <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 { XmlComponent } from "@file/xml-components";
|
||||
import { Form } from "./form";
|
||||
// import { NoFill } from "./no-fill";
|
||||
// import { Outline } from "./outline/outline";
|
||||
import { OutlineOptions, createOutline } from "./outline/outline";
|
||||
import { PresetGeometry } from "./preset-geometry/preset-geometry";
|
||||
import { ShapePropertiesAttributes } from "./shape-properties-attributes";
|
||||
import { createNoFill } from "./outline/no-fill";
|
||||
|
||||
export class ShapeProperties extends XmlComponent {
|
||||
private readonly form: Form;
|
||||
|
||||
public constructor(transform: IMediaDataTransformation) {
|
||||
public constructor({ outline, transform }: { readonly outline?: OutlineOptions; readonly transform: IMediaDataTransformation }) {
|
||||
super("pic:spPr");
|
||||
|
||||
this.root.push(
|
||||
@ -23,7 +23,10 @@ export class ShapeProperties extends XmlComponent {
|
||||
|
||||
this.root.push(this.form);
|
||||
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 { GraphicData } from "./graphic-data";
|
||||
import { OutlineOptions } from "./graphic-data/pic/shape-properties/outline/outline";
|
||||
|
||||
class GraphicAttributes extends XmlAttributeComponent<{
|
||||
readonly a: string;
|
||||
@ -14,7 +15,15 @@ class GraphicAttributes extends XmlAttributeComponent<{
|
||||
export class Graphic extends XmlComponent {
|
||||
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");
|
||||
this.root.push(
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
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 { EffectExtent } from "./../effect-extent/effect-extent";
|
||||
import { createEffectExtent } from "./../effect-extent/effect-extent";
|
||||
import { Extent } from "./../extent/extent";
|
||||
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
||||
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 transform: IMediaDataTransformation;
|
||||
readonly docProperties?: DocPropertiesOptions;
|
||||
}
|
||||
readonly outline?: OutlineOptions;
|
||||
};
|
||||
|
||||
// <xsd:complexType name="CT_Inline">
|
||||
// <xsd:sequence>
|
||||
@ -28,29 +29,41 @@ interface InlineOptions {
|
||||
// <xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
|
||||
// <xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
|
||||
// </xsd:complexType>
|
||||
export class Inline extends XmlComponent {
|
||||
private readonly extent: Extent;
|
||||
private readonly graphic: Graphic;
|
||||
|
||||
public constructor({ mediaData, transform, docProperties }: InlineOptions) {
|
||||
super("wp:inline");
|
||||
|
||||
this.root.push(
|
||||
new InlineAttributes({
|
||||
distT: 0,
|
||||
distB: 0,
|
||||
distL: 0,
|
||||
distR: 0,
|
||||
}),
|
||||
);
|
||||
|
||||
this.extent = new Extent(transform.emus.x, transform.emus.y);
|
||||
this.graphic = new Graphic(mediaData, transform);
|
||||
|
||||
this.root.push(this.extent);
|
||||
this.root.push(new EffectExtent());
|
||||
this.root.push(new DocProperties(docProperties));
|
||||
this.root.push(new GraphicFrameProperties());
|
||||
this.root.push(this.graphic);
|
||||
export const createInline = ({ mediaData, transform, docProperties, outline }: InlineOptions): XmlComponent =>
|
||||
new BuilderElement({
|
||||
name: "wp:inline",
|
||||
attributes: {
|
||||
distanceTop: {
|
||||
key: "distT",
|
||||
value: 0,
|
||||
},
|
||||
distanceBottom: {
|
||||
key: "distB",
|
||||
value: 0,
|
||||
},
|
||||
distanceLeft: {
|
||||
key: "distL",
|
||||
value: 0,
|
||||
},
|
||||
distanceRight: {
|
||||
key: "distR",
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
children: [
|
||||
new Extent(transform.emus.x, transform.emus.y),
|
||||
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
|
||||
import { IDistance } from "../drawing";
|
||||
|
||||
export enum TextWrappingType {
|
||||
NONE,
|
||||
SQUARE,
|
||||
TIGHT,
|
||||
TOP_AND_BOTTOM,
|
||||
}
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
export const TextWrappingType = {
|
||||
NONE: 0,
|
||||
SQUARE: 1,
|
||||
TIGHT: 2,
|
||||
TOP_AND_BOTTOM: 3,
|
||||
} as const;
|
||||
|
||||
export enum TextWrappingSide {
|
||||
BOTH_SIDES = "bothSides",
|
||||
LEFT = "left",
|
||||
RIGHT = "right",
|
||||
LARGEST = "largest",
|
||||
}
|
||||
export const TextWrappingSide = {
|
||||
BOTH_SIDES: "bothSides",
|
||||
LEFT: "left",
|
||||
RIGHT: "right",
|
||||
LARGEST: "largest",
|
||||
} as const;
|
||||
|
||||
/* eslint-enable */
|
||||
|
||||
export interface ITextWrapping {
|
||||
readonly type: TextWrappingType;
|
||||
readonly side?: TextWrappingSide;
|
||||
readonly type: (typeof TextWrappingType)[keyof typeof TextWrappingType];
|
||||
readonly side?: (typeof TextWrappingSide)[keyof typeof TextWrappingSide];
|
||||
readonly margins?: IDistance;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import { IMargins } from "../floating";
|
||||
import { ITextWrapping, TextWrappingSide } from "./text-wrapping";
|
||||
|
||||
interface IWrapSquareAttributes extends IDistance {
|
||||
readonly wrapText?: TextWrappingSide;
|
||||
readonly wrapText?: (typeof TextWrappingSide)[keyof typeof TextWrappingSide];
|
||||
}
|
||||
|
||||
class WrapSquareAttributes extends XmlAttributeComponent<IWrapSquareAttributes> {
|
||||
|
@ -436,7 +436,44 @@ describe("File", () => {
|
||||
it("should work with external styles", () => {
|
||||
const doc = new File({
|
||||
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;
|
||||
|
@ -17,6 +17,7 @@ import { Styles } from "./styles";
|
||||
import { ExternalStylesFactory } from "./styles/external-styles-factory";
|
||||
import { DefaultStylesFactory } from "./styles/factory";
|
||||
import { FileChild } from "./file-child";
|
||||
import { FontWrapper } from "./fonts/font-wrapper";
|
||||
|
||||
export interface ISectionOptions {
|
||||
readonly headers?: {
|
||||
@ -53,6 +54,7 @@ export class File {
|
||||
private readonly appProperties: AppProperties;
|
||||
private readonly styles: Styles;
|
||||
private readonly comments: Comments;
|
||||
private readonly fontWrapper: FontWrapper;
|
||||
|
||||
public constructor(options: IPropertiesOptions) {
|
||||
this.coreProperties = new CoreProperties({
|
||||
@ -77,11 +79,12 @@ export class File {
|
||||
evenAndOddHeaders: options.evenAndOddHeaderAndFooters ? true : false,
|
||||
trackRevisions: options.features?.trackRevisions,
|
||||
updateFields: options.features?.updateFields,
|
||||
defaultTabStop: options.defaultTabStop,
|
||||
});
|
||||
|
||||
this.media = new Media();
|
||||
|
||||
if (options.externalStyles) {
|
||||
if (options.externalStyles !== undefined) {
|
||||
const stylesFactory = new ExternalStylesFactory();
|
||||
this.styles = stylesFactory.newInstance(options.externalStyles);
|
||||
} else if (options.styles) {
|
||||
@ -108,6 +111,8 @@ export class File {
|
||||
this.footnotesWrapper.View.createFootNote(parseFloat(key), options.footnotes[key].children);
|
||||
}
|
||||
}
|
||||
|
||||
this.fontWrapper = new FontWrapper(options.fonts ?? []);
|
||||
}
|
||||
|
||||
private addSection({ headers = {}, footers = {}, children, properties }: ISectionOptions): void {
|
||||
@ -154,7 +159,10 @@ export class File {
|
||||
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
|
||||
this.headers.push({ header, type });
|
||||
this.documentWrapper.Relationships.createRelationship(
|
||||
@ -165,7 +173,10 @@ export class File {
|
||||
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
|
||||
this.footers.push({ footer, type });
|
||||
this.documentWrapper.Relationships.createRelationship(
|
||||
@ -285,4 +296,8 @@ export class File {
|
||||
public get Comments(): 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();
|
||||
});
|
||||
});
|
@ -10,7 +10,7 @@ import { Table } from "./table";
|
||||
|
||||
export interface IDocumentFooter {
|
||||
readonly footer: FooterWrapper;
|
||||
readonly type: HeaderFooterReferenceType;
|
||||
readonly type: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType];
|
||||
}
|
||||
|
||||
export class FooterWrapper implements IViewWrapper {
|
||||
|
@ -4,14 +4,15 @@ import { XmlComponent } from "@file/xml-components";
|
||||
import { FootnoteAttributes } from "./footnote-attributes";
|
||||
import { FootnoteRefRun } from "./run/footnote-ref-run";
|
||||
|
||||
export enum FootnoteType {
|
||||
SEPERATOR = "separator",
|
||||
CONTINUATION_SEPERATOR = "continuationSeparator",
|
||||
}
|
||||
export const FootnoteType = {
|
||||
SEPERATOR: "separator",
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
CONTINUATION_SEPERATOR: "continuationSeparator",
|
||||
} as const;
|
||||
|
||||
export interface IFootnoteOptions {
|
||||
readonly id: number;
|
||||
readonly type?: FootnoteType;
|
||||
readonly type?: (typeof FootnoteType)[keyof typeof FootnoteType];
|
||||
readonly children: readonly Paragraph[];
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ import { Table } from "./table";
|
||||
|
||||
export interface IDocumentHeader {
|
||||
readonly header: HeaderWrapper;
|
||||
readonly type: HeaderFooterReferenceType;
|
||||
readonly type: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType];
|
||||
}
|
||||
|
||||
export class HeaderWrapper implements IViewWrapper {
|
||||
|
@ -1,6 +1,7 @@
|
||||
export * from "./paragraph";
|
||||
export * from "./table";
|
||||
export * from "./file";
|
||||
export * from "./file-child";
|
||||
export * from "./numbering";
|
||||
export * from "./media";
|
||||
export * from "./drawing";
|
||||
@ -18,3 +19,4 @@ export * from "./shared";
|
||||
export * from "./border";
|
||||
export * from "./vertical-align";
|
||||
export * from "./checkbox";
|
||||
export * from "./fonts";
|
||||
|
@ -14,11 +14,25 @@ export interface IMediaDataTransformation {
|
||||
readonly rotation?: number;
|
||||
}
|
||||
|
||||
export interface IMediaData {
|
||||
readonly stream: Buffer | Uint8Array | ArrayBuffer;
|
||||
type CoreMediaData = {
|
||||
readonly fileName: string;
|
||||
readonly transformation: IMediaDataTransformation;
|
||||
}
|
||||
readonly data: Buffer | Uint8Array | ArrayBuffer;
|
||||
};
|
||||
|
||||
type RegularMediaData = {
|
||||
readonly type: "jpg" | "png" | "gif" | "bmp";
|
||||
};
|
||||
|
||||
type SvgMediaData = {
|
||||
readonly type: "svg";
|
||||
/**
|
||||
* Required in case the Word processor does not support SVG.
|
||||
*/
|
||||
readonly fallback: RegularMediaData & CoreMediaData;
|
||||
};
|
||||
|
||||
export type IMediaData = (RegularMediaData | SvgMediaData) & CoreMediaData;
|
||||
|
||||
// Needed because of: https://github.com/s-panferov/awesome-typescript-loader/issues/432
|
||||
/**
|
||||
|
@ -19,7 +19,8 @@ describe("Media", () => {
|
||||
const media = new Media();
|
||||
|
||||
media.addImage("test2.png", {
|
||||
stream: Buffer.from(""),
|
||||
type: "png",
|
||||
data: Buffer.from(""),
|
||||
fileName: "test.png",
|
||||
transformation: {
|
||||
pixels: {
|
||||
|
@ -4,6 +4,7 @@ import { Formatter } from "@export/formatter";
|
||||
|
||||
import { AlignmentType, EmphasisMarkType, TabStopPosition } from "../paragraph";
|
||||
import { UnderlineType } from "../paragraph/run/underline";
|
||||
import { HighlightColor } from "../paragraph/run/properties";
|
||||
import { ShadingType } from "../shading";
|
||||
import { AbstractNumbering } from "./abstract-numbering";
|
||||
import { LevelFormat, LevelSuffix } from "./level";
|
||||
@ -2048,23 +2049,23 @@ describe("AbstractNumbering", () => {
|
||||
|
||||
const highlightTests = [
|
||||
{
|
||||
highlight: "005599",
|
||||
expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }, { "w:highlightCs": { _attr: { "w:val": "005599" } } }],
|
||||
highlight: HighlightColor.YELLOW,
|
||||
expected: [{ "w:highlight": { _attr: { "w:val": "yellow" } } }, { "w:highlightCs": { _attr: { "w:val": "yellow" } } }],
|
||||
},
|
||||
{
|
||||
highlight: "005599",
|
||||
highlight: HighlightColor.YELLOW,
|
||||
highlightComplexScript: true,
|
||||
expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }, { "w:highlightCs": { _attr: { "w:val": "005599" } } }],
|
||||
expected: [{ "w:highlight": { _attr: { "w:val": "yellow" } } }, { "w:highlightCs": { _attr: { "w:val": "yellow" } } }],
|
||||
},
|
||||
{
|
||||
highlight: "005599",
|
||||
highlight: HighlightColor.YELLOW,
|
||||
highlightComplexScript: false,
|
||||
expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }],
|
||||
expected: [{ "w:highlight": { _attr: { "w:val": "yellow" } } }],
|
||||
},
|
||||
{
|
||||
highlight: "005599",
|
||||
highlight: HighlightColor.YELLOW,
|
||||
highlightComplexScript: "550099",
|
||||
expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }, { "w:highlightCs": { _attr: { "w:val": "550099" } } }],
|
||||
expected: [{ "w:highlight": { _attr: { "w:val": "yellow" } } }, { "w:highlightCs": { _attr: { "w:val": "550099" } } }],
|
||||
},
|
||||
];
|
||||
highlightTests.forEach(({ highlight, highlightComplexScript, expected }) => {
|
||||
|
@ -75,71 +75,75 @@ import { IRunStylePropertiesOptions, RunProperties } from "../paragraph/run/prop
|
||||
// <xsd:enumeration value="custom"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum LevelFormat {
|
||||
DECIMAL = "decimal",
|
||||
UPPER_ROMAN = "upperRoman",
|
||||
LOWER_ROMAN = "lowerRoman",
|
||||
UPPER_LETTER = "upperLetter",
|
||||
LOWER_LETTER = "lowerLetter",
|
||||
ORDINAL = "ordinal",
|
||||
CARDINAL_TEXT = "cardinalText",
|
||||
ORDINAL_TEXT = "ordinalText",
|
||||
HEX = "hex",
|
||||
CHICAGO = "chicago",
|
||||
IDEOGRAPH__DIGITAL = "ideographDigital",
|
||||
JAPANESE_COUNTING = "japaneseCounting",
|
||||
AIUEO = "aiueo",
|
||||
IROHA = "iroha",
|
||||
DECIMAL_FULL_WIDTH = "decimalFullWidth",
|
||||
DECIMAL_HALF_WIDTH = "decimalHalfWidth",
|
||||
JAPANESE_LEGAL = "japaneseLegal",
|
||||
JAPANESE_DIGITAL_TEN_THOUSAND = "japaneseDigitalTenThousand",
|
||||
DECIMAL_ENCLOSED_CIRCLE = "decimalEnclosedCircle",
|
||||
DECIMAL_FULL_WIDTH2 = "decimalFullWidth2",
|
||||
AIUEO_FULL_WIDTH = "aiueoFullWidth",
|
||||
IROHA_FULL_WIDTH = "irohaFullWidth",
|
||||
DECIMAL_ZERO = "decimalZero",
|
||||
BULLET = "bullet",
|
||||
GANADA = "ganada",
|
||||
CHOSUNG = "chosung",
|
||||
DECIMAL_ENCLOSED_FULLSTOP = "decimalEnclosedFullstop",
|
||||
DECIMAL_ENCLOSED_PARENTHESES = "decimalEnclosedParen",
|
||||
DECIMAL_ENCLOSED_CIRCLE_CHINESE = "decimalEnclosedCircleChinese",
|
||||
IDEOGRAPH_ENCLOSED_CIRCLE = "ideographEnclosedCircle",
|
||||
IDEOGRAPH_TRADITIONAL = "ideographTraditional",
|
||||
IDEOGRAPH_ZODIAC = "ideographZodiac",
|
||||
IDEOGRAPH_ZODIAC_TRADITIONAL = "ideographZodiacTraditional",
|
||||
TAIWANESE_COUNTING = "taiwaneseCounting",
|
||||
IDEOGRAPH_LEGAL_TRADITIONAL = "ideographLegalTraditional",
|
||||
TAIWANESE_COUNTING_THOUSAND = "taiwaneseCountingThousand",
|
||||
TAIWANESE_DIGITAL = "taiwaneseDigital",
|
||||
CHINESE_COUNTING = "chineseCounting",
|
||||
CHINESE_LEGAL_SIMPLIFIED = "chineseLegalSimplified",
|
||||
CHINESE_COUNTING_THOUSAND = "chineseCountingThousand",
|
||||
KOREAN_DIGITAL = "koreanDigital",
|
||||
KOREAN_COUNTING = "koreanCounting",
|
||||
KOREAN_LEGAL = "koreanLegal",
|
||||
KOREAN_DIGITAL2 = "koreanDigital2",
|
||||
VIETNAMESE_COUNTING = "vietnameseCounting",
|
||||
RUSSIAN_LOWER = "russianLower",
|
||||
RUSSIAN_UPPER = "russianUpper",
|
||||
NONE = "none",
|
||||
NUMBER_IN_DASH = "numberInDash",
|
||||
HEBREW1 = "hebrew1",
|
||||
HEBREW2 = "hebrew2",
|
||||
ARABIC_ALPHA = "arabicAlpha",
|
||||
ARABIC_ABJAD = "arabicAbjad",
|
||||
HINDI_VOWELS = "hindiVowels",
|
||||
HINDI_CONSONANTS = "hindiConsonants",
|
||||
HINDI_NUMBERS = "hindiNumbers",
|
||||
HINDI_COUNTING = "hindiCounting",
|
||||
THAI_LETTERS = "thaiLetters",
|
||||
THAI_NUMBERS = "thaiNumbers",
|
||||
THAI_COUNTING = "thaiCounting",
|
||||
BAHT_TEXT = "bahtText",
|
||||
DOLLAR_TEXT = "dollarText",
|
||||
CUSTOM = "custom",
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
export const LevelFormat = {
|
||||
DECIMAL: "decimal",
|
||||
UPPER_ROMAN: "upperRoman",
|
||||
LOWER_ROMAN: "lowerRoman",
|
||||
UPPER_LETTER: "upperLetter",
|
||||
LOWER_LETTER: "lowerLetter",
|
||||
ORDINAL: "ordinal",
|
||||
CARDINAL_TEXT: "cardinalText",
|
||||
ORDINAL_TEXT: "ordinalText",
|
||||
HEX: "hex",
|
||||
CHICAGO: "chicago",
|
||||
IDEOGRAPH__DIGITAL: "ideographDigital",
|
||||
JAPANESE_COUNTING: "japaneseCounting",
|
||||
AIUEO: "aiueo",
|
||||
IROHA: "iroha",
|
||||
DECIMAL_FULL_WIDTH: "decimalFullWidth",
|
||||
DECIMAL_HALF_WIDTH: "decimalHalfWidth",
|
||||
JAPANESE_LEGAL: "japaneseLegal",
|
||||
JAPANESE_DIGITAL_TEN_THOUSAND: "japaneseDigitalTenThousand",
|
||||
DECIMAL_ENCLOSED_CIRCLE: "decimalEnclosedCircle",
|
||||
DECIMAL_FULL_WIDTH2: "decimalFullWidth2",
|
||||
AIUEO_FULL_WIDTH: "aiueoFullWidth",
|
||||
IROHA_FULL_WIDTH: "irohaFullWidth",
|
||||
DECIMAL_ZERO: "decimalZero",
|
||||
BULLET: "bullet",
|
||||
GANADA: "ganada",
|
||||
CHOSUNG: "chosung",
|
||||
DECIMAL_ENCLOSED_FULLSTOP: "decimalEnclosedFullstop",
|
||||
DECIMAL_ENCLOSED_PARENTHESES: "decimalEnclosedParen",
|
||||
DECIMAL_ENCLOSED_CIRCLE_CHINESE: "decimalEnclosedCircleChinese",
|
||||
IDEOGRAPH_ENCLOSED_CIRCLE: "ideographEnclosedCircle",
|
||||
IDEOGRAPH_TRADITIONAL: "ideographTraditional",
|
||||
IDEOGRAPH_ZODIAC: "ideographZodiac",
|
||||
IDEOGRAPH_ZODIAC_TRADITIONAL: "ideographZodiacTraditional",
|
||||
TAIWANESE_COUNTING: "taiwaneseCounting",
|
||||
IDEOGRAPH_LEGAL_TRADITIONAL: "ideographLegalTraditional",
|
||||
TAIWANESE_COUNTING_THOUSAND: "taiwaneseCountingThousand",
|
||||
TAIWANESE_DIGITAL: "taiwaneseDigital",
|
||||
CHINESE_COUNTING: "chineseCounting",
|
||||
CHINESE_LEGAL_SIMPLIFIED: "chineseLegalSimplified",
|
||||
CHINESE_COUNTING_THOUSAND: "chineseCountingThousand",
|
||||
KOREAN_DIGITAL: "koreanDigital",
|
||||
KOREAN_COUNTING: "koreanCounting",
|
||||
KOREAN_LEGAL: "koreanLegal",
|
||||
KOREAN_DIGITAL2: "koreanDigital2",
|
||||
VIETNAMESE_COUNTING: "vietnameseCounting",
|
||||
RUSSIAN_LOWER: "russianLower",
|
||||
RUSSIAN_UPPER: "russianUpper",
|
||||
NONE: "none",
|
||||
NUMBER_IN_DASH: "numberInDash",
|
||||
HEBREW1: "hebrew1",
|
||||
HEBREW2: "hebrew2",
|
||||
ARABIC_ALPHA: "arabicAlpha",
|
||||
ARABIC_ABJAD: "arabicAbjad",
|
||||
HINDI_VOWELS: "hindiVowels",
|
||||
HINDI_CONSONANTS: "hindiConsonants",
|
||||
HINDI_NUMBERS: "hindiNumbers",
|
||||
HINDI_COUNTING: "hindiCounting",
|
||||
THAI_LETTERS: "thaiLetters",
|
||||
THAI_NUMBERS: "thaiNumbers",
|
||||
THAI_COUNTING: "thaiCounting",
|
||||
BAHT_TEXT: "bahtText",
|
||||
DOLLAR_TEXT: "dollarText",
|
||||
CUSTOM: "custom",
|
||||
} as const;
|
||||
|
||||
/* eslint-enable */
|
||||
|
||||
class LevelAttributes extends XmlAttributeComponent<{
|
||||
readonly ilvl?: number;
|
||||
@ -182,7 +186,7 @@ class LevelText extends XmlComponent {
|
||||
}
|
||||
|
||||
class LevelJc extends XmlComponent {
|
||||
public constructor(value: AlignmentType) {
|
||||
public constructor(value: (typeof AlignmentType)[keyof typeof AlignmentType]) {
|
||||
super("w:lvlJc");
|
||||
this.root.push(
|
||||
new Attributes({
|
||||
@ -192,19 +196,19 @@ class LevelJc extends XmlComponent {
|
||||
}
|
||||
}
|
||||
|
||||
export enum LevelSuffix {
|
||||
NOTHING = "nothing",
|
||||
SPACE = "space",
|
||||
TAB = "tab",
|
||||
}
|
||||
export const LevelSuffix = {
|
||||
NOTHING: "nothing",
|
||||
SPACE: "space",
|
||||
TAB: "tab",
|
||||
} as const;
|
||||
|
||||
export interface ILevelsOptions {
|
||||
readonly level: number;
|
||||
readonly format?: LevelFormat;
|
||||
readonly format?: (typeof LevelFormat)[keyof typeof LevelFormat];
|
||||
readonly text?: string;
|
||||
readonly alignment?: AlignmentType;
|
||||
readonly alignment?: (typeof AlignmentType)[keyof typeof AlignmentType];
|
||||
readonly start?: number;
|
||||
readonly suffix?: LevelSuffix;
|
||||
readonly suffix?: (typeof LevelSuffix)[keyof typeof LevelSuffix];
|
||||
readonly isLegalNumberingStyle?: boolean;
|
||||
readonly style?: {
|
||||
readonly run?: IRunStylePropertiesOptions;
|
||||
@ -223,7 +227,7 @@ export interface ILevelsOptions {
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
class Suffix extends XmlComponent {
|
||||
public constructor(value: LevelSuffix) {
|
||||
public constructor(value: (typeof LevelSuffix)[keyof typeof LevelSuffix]) {
|
||||
super("w:suff");
|
||||
this.root.push(
|
||||
new Attributes({
|
||||
|
@ -19,41 +19,47 @@ import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||
// <xsd:enumeration value="right"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum AlignmentType {
|
||||
/** Align Start */
|
||||
START = "start",
|
||||
/** Align Center */
|
||||
CENTER = "center",
|
||||
/** End */
|
||||
END = "end",
|
||||
/** Justified */
|
||||
BOTH = "both",
|
||||
/** Medium Kashida Length */
|
||||
MEDIUM_KASHIDA = "mediumKashida",
|
||||
/** Distribute All Characters Equally */
|
||||
DISTRIBUTE = "distribute",
|
||||
/** Align to List Tab */
|
||||
NUM_TAB = "numTab",
|
||||
/** Widest Kashida Length */
|
||||
HIGH_KASHIDA = "highKashida",
|
||||
/** Low Kashida Length */
|
||||
LOW_KASHIDA = "lowKashida",
|
||||
/** Thai Language Justification */
|
||||
THAI_DISTRIBUTE = "thaiDistribute",
|
||||
/** Align Left */
|
||||
LEFT = "left",
|
||||
/** Align Right */
|
||||
RIGHT = "right",
|
||||
/** Justified */
|
||||
JUSTIFIED = "both",
|
||||
}
|
||||
|
||||
export class AlignmentAttributes extends XmlAttributeComponent<{ readonly val: AlignmentType }> {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
export const AlignmentType = {
|
||||
/** Align Start */
|
||||
START: "start",
|
||||
/** Align Center */
|
||||
CENTER: "center",
|
||||
/** End */
|
||||
END: "end",
|
||||
/** Justified */
|
||||
BOTH: "both",
|
||||
/** Medium Kashida Length */
|
||||
MEDIUM_KASHIDA: "mediumKashida",
|
||||
/** Distribute All Characters Equally */
|
||||
DISTRIBUTE: "distribute",
|
||||
/** Align to List Tab */
|
||||
NUM_TAB: "numTab",
|
||||
/** Widest Kashida Length */
|
||||
HIGH_KASHIDA: "highKashida",
|
||||
/** Low Kashida Length */
|
||||
LOW_KASHIDA: "lowKashida",
|
||||
/** Thai Language Justification */
|
||||
THAI_DISTRIBUTE: "thaiDistribute",
|
||||
/** Align Left */
|
||||
LEFT: "left",
|
||||
/** Align Right */
|
||||
RIGHT: "right",
|
||||
/** Justified */
|
||||
JUSTIFIED: "both",
|
||||
} as const;
|
||||
|
||||
/* eslint-enable */
|
||||
|
||||
export class AlignmentAttributes extends XmlAttributeComponent<{
|
||||
readonly val: (typeof AlignmentType)[keyof typeof AlignmentType];
|
||||
}> {
|
||||
protected readonly xmlKeys = { val: "w:val" };
|
||||
}
|
||||
|
||||
export class Alignment extends XmlComponent {
|
||||
public constructor(type: AlignmentType) {
|
||||
public constructor(type: (typeof AlignmentType)[keyof typeof AlignmentType]) {
|
||||
super("w:jc");
|
||||
this.root.push(new AlignmentAttributes({ val: type }));
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user