Compare commits
32 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 |
@ -21,6 +21,7 @@
|
|||||||
"iife",
|
"iife",
|
||||||
"Initializable",
|
"Initializable",
|
||||||
"iroha",
|
"iroha",
|
||||||
|
"JOHAB",
|
||||||
"jsonify",
|
"jsonify",
|
||||||
"jszip",
|
"jszip",
|
||||||
"NUMPAGES",
|
"NUMPAGES",
|
||||||
@ -54,7 +55,8 @@
|
|||||||
"\\.to\\.include\\.members\\(\\[[^\\]]+]\\)",
|
"\\.to\\.include\\.members\\(\\[[^\\]]+]\\)",
|
||||||
"/new [a-zA-Z]+\\({[^£]+}\\)/g",
|
"/new [a-zA-Z]+\\({[^£]+}\\)/g",
|
||||||
"/<element name=\"[a-z]+\"/gi",
|
"/<element name=\"[a-z]+\"/gi",
|
||||||
"/<attribute name=\"[a-z]+\"/gi"
|
"/<attribute name=\"[a-z]+\"/gi",
|
||||||
|
"/key: \".+\"/"
|
||||||
],
|
],
|
||||||
"ignorePaths": ["package.json", "docs/api", "*.docx", "build"],
|
"ignorePaths": ["package.json", "docs/api", "*.docx", "build"],
|
||||||
"allowCompoundWords": true,
|
"allowCompoundWords": true,
|
||||||
|
@ -92,6 +92,7 @@ rules:
|
|||||||
format:
|
format:
|
||||||
- camelCase
|
- camelCase
|
||||||
- PascalCase
|
- PascalCase
|
||||||
|
- UPPER_CASE # for constants
|
||||||
filter:
|
filter:
|
||||||
regex: (^[a-z]+:.+)|_attr|[0-9]
|
regex: (^[a-z]+:.+)|_attr|[0-9]
|
||||||
match: false
|
match: false
|
||||||
|
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:
|
steps:
|
||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Install Dependencies
|
- uses: "./.github/actions/install-and-build"
|
||||||
run: npm ci --force
|
|
||||||
- name: Build
|
|
||||||
run: npm run build
|
|
||||||
- name: Archive Production Artifact
|
- name: Archive Production Artifact
|
||||||
uses: actions/upload-artifact@master
|
uses: actions/upload-artifact@master
|
||||||
with:
|
with:
|
||||||
@ -32,7 +29,7 @@ jobs:
|
|||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci --force
|
run: npm ci --force
|
||||||
- name: Test
|
- name: Test
|
||||||
run: npm run test.ci
|
run: npm run test:ci
|
||||||
- name: Codecov
|
- name: Codecov
|
||||||
uses: codecov/codecov-action@v3
|
uses: codecov/codecov-action@v3
|
||||||
with:
|
with:
|
||||||
@ -57,7 +54,7 @@ jobs:
|
|||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci --force
|
run: npm ci --force
|
||||||
- name: Prettier
|
- name: Prettier
|
||||||
run: npm run style
|
run: npm run prettier
|
||||||
cspell:
|
cspell:
|
||||||
name: CSpell
|
name: CSpell
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
939
.github/workflows/demos.yml
vendored
939
.github/workflows/demos.yml
vendored
@ -8,792 +8,189 @@ on:
|
|||||||
- master
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
|
||||||
name: Build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repo
|
|
||||||
uses: actions/checkout@master
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: npm ci --force
|
|
||||||
- name: Build
|
|
||||||
run: npm run build
|
|
||||||
- name: Archive Production Artifact
|
|
||||||
uses: actions/upload-artifact@master
|
|
||||||
with:
|
|
||||||
name: build
|
|
||||||
path: build
|
|
||||||
demos:
|
demos:
|
||||||
name: Run Demos and Validate
|
name: Demos
|
||||||
needs: [build]
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repo
|
- uses: actions/checkout@master
|
||||||
uses: actions/checkout@master
|
- uses: "./.github/actions/install-and-build"
|
||||||
- name: Install Dependencies
|
- name: Run Demos
|
||||||
run: npm ci --force
|
|
||||||
- name: Download Artifact
|
|
||||||
uses: actions/download-artifact@master
|
|
||||||
with:
|
|
||||||
name: build
|
|
||||||
path: build
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run run-ts -- ./demo/1-basic.ts
|
run: npm run run-ts -- ./demo/1-basic.ts
|
||||||
- name: Extract Word Document
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run extract
|
- run: npm run run-ts -- ./demo/2-declaritive-styles.ts
|
||||||
- name: Validate XML
|
- uses: "./.github/actions/validate-docx"
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/3-numbering-and-bullet-points.ts
|
||||||
with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/4-basic-table.ts
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/5-images.ts
|
||||||
run: npm run run-ts -- ./demo/2-declaritive-styles.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/6-page-borders.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/7-landscape.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/8-header-footer.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- run: npm run run-ts -- ./demo/9-images-in-header-and-footer.ts
|
||||||
- name: Run Demo
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run run-ts -- ./demo/3-numbering-and-bullet-points.ts
|
- run: npm run run-ts -- ./demo/10-my-cv.ts
|
||||||
- name: Extract Word Document
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run extract
|
- run: npm run run-ts -- ./demo/11-declaritive-styles-2.ts
|
||||||
- name: Validate XML
|
- uses: "./.github/actions/validate-docx"
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/12-scaling-images.ts
|
||||||
with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/13-xml-styles.ts
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/14-page-numbers.ts
|
||||||
run: npm run run-ts -- ./demo/4-basic-table.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/15-page-break-before.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/16-multiple-sections.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/17-footnotes.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./demo/17-footnotes.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
# element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected.
|
# element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected.
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/18-image-from-buffer.ts
|
||||||
# with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/19-export-to-base64.ts
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run run-ts -- ./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 run-ts -- ./demo/19-export-to-base64.ts
|
|
||||||
# Base 64 No longer works, abruptly. Node issue?
|
# Base 64 No longer works, abruptly. Node issue?
|
||||||
# - name: Extract Word Document
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# run: npm run extract
|
- run: npm run run-ts -- ./demo/20-table-cell-borders.ts
|
||||||
# - name: Validate XML
|
- uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/21-bookmarks.ts
|
||||||
# with:
|
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run run-ts -- ./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 run-ts -- ./demo/21-bookmarks.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
# Bad ID - need numeric ID
|
# Bad ID - need numeric ID
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/22-right-to-left-text.ts
|
||||||
# with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/23-base64-images.ts
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/24-images-to-table-cell.ts
|
||||||
run: npm run run-ts -- ./demo/22-right-to-left-text.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/25-table-xml-styles.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/26-paragraph-borders.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/27-declaritive-styles-3.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- run: npm run run-ts -- ./demo/28-table-of-contents.ts
|
||||||
- name: Run Demo
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run run-ts -- ./demo/23-base64-images.ts
|
- run: npm run run-ts -- ./demo/29-numbered-lists.ts
|
||||||
- name: Extract Word Document
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run extract
|
- run: npm run run-ts -- ./demo/31-tables.ts
|
||||||
- name: Validate XML
|
- uses: "./.github/actions/validate-docx"
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/32-merge-and-shade-table-cells.ts
|
||||||
with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/33-sequential-captions.ts
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/34-floating-tables.ts
|
||||||
run: npm run run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./demo/34-floating-tables.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
# element tblpPr: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tblpPr', attribute 'overlap': The attribute 'overlap' is not allowed.
|
# element tblpPr: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tblpPr', attribute 'overlap': The attribute 'overlap' is not allowed.
|
||||||
# element tblpPr: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tblpPr': Element content is not allowed, because the content type is empty.
|
# element tblpPr: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tblpPr': Element content is not allowed, because the content type is empty.
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/35-hyperlinks.ts
|
||||||
# with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/36-image-to-table-cell.ts
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/37-images-to-header-and-footer.ts
|
||||||
run: npm run run-ts -- ./demo/35-hyperlinks.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/38-text-wrapping.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/39-page-numbers.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/40-line-numbers.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- run: npm run run-ts -- ./demo/41-merge-table-cells-2.ts
|
||||||
- name: Run Demo
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run run-ts -- ./demo/36-image-to-table-cell.ts
|
- run: npm run run-ts -- ./demo/42-restart-page-numbers.ts
|
||||||
- name: Extract Word Document
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run extract
|
- run: npm run run-ts -- ./demo/43-images-to-table-cell-2.ts
|
||||||
- name: Validate XML
|
- uses: "./.github/actions/validate-docx"
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/44-multiple-columns.ts
|
||||||
with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/45-highlighting-text.ts
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/46-shading-text.ts
|
||||||
run: npm run run-ts -- ./demo/37-images-to-header-and-footer.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/47-number-of-total-pages-section.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/48-vertical-align.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/49-table-borders.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- run: npm run run-ts -- ./demo/50-readme-demo.ts
|
||||||
- name: Run Demo
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run run-ts -- ./demo/38-text-wrapping.ts
|
- run: npm run run-ts -- ./demo/51-character-styles.ts
|
||||||
- name: Extract Word Document
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run extract
|
- run: npm run run-ts -- ./demo/52-japanese.ts
|
||||||
- name: Validate XML
|
- uses: "./.github/actions/validate-docx"
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/53-chinese.ts
|
||||||
with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/54-custom-properties.ts
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/55-math.ts
|
||||||
run: npm run run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./demo/55-math.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
#: element subHide: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}subHide': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}ctrlPr ).
|
#: element subHide: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}subHide': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}ctrlPr ).
|
||||||
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sub ).
|
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sub ).
|
||||||
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sup ).
|
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sup ).
|
||||||
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sub ).
|
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sub ).
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/56-background-color.ts
|
||||||
# with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/57-add-parent-numbered-lists.ts
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/58-section-types.ts
|
||||||
run: npm run run-ts -- ./demo/56-background-color.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/59-header-footer-margins.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/60-track-revisions.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./demo/60-track-revisions.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
# element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected.
|
# element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected.
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/61-text-frame.ts
|
||||||
# with:
|
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run run-ts -- ./demo/61-text-frame.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
# element left: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}left': This element is not expected. Expected is one of ( {http://schemas.openxmlformats.org/wordprocessingml/2006/main}right, {http://schemas.openxmlformats.org/wordprocessingml/2006/main}between, {http://schemas.openxmlformats.org/wordprocessingml/2006/main}bar ).
|
# element left: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}left': This element is not expected. Expected is one of ( {http://schemas.openxmlformats.org/wordprocessingml/2006/main}right, {http://schemas.openxmlformats.org/wordprocessingml/2006/main}between, {http://schemas.openxmlformats.org/wordprocessingml/2006/main}bar ).
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/62-paragraph-spacing.ts
|
||||||
# with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/63-odd-even-header-footer.ts
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/64-complex-numbering-text.ts
|
||||||
run: npm run run-ts -- ./demo/62-paragraph-spacing.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/65-page-sizes.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/66-fields.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
|
||||||
with:
|
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
|
||||||
- name: Run Demo
|
|
||||||
run: npm run run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./demo/66-fields.ts
|
|
||||||
- name: Extract Word Document
|
|
||||||
run: npm run extract
|
|
||||||
# element bookmarkStart: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}bookmarkStart', attribute '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}id': '-irrswq-ln94j4fdgdjxs' is not a valid value of the atomic type '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ST_DecimalNumber'.
|
# element bookmarkStart: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}bookmarkStart', attribute '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}id': '-irrswq-ln94j4fdgdjxs' is not a valid value of the atomic type '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ST_DecimalNumber'.
|
||||||
# element bookmarkEnd: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}bookmarkEnd', attribute '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}id': '-irrswq-ln94j4fdgdjxs' is not a valid value of the atomic type '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ST_DecimalNumber'.
|
# element bookmarkEnd: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}bookmarkEnd', attribute '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}id': '-irrswq-ln94j4fdgdjxs' is not a valid value of the atomic type '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ST_DecimalNumber'.
|
||||||
# - name: Validate XML
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/67-column-break.ts
|
||||||
# with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/68-numbering-instances-and-starting-number.ts
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/69-different-width-columns.ts
|
||||||
run: npm run run-ts -- ./demo/67-column-break.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/70-line-numbers-suppression.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/71-page-borders-2.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/72-word-wrap.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- run: npm run run-ts -- ./demo/73-comments.ts
|
||||||
- name: Run Demo
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run run-ts -- ./demo/68-numbering-instances-and-starting-number.ts
|
- run: npm run run-ts -- ./demo/74-nodejs-stream.ts
|
||||||
- name: Extract Word Document
|
# - uses: "./.github/actions/validate-docx"
|
||||||
run: npm run extract
|
|
||||||
- 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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./demo/75-tab-stops.ts
|
# run: npm run run-ts -- ./demo/75-tab-stops.ts
|
||||||
# - name: Extract Word Document
|
# - uses: "./.github/actions/validate-docx"
|
||||||
# run: npm run extract
|
- run: npm run run-ts -- ./demo/76-compatibility.ts
|
||||||
# - name: Validate XML
|
- uses: "./.github/actions/validate-docx"
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
- run: npm run run-ts -- ./demo/77-side-by-side-tables.ts
|
||||||
# with:
|
- uses: "./.github/actions/validate-docx"
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
- run: npm run run-ts -- ./demo/78-thai-distributed.ts
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Run Demo
|
- run: npm run run-ts -- ./demo/79-table-from-data-source.ts
|
||||||
run: npm run run-ts -- ./demo/76-compatibility.ts
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Extract Word Document
|
- run: npm run run-ts -- ./demo/80-thai-distributed.ts
|
||||||
run: npm run extract
|
- uses: "./.github/actions/validate-docx"
|
||||||
- name: Validate XML
|
- run: npm run run-ts -- ./demo/81-continuous-header.ts
|
||||||
uses: ChristophWurst/xmllint-action@v1
|
- uses: "./.github/actions/validate-docx"
|
||||||
with:
|
- run: npm run run-ts -- ./demo/82-new-headers-new-section.ts
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
- uses: "./.github/actions/validate-docx"
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
- run: npm run run-ts -- ./demo/83-setting-languages.ts
|
||||||
- name: Run Demo
|
- uses: "./.github/actions/validate-docx"
|
||||||
run: npm run run-ts -- ./demo/77-side-by-side-tables.ts
|
- run: npm run run-ts -- ./demo/84-positional-tabs.ts
|
||||||
- name: Extract Word Document
|
- uses: "./.github/actions/validate-docx"
|
||||||
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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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 run-ts -- ./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
|
|
||||||
|
@ -45,7 +45,7 @@ const doc = new Document({
|
|||||||
children: [
|
children: [
|
||||||
new TextRun("My Title "),
|
new TextRun("My Title "),
|
||||||
new TextRun({
|
new TextRun({
|
||||||
children: ["Footer - Page ", PageNumber.CURRENT],
|
children: ["Footer - Page ", PageNumber.CURRENT, " of ", PageNumber.TOTAL_PAGES],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import {
|
import {
|
||||||
|
convertMillimetersToTwip,
|
||||||
Document,
|
Document,
|
||||||
HorizontalPositionAlign,
|
HorizontalPositionAlign,
|
||||||
HorizontalPositionRelativeFrom,
|
HorizontalPositionRelativeFrom,
|
||||||
@ -41,6 +42,11 @@ const doc = new Document({
|
|||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
},
|
},
|
||||||
|
outline: {
|
||||||
|
type: "solidFill",
|
||||||
|
solidFillType: "rgb",
|
||||||
|
value: "FF0000",
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
@ -55,6 +61,12 @@ const doc = new Document({
|
|||||||
vertical: true,
|
vertical: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
outline: {
|
||||||
|
type: "solidFill",
|
||||||
|
solidFillType: "rgb",
|
||||||
|
value: "0000FF",
|
||||||
|
width: convertMillimetersToTwip(600),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import {
|
import {
|
||||||
|
AlignmentType,
|
||||||
BorderStyle,
|
BorderStyle,
|
||||||
Document,
|
Document,
|
||||||
FrameAnchorType,
|
FrameAnchorType,
|
||||||
@ -20,6 +21,7 @@ const doc = new Document({
|
|||||||
children: [
|
children: [
|
||||||
new Paragraph({
|
new Paragraph({
|
||||||
frame: {
|
frame: {
|
||||||
|
type: "absolute",
|
||||||
position: {
|
position: {
|
||||||
x: 1000,
|
x: 1000,
|
||||||
y: 3000,
|
y: 3000,
|
||||||
@ -30,6 +32,54 @@ const doc = new Document({
|
|||||||
horizontal: FrameAnchorType.MARGIN,
|
horizontal: FrameAnchorType.MARGIN,
|
||||||
vertical: FrameAnchorType.MARGIN,
|
vertical: FrameAnchorType.MARGIN,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
top: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
bottom: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
left: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
new TextRun("Hello World"),
|
||||||
|
new TextRun({
|
||||||
|
text: "Foo Bar",
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
children: [new Tab(), "Github is the best"],
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
frame: {
|
||||||
|
type: "alignment",
|
||||||
|
width: 4000,
|
||||||
|
height: 1000,
|
||||||
|
anchor: {
|
||||||
|
horizontal: FrameAnchorType.MARGIN,
|
||||||
|
vertical: FrameAnchorType.MARGIN,
|
||||||
|
},
|
||||||
alignment: {
|
alignment: {
|
||||||
x: HorizontalPositionAlign.CENTER,
|
x: HorizontalPositionAlign.CENTER,
|
||||||
y: VerticalPositionAlign.TOP,
|
y: VerticalPositionAlign.TOP,
|
||||||
@ -73,6 +123,59 @@ const doc = new Document({
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
frame: {
|
||||||
|
type: "alignment",
|
||||||
|
width: 4000,
|
||||||
|
height: 1000,
|
||||||
|
anchor: {
|
||||||
|
horizontal: FrameAnchorType.MARGIN,
|
||||||
|
vertical: FrameAnchorType.MARGIN,
|
||||||
|
},
|
||||||
|
alignment: {
|
||||||
|
x: HorizontalPositionAlign.CENTER,
|
||||||
|
y: VerticalPositionAlign.BOTTOM,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
top: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
bottom: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
left: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
color: "auto",
|
||||||
|
space: 1,
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 6,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
alignment: AlignmentType.RIGHT,
|
||||||
|
children: [
|
||||||
|
new TextRun("Hello World"),
|
||||||
|
new TextRun({
|
||||||
|
text: "Foo Bar",
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
children: [new Tab(), "Github is the best"],
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -107,5 +107,5 @@ const doc = new Document({
|
|||||||
|
|
||||||
// Used to export the file into a .docx file
|
// Used to export the file into a .docx file
|
||||||
Packer.toBuffer(doc).then((buffer) => {
|
Packer.toBuffer(doc).then((buffer) => {
|
||||||
fs.writeFileSync("6-numbering.docx", buffer);
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
});
|
});
|
||||||
|
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.
10
demo/tsconfig.json
Normal file
10
demo/tsconfig.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDir": "./",
|
||||||
|
"paths": {
|
||||||
|
"docx": ["../build"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["../demo"]
|
||||||
|
}
|
4990
package-lock.json
generated
4990
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "docx",
|
"name": "docx",
|
||||||
"version": "8.4.0",
|
"version": "8.5.0",
|
||||||
"description": "Easily generate .docx files with JS/TS with a nice declarative API. Works for Node and on the Browser.",
|
"description": "Easily generate .docx files with JS/TS with a nice declarative API. Works for Node and on the Browser.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "build/index.umd.js",
|
"main": "build/index.umd.js",
|
||||||
@ -20,21 +20,21 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build",
|
||||||
"test": "vitest --ui --coverage",
|
"test": "vitest --ui --coverage",
|
||||||
"test.ci": "vitest run --coverage",
|
"test:ci": "vitest run --coverage",
|
||||||
"prepublishOnly": "npm run build --omit=dev",
|
"prepublishOnly": "npm run build --omit=dev",
|
||||||
"lint": "eslint --ext .ts src",
|
"lint": "eslint --ext .ts src",
|
||||||
"predemo": "npm run build",
|
"predemo": "npm run build",
|
||||||
"demo": "tsx ./demo/index.ts",
|
"demo": "tsx ./demo/index.ts",
|
||||||
"typedoc": "typedoc src/index.ts --tsconfig tsconfig.typedoc.json",
|
"typedoc": "typedoc src/index.ts --tsconfig tsconfig.typedoc.json",
|
||||||
"style": "prettier -l \"{src,scripts,demo}/**/*.{ts,html}\"",
|
"prettier": "prettier -l \"{src,scripts,demo}/**/*.{ts,html}\"",
|
||||||
"style.fix": "npm run style -- --write",
|
"prettier:fix": "npm run prettier -- --write",
|
||||||
"cspell": "cspell \"{src,demo,docs,scripts}/**/*.{ts,scss,html,md}\" && cspell \"./*.*\"",
|
"cspell": "cspell \"{src,demo,docs,scripts}/**/*.{ts,scss,html,md}\" && cspell \"./*.*\"",
|
||||||
"serve.docs": "cd docs && docsify serve",
|
"serve.docs": "cd docs && docsify serve",
|
||||||
"extract": "tsx scripts/extract-document.ts",
|
"extract": "tsx scripts/extract-document.ts",
|
||||||
"run-ts": "tsx"
|
"run-ts": "tsx"
|
||||||
},
|
},
|
||||||
"pre-commit": [
|
"pre-commit": [
|
||||||
"style",
|
"prettier",
|
||||||
"lint"
|
"lint"
|
||||||
],
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -73,9 +73,9 @@
|
|||||||
"@types/xml": "^1.0.8",
|
"@types/xml": "^1.0.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.9.1",
|
"@typescript-eslint/eslint-plugin": "^6.9.1",
|
||||||
"@typescript-eslint/parser": "^6.9.1",
|
"@typescript-eslint/parser": "^6.9.1",
|
||||||
"@vitest/coverage-v8": "^0.34.6",
|
"@vitest/coverage-v8": "^1.1.0",
|
||||||
"@vitest/ui": "^0.33.0",
|
"@vitest/ui": "^1.1.0",
|
||||||
"cspell": "^7.3.8",
|
"cspell": "^8.2.3",
|
||||||
"docsify-cli": "^4.3.0",
|
"docsify-cli": "^4.3.0",
|
||||||
"eslint": "^8.23.0",
|
"eslint": "^8.23.0",
|
||||||
"eslint-plugin-functional": "^6.0.0",
|
"eslint-plugin-functional": "^6.0.0",
|
||||||
@ -87,19 +87,19 @@
|
|||||||
"execa": "^8.0.1",
|
"execa": "^8.0.1",
|
||||||
"glob": "^10.2.7",
|
"glob": "^10.2.7",
|
||||||
"inquirer": "^9.2.7",
|
"inquirer": "^9.2.7",
|
||||||
"jsdom": "^22.1.0",
|
"jsdom": "^23.0.1",
|
||||||
"pre-commit": "^1.2.2",
|
"pre-commit": "^1.2.2",
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.1.1",
|
||||||
"tsconfig-paths": "^4.0.0",
|
"tsconfig-paths": "^4.0.0",
|
||||||
"tsx": "^4.7.0",
|
"tsx": "^4.7.0",
|
||||||
"typedoc": "^0.24.8",
|
"typedoc": "^0.25.4",
|
||||||
"typescript": "5.1.6",
|
"typescript": "5.3.3",
|
||||||
"unzipper": "^0.10.11",
|
"unzipper": "^0.10.11",
|
||||||
"vite": "^5.0.10",
|
"vite": "^5.0.10",
|
||||||
"vite-plugin-dts": "^3.3.1",
|
"vite-plugin-dts": "^3.3.1",
|
||||||
"vite-plugin-node-polyfills": "^0.9.0",
|
"vite-plugin-node-polyfills": "^0.19.0",
|
||||||
"vite-tsconfig-paths": "^4.2.0",
|
"vite-tsconfig-paths": "^4.2.0",
|
||||||
"vitest": "^0.33.0"
|
"vitest": "^1.1.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
|
@ -36,7 +36,7 @@ describe("Compiler", () => {
|
|||||||
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
|
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
|
||||||
|
|
||||||
expect(fileNames).is.an.instanceof(Array);
|
expect(fileNames).is.an.instanceof(Array);
|
||||||
expect(fileNames).has.length(17);
|
expect(fileNames).has.length(19);
|
||||||
expect(fileNames).to.include("word/document.xml");
|
expect(fileNames).to.include("word/document.xml");
|
||||||
expect(fileNames).to.include("word/styles.xml");
|
expect(fileNames).to.include("word/styles.xml");
|
||||||
expect(fileNames).to.include("docProps/core.xml");
|
expect(fileNames).to.include("docProps/core.xml");
|
||||||
@ -47,7 +47,9 @@ describe("Compiler", () => {
|
|||||||
expect(fileNames).to.include("word/_rels/footnotes.xml.rels");
|
expect(fileNames).to.include("word/_rels/footnotes.xml.rels");
|
||||||
expect(fileNames).to.include("word/settings.xml");
|
expect(fileNames).to.include("word/settings.xml");
|
||||||
expect(fileNames).to.include("word/comments.xml");
|
expect(fileNames).to.include("word/comments.xml");
|
||||||
|
expect(fileNames).to.include("word/fontTable.xml");
|
||||||
expect(fileNames).to.include("word/_rels/document.xml.rels");
|
expect(fileNames).to.include("word/_rels/document.xml.rels");
|
||||||
|
expect(fileNames).to.include("word/_rels/fontTable.xml.rels");
|
||||||
expect(fileNames).to.include("[Content_Types].xml");
|
expect(fileNames).to.include("[Content_Types].xml");
|
||||||
expect(fileNames).to.include("_rels/.rels");
|
expect(fileNames).to.include("_rels/.rels");
|
||||||
},
|
},
|
||||||
@ -94,7 +96,7 @@ describe("Compiler", () => {
|
|||||||
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
|
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
|
||||||
|
|
||||||
expect(fileNames).is.an.instanceof(Array);
|
expect(fileNames).is.an.instanceof(Array);
|
||||||
expect(fileNames).has.length(25);
|
expect(fileNames).has.length(27);
|
||||||
|
|
||||||
expect(fileNames).to.include("word/header1.xml");
|
expect(fileNames).to.include("word/header1.xml");
|
||||||
expect(fileNames).to.include("word/_rels/header1.xml.rels");
|
expect(fileNames).to.include("word/_rels/header1.xml.rels");
|
||||||
@ -127,12 +129,10 @@ describe("Compiler", () => {
|
|||||||
const spy = vi.spyOn(compiler["formatter"], "format");
|
const spy = vi.spyOn(compiler["formatter"], "format");
|
||||||
|
|
||||||
compiler.compile(file);
|
compiler.compile(file);
|
||||||
expect(spy).toBeCalledTimes(13);
|
expect(spy).toBeCalledTimes(15);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should work with media datas", () => {
|
it("should work with media datas", () => {
|
||||||
// This test is required because before, there was a case where Document was formatted twice, which was inefficient
|
|
||||||
// This also caused issues such as running prepForXml multiple times as format() was ran multiple times.
|
|
||||||
const file = new File({
|
const file = new File({
|
||||||
sections: [
|
sections: [
|
||||||
{
|
{
|
||||||
@ -182,5 +182,14 @@ describe("Compiler", () => {
|
|||||||
|
|
||||||
compiler.compile(file);
|
compiler.compile(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should work with fonts", () => {
|
||||||
|
const file = new File({
|
||||||
|
sections: [],
|
||||||
|
fonts: [{ name: "Pacifico", data: Buffer.from("") }],
|
||||||
|
});
|
||||||
|
|
||||||
|
compiler.compile(file);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -2,6 +2,7 @@ import JSZip from "jszip";
|
|||||||
import xml from "xml";
|
import xml from "xml";
|
||||||
|
|
||||||
import { File } from "@file/file";
|
import { File } from "@file/file";
|
||||||
|
import { obfuscate } from "@file/fonts/obfuscate-ttf-to-odttf";
|
||||||
|
|
||||||
import { Formatter } from "../formatter";
|
import { Formatter } from "../formatter";
|
||||||
import { ImageReplacer } from "./image-replacer";
|
import { ImageReplacer } from "./image-replacer";
|
||||||
@ -31,6 +32,8 @@ interface IXmlifyedFileMapping {
|
|||||||
readonly FootNotesRelationships: IXmlifyedFile;
|
readonly FootNotesRelationships: IXmlifyedFile;
|
||||||
readonly Settings: IXmlifyedFile;
|
readonly Settings: IXmlifyedFile;
|
||||||
readonly Comments?: IXmlifyedFile;
|
readonly Comments?: IXmlifyedFile;
|
||||||
|
readonly FontTable?: IXmlifyedFile;
|
||||||
|
readonly FontTableRelationships?: IXmlifyedFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Compiler {
|
export class Compiler {
|
||||||
@ -63,6 +66,11 @@ export class Compiler {
|
|||||||
zip.file(`word/media/${fileName}`, stream);
|
zip.file(`word/media/${fileName}`, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const { data: buffer, name, fontKey } of file.FontTable.fontOptionsWithKey) {
|
||||||
|
const [nameWithoutExtension] = name.split(".");
|
||||||
|
zip.file(`word/fonts/${nameWithoutExtension}.odttf`, obfuscate(buffer, fontKey));
|
||||||
|
}
|
||||||
|
|
||||||
return zip;
|
return zip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,6 +447,40 @@ export class Compiler {
|
|||||||
),
|
),
|
||||||
path: "word/comments.xml",
|
path: "word/comments.xml",
|
||||||
},
|
},
|
||||||
|
FontTable: {
|
||||||
|
data: xml(
|
||||||
|
this.formatter.format(file.FontTable.View, {
|
||||||
|
viewWrapper: file.Document,
|
||||||
|
file,
|
||||||
|
stack: [],
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
standalone: "yes",
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
path: "word/fontTable.xml",
|
||||||
|
},
|
||||||
|
FontTableRelationships: {
|
||||||
|
data: (() =>
|
||||||
|
xml(
|
||||||
|
this.formatter.format(file.FontTable.Relationships, {
|
||||||
|
viewWrapper: file.Document,
|
||||||
|
file,
|
||||||
|
stack: [],
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
))(),
|
||||||
|
path: "word/_rels/fontTable.xml.rels",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,16 @@ describe("ContentTypes", () => {
|
|||||||
Default: { _attr: { ContentType: "application/vnd.openxmlformats-package.relationships+xml", Extension: "rels" } },
|
Default: { _attr: { ContentType: "application/vnd.openxmlformats-package.relationships+xml", Extension: "rels" } },
|
||||||
});
|
});
|
||||||
expect(tree["Types"][7]).to.deep.equal({ Default: { _attr: { ContentType: "application/xml", Extension: "xml" } } });
|
expect(tree["Types"][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/vnd.openxmlformats-officedocument.obfuscatedFont",
|
||||||
|
Extension: "odttf",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(tree["Types"][9]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
|
||||||
@ -37,7 +46,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][9]).to.deep.equal({
|
expect(tree["Types"][10]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
|
||||||
@ -45,7 +54,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][10]).to.deep.equal({
|
expect(tree["Types"][11]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-package.core-properties+xml",
|
ContentType: "application/vnd.openxmlformats-package.core-properties+xml",
|
||||||
@ -53,7 +62,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][11]).to.deep.equal({
|
expect(tree["Types"][12]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.custom-properties+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.custom-properties+xml",
|
||||||
@ -61,7 +70,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][12]).to.deep.equal({
|
expect(tree["Types"][13]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.extended-properties+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.extended-properties+xml",
|
||||||
@ -69,7 +78,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][13]).to.deep.equal({
|
expect(tree["Types"][14]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
|
||||||
@ -77,7 +86,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][14]).to.deep.equal({
|
expect(tree["Types"][15]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml",
|
||||||
@ -85,7 +94,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["Types"][15]).to.deep.equal({
|
expect(tree["Types"][16]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
|
||||||
@ -102,7 +111,7 @@ describe("ContentTypes", () => {
|
|||||||
contentTypes.addFooter(102);
|
contentTypes.addFooter(102);
|
||||||
const tree = new Formatter().format(contentTypes);
|
const tree = new Formatter().format(contentTypes);
|
||||||
|
|
||||||
expect(tree["Types"][17]).to.deep.equal({
|
expect(tree["Types"][19]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml",
|
||||||
@ -111,7 +120,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(tree["Types"][18]).to.deep.equal({
|
expect(tree["Types"][20]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml",
|
||||||
@ -128,7 +137,7 @@ describe("ContentTypes", () => {
|
|||||||
contentTypes.addHeader(202);
|
contentTypes.addHeader(202);
|
||||||
const tree = new Formatter().format(contentTypes);
|
const tree = new Formatter().format(contentTypes);
|
||||||
|
|
||||||
expect(tree["Types"][17]).to.deep.equal({
|
expect(tree["Types"][19]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
|
||||||
@ -137,7 +146,7 @@ describe("ContentTypes", () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(tree["Types"][18]).to.deep.equal({
|
expect(tree["Types"][20]).to.deep.equal({
|
||||||
Override: {
|
Override: {
|
||||||
_attr: {
|
_attr: {
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
|
||||||
|
@ -20,6 +20,7 @@ export class ContentTypes extends XmlComponent {
|
|||||||
this.root.push(new Default("image/gif", "gif"));
|
this.root.push(new Default("image/gif", "gif"));
|
||||||
this.root.push(new Default("application/vnd.openxmlformats-package.relationships+xml", "rels"));
|
this.root.push(new Default("application/vnd.openxmlformats-package.relationships+xml", "rels"));
|
||||||
this.root.push(new Default("application/xml", "xml"));
|
this.root.push(new Default("application/xml", "xml"));
|
||||||
|
this.root.push(new Default("application/vnd.openxmlformats-officedocument.obfuscatedFont", "odttf"));
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "/word/document.xml"),
|
new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "/word/document.xml"),
|
||||||
@ -33,6 +34,7 @@ export class ContentTypes extends XmlComponent {
|
|||||||
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", "/word/footnotes.xml"));
|
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", "/word/footnotes.xml"));
|
||||||
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", "/word/settings.xml"));
|
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", "/word/settings.xml"));
|
||||||
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml", "/word/comments.xml"));
|
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml", "/word/comments.xml"));
|
||||||
|
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml", "/word/fontTable.xml"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public addFooter(index: number): void {
|
public addFooter(index: number): void {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { ICommentsOptions } from "@file/paragraph/run/comment-run";
|
import { ICommentsOptions } from "@file/paragraph/run/comment-run";
|
||||||
import { ICompatibilityOptions } from "@file/settings/compatibility";
|
import { ICompatibilityOptions } from "@file/settings/compatibility";
|
||||||
|
import { FontOptions } from "@file/fonts/font-table";
|
||||||
import { StringContainer, XmlComponent } from "@file/xml-components";
|
import { StringContainer, XmlComponent } from "@file/xml-components";
|
||||||
import { dateTimeValue } from "@util/values";
|
import { dateTimeValue } from "@util/values";
|
||||||
|
|
||||||
@ -40,6 +41,7 @@ export interface IPropertiesOptions {
|
|||||||
readonly customProperties?: readonly ICustomPropertyOptions[];
|
readonly customProperties?: readonly ICustomPropertyOptions[];
|
||||||
readonly evenAndOddHeaderAndFooters?: boolean;
|
readonly evenAndOddHeaderAndFooters?: boolean;
|
||||||
readonly defaultTabStop?: number;
|
readonly defaultTabStop?: number;
|
||||||
|
readonly fonts?: readonly FontOptions[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// <xs:element name="coreProperties" type="CT_CoreProperties"/>
|
// <xs:element name="coreProperties" type="CT_CoreProperties"/>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { XmlComponent } from "./xml-components";
|
||||||
import { Document, IDocumentOptions } from "./document";
|
import { Document, IDocumentOptions } from "./document";
|
||||||
import { Footer } from "./footer/footer";
|
import { Footer } from "./footer/footer";
|
||||||
import { FootNotes } from "./footnotes";
|
import { FootNotes } from "./footnotes";
|
||||||
@ -5,7 +6,7 @@ import { Header } from "./header/header";
|
|||||||
import { Relationships } from "./relationships";
|
import { Relationships } from "./relationships";
|
||||||
|
|
||||||
export interface IViewWrapper {
|
export interface IViewWrapper {
|
||||||
readonly View: Document | Footer | Header | FootNotes;
|
readonly View: Document | Footer | Header | FootNotes | XmlComponent;
|
||||||
readonly Relationships: Relationships;
|
readonly Relationships: Relationships;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// http://officeopenxml.com/WPsectionLineNumbering.php
|
// http://officeopenxml.com/WPsectionLineNumbering.php
|
||||||
import { NextAttributeComponent, XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
import { decimalNumber, PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
|
import { decimalNumber, PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
|
||||||
|
|
||||||
// <xsd:simpleType name="ST_LineNumberRestart">
|
// <xsd:simpleType name="ST_LineNumberRestart">
|
||||||
@ -25,31 +25,23 @@ export const LineNumberRestartFormat = {
|
|||||||
// <xsd:attribute name="restart" type="ST_LineNumberRestart" use="optional" default="newPage"/>
|
// <xsd:attribute name="restart" type="ST_LineNumberRestart" use="optional" default="newPage"/>
|
||||||
// </xsd:complexType>
|
// </xsd:complexType>
|
||||||
|
|
||||||
export interface ILineNumberAttributes {
|
export type ILineNumberAttributes = {
|
||||||
readonly countBy?: number;
|
readonly countBy?: number;
|
||||||
readonly start?: number;
|
readonly start?: number;
|
||||||
readonly restart?: (typeof LineNumberRestartFormat)[keyof typeof LineNumberRestartFormat];
|
readonly restart?: (typeof LineNumberRestartFormat)[keyof typeof LineNumberRestartFormat];
|
||||||
readonly distance?: number | PositiveUniversalMeasure;
|
readonly distance?: number | PositiveUniversalMeasure;
|
||||||
}
|
};
|
||||||
|
|
||||||
export class LineNumberType extends XmlComponent {
|
export const createLineNumberType = ({ countBy, start, restart, distance }: ILineNumberAttributes): XmlComponent =>
|
||||||
public constructor({ countBy, start, restart, distance }: ILineNumberAttributes) {
|
new BuilderElement<ILineNumberAttributes>({
|
||||||
super("w:lnNumType");
|
name: "w:lnNumType",
|
||||||
this.root.push(
|
attributes: {
|
||||||
new NextAttributeComponent<{
|
countBy: { key: "w:countBy", value: countBy === undefined ? undefined : decimalNumber(countBy) },
|
||||||
readonly countBy?: number;
|
start: { key: "w:start", value: start === undefined ? undefined : decimalNumber(start) },
|
||||||
readonly start?: number;
|
restart: { key: "w:restart", value: restart },
|
||||||
readonly restart?: (typeof LineNumberRestartFormat)[keyof typeof LineNumberRestartFormat];
|
distance: {
|
||||||
readonly distance?: number | PositiveUniversalMeasure;
|
key: "w:distance",
|
||||||
}>({
|
value: distance === undefined ? undefined : twipsMeasureValue(distance),
|
||||||
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),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -9,7 +9,7 @@ import { OnOffElement, XmlComponent } from "@file/xml-components";
|
|||||||
import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./properties/header-footer-reference";
|
import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./properties/header-footer-reference";
|
||||||
import { Columns, IColumnsAttributes } from "./properties/columns";
|
import { Columns, IColumnsAttributes } from "./properties/columns";
|
||||||
import { DocumentGrid, IDocGridAttributesProperties } from "./properties/doc-grid";
|
import { DocumentGrid, IDocGridAttributesProperties } from "./properties/doc-grid";
|
||||||
import { ILineNumberAttributes, LineNumberType } from "./properties/line-number";
|
import { ILineNumberAttributes, createLineNumberType } from "./properties/line-number";
|
||||||
import { IPageBordersOptions, PageBorders } from "./properties/page-borders";
|
import { IPageBordersOptions, PageBorders } from "./properties/page-borders";
|
||||||
import { IPageMarginAttributes, PageMargin } from "./properties/page-margin";
|
import { IPageMarginAttributes, PageMargin } from "./properties/page-margin";
|
||||||
import { IPageNumberTypeAttributes, PageNumberType } from "./properties/page-number";
|
import { IPageNumberTypeAttributes, PageNumberType } from "./properties/page-number";
|
||||||
@ -137,7 +137,7 @@ export class SectionProperties extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lineNumbers) {
|
if (lineNumbers) {
|
||||||
this.root.push(new LineNumberType(lineNumbers));
|
this.root.push(createLineNumberType(lineNumbers));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.root.push(new PageNumberType(pageNumbers));
|
this.root.push(new PageNumberType(pageNumbers));
|
||||||
|
@ -9,10 +9,10 @@ import { TextWrappingType } from "../text-wrap";
|
|||||||
import { Anchor } from "./anchor";
|
import { Anchor } from "./anchor";
|
||||||
|
|
||||||
const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
||||||
new Anchor(
|
new Anchor({
|
||||||
{
|
mediaData: {
|
||||||
fileName: "test.png",
|
fileName: "test.png",
|
||||||
stream: new Buffer(""),
|
stream: Buffer.from(""),
|
||||||
transformation: {
|
transformation: {
|
||||||
pixels: {
|
pixels: {
|
||||||
x: 0,
|
x: 0,
|
||||||
@ -24,7 +24,7 @@ const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
transform: {
|
||||||
pixels: {
|
pixels: {
|
||||||
x: 100,
|
x: 100,
|
||||||
y: 100,
|
y: 100,
|
||||||
@ -35,7 +35,7 @@ const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
drawingOptions,
|
drawingOptions,
|
||||||
);
|
});
|
||||||
|
|
||||||
describe("Anchor", () => {
|
describe("Anchor", () => {
|
||||||
let anchor: Anchor;
|
let anchor: Anchor;
|
||||||
|
@ -6,7 +6,7 @@ import { HorizontalPosition, IFloating, SimplePos, VerticalPosition } from "../f
|
|||||||
import { Graphic } from "../inline/graphic";
|
import { Graphic } from "../inline/graphic";
|
||||||
import { TextWrappingType, WrapNone, WrapSquare, WrapTight, WrapTopAndBottom } from "../text-wrap";
|
import { TextWrappingType, WrapNone, WrapSquare, WrapTight, WrapTopAndBottom } from "../text-wrap";
|
||||||
import { DocProperties } from "./../doc-properties/doc-properties";
|
import { DocProperties } from "./../doc-properties/doc-properties";
|
||||||
import { EffectExtent } from "./../effect-extent/effect-extent";
|
import { createEffectExtent } from "./../effect-extent/effect-extent";
|
||||||
import { Extent } from "./../extent/extent";
|
import { Extent } from "./../extent/extent";
|
||||||
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
||||||
import { AnchorAttributes } from "./anchor-attributes";
|
import { AnchorAttributes } from "./anchor-attributes";
|
||||||
@ -37,7 +37,15 @@ import { AnchorAttributes } from "./anchor-attributes";
|
|||||||
// <xsd:attribute name="allowOverlap" type="xsd:boolean" use="required"/>
|
// <xsd:attribute name="allowOverlap" type="xsd:boolean" use="required"/>
|
||||||
// </xsd:complexType>
|
// </xsd:complexType>
|
||||||
export class Anchor extends XmlComponent {
|
export class Anchor extends XmlComponent {
|
||||||
public constructor(mediaData: IMediaData, transform: IMediaDataTransformation, drawingOptions: IDrawingOptions) {
|
public constructor({
|
||||||
|
mediaData,
|
||||||
|
transform,
|
||||||
|
drawingOptions,
|
||||||
|
}: {
|
||||||
|
readonly mediaData: IMediaData;
|
||||||
|
readonly transform: IMediaDataTransformation;
|
||||||
|
readonly drawingOptions: IDrawingOptions;
|
||||||
|
}) {
|
||||||
super("wp:anchor");
|
super("wp:anchor");
|
||||||
|
|
||||||
const floating: IFloating = {
|
const floating: IFloating = {
|
||||||
@ -69,7 +77,7 @@ export class Anchor extends XmlComponent {
|
|||||||
this.root.push(new HorizontalPosition(floating.horizontalPosition));
|
this.root.push(new HorizontalPosition(floating.horizontalPosition));
|
||||||
this.root.push(new VerticalPosition(floating.verticalPosition));
|
this.root.push(new VerticalPosition(floating.verticalPosition));
|
||||||
this.root.push(new Extent(transform.emus.x, transform.emus.y));
|
this.root.push(new Extent(transform.emus.x, transform.emus.y));
|
||||||
this.root.push(new EffectExtent());
|
this.root.push(createEffectExtent({ top: 0, right: 0, bottom: 0, left: 0 }));
|
||||||
|
|
||||||
if (drawingOptions.floating !== undefined && drawingOptions.floating.wrap !== undefined) {
|
if (drawingOptions.floating !== undefined && drawingOptions.floating.wrap !== undefined) {
|
||||||
switch (drawingOptions.floating.wrap.type) {
|
switch (drawingOptions.floating.wrap.type) {
|
||||||
@ -92,6 +100,6 @@ export class Anchor extends XmlComponent {
|
|||||||
|
|
||||||
this.root.push(new DocProperties(drawingOptions.docProperties));
|
this.root.push(new DocProperties(drawingOptions.docProperties));
|
||||||
this.root.push(new GraphicFrameProperties());
|
this.root.push(new GraphicFrameProperties());
|
||||||
this.root.push(new Graphic(mediaData, transform));
|
this.root.push(new Graphic({ mediaData, transform, outline: drawingOptions.outline }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,18 +4,20 @@ import { XmlComponent } from "@file/xml-components";
|
|||||||
import { Anchor } from "./anchor";
|
import { Anchor } from "./anchor";
|
||||||
import { DocPropertiesOptions } from "./doc-properties/doc-properties";
|
import { DocPropertiesOptions } from "./doc-properties/doc-properties";
|
||||||
import { IFloating } from "./floating";
|
import { IFloating } from "./floating";
|
||||||
import { Inline } from "./inline";
|
import { createInline } from "./inline";
|
||||||
|
import { OutlineOptions } from "./inline/graphic/graphic-data/pic/shape-properties/outline/outline";
|
||||||
|
|
||||||
export interface IDistance {
|
export type IDistance = {
|
||||||
readonly distT?: number;
|
readonly distT?: number;
|
||||||
readonly distB?: number;
|
readonly distB?: number;
|
||||||
readonly distL?: number;
|
readonly distL?: number;
|
||||||
readonly distR?: number;
|
readonly distR?: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface IDrawingOptions {
|
export interface IDrawingOptions {
|
||||||
readonly floating?: IFloating;
|
readonly floating?: IFloating;
|
||||||
readonly docProperties?: DocPropertiesOptions;
|
readonly docProperties?: DocPropertiesOptions;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <xsd:complexType name="CT_Drawing">
|
// <xsd:complexType name="CT_Drawing">
|
||||||
@ -30,14 +32,16 @@ export class Drawing extends XmlComponent {
|
|||||||
super("w:drawing");
|
super("w:drawing");
|
||||||
|
|
||||||
if (!drawingOptions.floating) {
|
if (!drawingOptions.floating) {
|
||||||
const inline = new Inline({
|
this.root.push(
|
||||||
mediaData: imageData,
|
createInline({
|
||||||
transform: imageData.transformation,
|
mediaData: imageData,
|
||||||
docProperties: drawingOptions.docProperties,
|
transform: imageData.transformation,
|
||||||
});
|
docProperties: drawingOptions.docProperties,
|
||||||
this.root.push(inline);
|
outline: drawingOptions.outline,
|
||||||
|
}),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.root.push(new Anchor(imageData, imageData.transformation, drawingOptions));
|
this.root.push(new Anchor({ mediaData: imageData, transform: imageData.transformation, drawingOptions }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
import { XmlAttributeComponent } from "@file/xml-components";
|
|
||||||
|
|
||||||
export class EffectExtentAttributes extends XmlAttributeComponent<{
|
|
||||||
readonly b?: number;
|
|
||||||
readonly l?: number;
|
|
||||||
readonly r?: number;
|
|
||||||
readonly t?: number;
|
|
||||||
}> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
b: "b",
|
|
||||||
l: "l",
|
|
||||||
r: "r",
|
|
||||||
t: "t",
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,17 +1,31 @@
|
|||||||
import { XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
import { EffectExtentAttributes } from "./effect-extent-attributes";
|
|
||||||
|
|
||||||
export class EffectExtent extends XmlComponent {
|
export type EffectExtentAttributes = {
|
||||||
public constructor() {
|
readonly top: number;
|
||||||
super("wp:effectExtent");
|
readonly right: number;
|
||||||
|
readonly bottom: number;
|
||||||
|
readonly left: number;
|
||||||
|
};
|
||||||
|
|
||||||
this.root.push(
|
export const createEffectExtent = ({ top, right, bottom, left }: EffectExtentAttributes): XmlComponent =>
|
||||||
new EffectExtentAttributes({
|
new BuilderElement<EffectExtentAttributes>({
|
||||||
b: 0,
|
name: "wp:effectExtent",
|
||||||
l: 0,
|
attributes: {
|
||||||
r: 0,
|
top: {
|
||||||
t: 0,
|
key: "t",
|
||||||
}),
|
value: top,
|
||||||
);
|
},
|
||||||
}
|
right: {
|
||||||
}
|
key: "r",
|
||||||
|
value: right,
|
||||||
|
},
|
||||||
|
bottom: {
|
||||||
|
key: "b",
|
||||||
|
value: bottom,
|
||||||
|
},
|
||||||
|
left: {
|
||||||
|
key: "l",
|
||||||
|
value: left,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
@ -3,11 +3,20 @@ import { XmlComponent } from "@file/xml-components";
|
|||||||
|
|
||||||
import { GraphicDataAttributes } from "./graphic-data-attribute";
|
import { GraphicDataAttributes } from "./graphic-data-attribute";
|
||||||
import { Pic } from "./pic";
|
import { Pic } from "./pic";
|
||||||
|
import { OutlineOptions } from "./pic/shape-properties/outline/outline";
|
||||||
|
|
||||||
export class GraphicData extends XmlComponent {
|
export class GraphicData extends XmlComponent {
|
||||||
private readonly pic: Pic;
|
private readonly pic: Pic;
|
||||||
|
|
||||||
public constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
public constructor({
|
||||||
|
mediaData,
|
||||||
|
transform,
|
||||||
|
outline,
|
||||||
|
}: {
|
||||||
|
readonly mediaData: IMediaData;
|
||||||
|
readonly transform: IMediaDataTransformation;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
|
}) {
|
||||||
super("a:graphicData");
|
super("a:graphicData");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
@ -16,7 +25,7 @@ export class GraphicData extends XmlComponent {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.pic = new Pic(mediaData, transform);
|
this.pic = new Pic({ mediaData, transform, outline });
|
||||||
|
|
||||||
this.root.push(this.pic);
|
this.root.push(this.pic);
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,18 @@ import { BlipFill } from "./blip/blip-fill";
|
|||||||
import { NonVisualPicProperties } from "./non-visual-pic-properties/non-visual-pic-properties";
|
import { NonVisualPicProperties } from "./non-visual-pic-properties/non-visual-pic-properties";
|
||||||
import { PicAttributes } from "./pic-attributes";
|
import { PicAttributes } from "./pic-attributes";
|
||||||
import { ShapeProperties } from "./shape-properties/shape-properties";
|
import { ShapeProperties } from "./shape-properties/shape-properties";
|
||||||
|
import { OutlineOptions } from "./shape-properties/outline/outline";
|
||||||
|
|
||||||
export class Pic extends XmlComponent {
|
export class Pic extends XmlComponent {
|
||||||
public constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
public constructor({
|
||||||
|
mediaData,
|
||||||
|
transform,
|
||||||
|
outline,
|
||||||
|
}: {
|
||||||
|
readonly mediaData: IMediaData;
|
||||||
|
readonly transform: IMediaDataTransformation;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
|
}) {
|
||||||
super("pic:pic");
|
super("pic:pic");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
@ -19,6 +28,6 @@ export class Pic extends XmlComponent {
|
|||||||
|
|
||||||
this.root.push(new NonVisualPicProperties());
|
this.root.push(new NonVisualPicProperties());
|
||||||
this.root.push(new BlipFill(mediaData));
|
this.root.push(new BlipFill(mediaData));
|
||||||
this.root.push(new ShapeProperties(transform));
|
this.root.push(new ShapeProperties({ transform, outline }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,12 @@ import { describe, expect, it } from "vitest";
|
|||||||
|
|
||||||
import { Formatter } from "@export/formatter";
|
import { Formatter } from "@export/formatter";
|
||||||
|
|
||||||
import { NoFill } from "./no-fill";
|
import { createNoFill } from "./no-fill";
|
||||||
|
|
||||||
describe("NoFill", () => {
|
describe("NoFill", () => {
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
it("should create", () => {
|
it("should create", () => {
|
||||||
const tree = new Formatter().format(new NoFill());
|
const tree = new Formatter().format(createNoFill());
|
||||||
expect(tree).to.deep.equal({
|
expect(tree).to.deep.equal({
|
||||||
"a:noFill": {},
|
"a:noFill": {},
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
import { XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
export class NoFill extends XmlComponent {
|
export const createNoFill = (): XmlComponent => new BuilderElement({ name: "a:noFill" });
|
||||||
public constructor() {
|
|
||||||
super("a:noFill");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,19 +1,66 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
import { Formatter } from "@export/formatter";
|
import { Formatter } from "@export/formatter";
|
||||||
import { Outline } from "./outline";
|
|
||||||
|
|
||||||
describe("Outline", () => {
|
import { createOutline } from "./outline";
|
||||||
describe("#constructor()", () => {
|
import { SchemeColor } from "./scheme-color";
|
||||||
it("should create", () => {
|
|
||||||
const tree = new Formatter().format(new Outline());
|
describe("createOutline", () => {
|
||||||
expect(tree).to.deep.equal({
|
it("should create no fill", () => {
|
||||||
"a:ln": [
|
const tree = new Formatter().format(createOutline({ type: "noFill" }));
|
||||||
{
|
expect(tree).to.deep.equal({
|
||||||
"a:noFill": {},
|
"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
|
// http://officeopenxml.com/drwSp-outline.php
|
||||||
import { XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
import { NoFill } from "./no-fill";
|
import { createNoFill } from "./no-fill";
|
||||||
|
import { createSolidFill } from "./solid-fill";
|
||||||
|
import { SchemeColor } from "./scheme-color";
|
||||||
|
|
||||||
export class Outline extends XmlComponent {
|
// <xsd:complexType name="CT_TextOutlineEffect">
|
||||||
public constructor() {
|
// <xsd:sequence>
|
||||||
super("a:ln");
|
// <xsd:group ref="EG_FillProperties" minOccurs="0"/>
|
||||||
|
// <xsd:group ref="EG_LineDashProperties" minOccurs="0"/>
|
||||||
|
// <xsd:group ref="EG_LineJoinProperties" minOccurs="0"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// <xsd:attribute name="w" use="optional" type="a:ST_LineWidth"/>
|
||||||
|
// <xsd:attribute name="cap" use="optional" type="ST_LineCap"/>
|
||||||
|
// <xsd:attribute name="cmpd" use="optional" type="ST_CompoundLine"/>
|
||||||
|
// <xsd:attribute name="algn" use="optional" type="ST_PenAlignment"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
|
||||||
this.root.push(new NoFill());
|
// <xsd:simpleType name="ST_LineCap">
|
||||||
}
|
// <xsd:restriction base="xsd:string">
|
||||||
}
|
// <xsd:enumeration value="rnd"/>
|
||||||
|
// <xsd:enumeration value="sq"/>
|
||||||
|
// <xsd:enumeration value="flat"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export const LineCap = {
|
||||||
|
ROUND: "rnd",
|
||||||
|
SQUARE: "sq",
|
||||||
|
FLAT: "flat",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_CompoundLine">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="sng"/>
|
||||||
|
// <xsd:enumeration value="dbl"/>
|
||||||
|
// <xsd:enumeration value="thickThin"/>
|
||||||
|
// <xsd:enumeration value="thinThick"/>
|
||||||
|
// <xsd:enumeration value="tri"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export const CompoundLine = {
|
||||||
|
SINGLE: "sng",
|
||||||
|
DOUBLE: "dbl",
|
||||||
|
THICK_THIN: "thickThin",
|
||||||
|
THIN_THICK: "thinThick",
|
||||||
|
TRI: "tri",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_PenAlignment">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="ctr"/>
|
||||||
|
// <xsd:enumeration value="in"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export const PenAlignment = {
|
||||||
|
CENTER: "ctr",
|
||||||
|
INSET: "in",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type OutlineAttributes = {
|
||||||
|
readonly width?: number;
|
||||||
|
readonly cap?: keyof typeof LineCap;
|
||||||
|
readonly compoundLine?: keyof typeof CompoundLine;
|
||||||
|
readonly align?: keyof typeof PenAlignment;
|
||||||
|
};
|
||||||
|
|
||||||
|
type OutlineNoFill = {
|
||||||
|
readonly type: "noFill";
|
||||||
|
};
|
||||||
|
|
||||||
|
type OutlineRgbSolidFill = {
|
||||||
|
readonly type: "solidFill";
|
||||||
|
readonly solidFillType: "rgb";
|
||||||
|
readonly value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type OutlineSchemeSolidFill = {
|
||||||
|
readonly type: "solidFill";
|
||||||
|
readonly solidFillType: "scheme";
|
||||||
|
readonly value: (typeof SchemeColor)[keyof typeof SchemeColor];
|
||||||
|
};
|
||||||
|
|
||||||
|
type OutlineSolidFill = OutlineRgbSolidFill | OutlineSchemeSolidFill;
|
||||||
|
|
||||||
|
// <xsd:group name="EG_FillProperties">
|
||||||
|
// <xsd:choice>
|
||||||
|
// <xsd:element name="noFill" type="w:CT_Empty"/>
|
||||||
|
// <xsd:element name="solidFill" type="CT_SolidColorFillProperties"/>
|
||||||
|
// <xsd:element name="gradFill" type="CT_GradientFillProperties"/>
|
||||||
|
// </xsd:choice>
|
||||||
|
// </xsd:group>
|
||||||
|
type OutlineFillProperties = OutlineNoFill | OutlineSolidFill;
|
||||||
|
|
||||||
|
export type OutlineOptions = OutlineAttributes & OutlineFillProperties;
|
||||||
|
|
||||||
|
export const createOutline = (options: OutlineOptions): XmlComponent =>
|
||||||
|
new BuilderElement<OutlineAttributes>({
|
||||||
|
name: "a:ln",
|
||||||
|
attributes: {
|
||||||
|
width: {
|
||||||
|
key: "w",
|
||||||
|
value: options.width,
|
||||||
|
},
|
||||||
|
cap: {
|
||||||
|
key: "cap",
|
||||||
|
value: options.cap,
|
||||||
|
},
|
||||||
|
compoundLine: {
|
||||||
|
key: "cmpd",
|
||||||
|
value: options.compoundLine,
|
||||||
|
},
|
||||||
|
align: {
|
||||||
|
key: "algn",
|
||||||
|
value: options.align,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
options.type === "noFill"
|
||||||
|
? createNoFill()
|
||||||
|
: options.solidFillType === "rgb"
|
||||||
|
? createSolidFill({
|
||||||
|
type: "rgb",
|
||||||
|
value: options.value,
|
||||||
|
})
|
||||||
|
: createSolidFill({
|
||||||
|
type: "scheme",
|
||||||
|
value: options.value,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
type SolidRgbColorOptions = {
|
||||||
|
readonly value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_SRgbColor">
|
||||||
|
// <xsd:sequence>
|
||||||
|
// <xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// <xsd:attribute name="val" type="s:ST_HexColorRGB" use="required"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
export const createSolidRgbColor = (options: SolidRgbColorOptions): XmlComponent =>
|
||||||
|
new BuilderElement<SolidRgbColorOptions>({
|
||||||
|
name: "a:srgbClr",
|
||||||
|
attributes: {
|
||||||
|
value: {
|
||||||
|
key: "val",
|
||||||
|
value: options.value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
@ -0,0 +1,65 @@
|
|||||||
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
type SchemeColorOptions = {
|
||||||
|
readonly value: (typeof SchemeColor)[keyof typeof SchemeColor];
|
||||||
|
};
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_SchemeColorVal">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="bg1"/>
|
||||||
|
// <xsd:enumeration value="tx1"/>
|
||||||
|
// <xsd:enumeration value="bg2"/>
|
||||||
|
// <xsd:enumeration value="tx2"/>
|
||||||
|
// <xsd:enumeration value="accent1"/>
|
||||||
|
// <xsd:enumeration value="accent2"/>
|
||||||
|
// <xsd:enumeration value="accent3"/>
|
||||||
|
// <xsd:enumeration value="accent4"/>
|
||||||
|
// <xsd:enumeration value="accent5"/>
|
||||||
|
// <xsd:enumeration value="accent6"/>
|
||||||
|
// <xsd:enumeration value="hlink"/>
|
||||||
|
// <xsd:enumeration value="folHlink"/>
|
||||||
|
// <xsd:enumeration value="dk1"/>
|
||||||
|
// <xsd:enumeration value="lt1"/>
|
||||||
|
// <xsd:enumeration value="dk2"/>
|
||||||
|
// <xsd:enumeration value="lt2"/>
|
||||||
|
// <xsd:enumeration value="phClr"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
|
||||||
|
// cspell:ignore folHlink, phClr, hlink
|
||||||
|
export const SchemeColor = {
|
||||||
|
BG1: "bg1",
|
||||||
|
TX1: "tx1",
|
||||||
|
BG2: "bg2",
|
||||||
|
TX2: "tx2",
|
||||||
|
ACCENT1: "accent1",
|
||||||
|
ACCENT2: "accent2",
|
||||||
|
ACCENT3: "accent3",
|
||||||
|
ACCENT4: "accent4",
|
||||||
|
ACCENT5: "accent5",
|
||||||
|
ACCENT6: "accent6",
|
||||||
|
HLINK: "hlink",
|
||||||
|
FOLHLINK: "folHlink",
|
||||||
|
DK1: "dk1",
|
||||||
|
LT1: "lt1",
|
||||||
|
DK2: "dk2",
|
||||||
|
LT2: "lt2",
|
||||||
|
PHCLR: "phClr",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_SchemeColor">
|
||||||
|
// <xsd:sequence>
|
||||||
|
// <xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// <xsd:attribute name="val" type="ST_SchemeColorVal" use="required"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
export const createSchemeColor = (options: SchemeColorOptions): XmlComponent =>
|
||||||
|
new BuilderElement<SchemeColorOptions>({
|
||||||
|
name: "a:schemeClr",
|
||||||
|
attributes: {
|
||||||
|
value: {
|
||||||
|
key: "val",
|
||||||
|
value: options.value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
@ -0,0 +1,38 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { Formatter } from "@export/formatter";
|
||||||
|
|
||||||
|
import { createSolidFill } from "./solid-fill";
|
||||||
|
import { SchemeColor } from "./scheme-color";
|
||||||
|
|
||||||
|
describe("createSolidFill", () => {
|
||||||
|
it("should create of rgb", () => {
|
||||||
|
const tree = new Formatter().format(createSolidFill({ type: "rgb", value: "FFFFFF" }));
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"a:solidFill": [
|
||||||
|
{
|
||||||
|
"a:srgbClr": {
|
||||||
|
_attr: {
|
||||||
|
val: "FFFFFF",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create of scheme", () => {
|
||||||
|
const tree = new Formatter().format(createSolidFill({ type: "scheme", value: SchemeColor.TX1 }));
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"a:solidFill": [
|
||||||
|
{
|
||||||
|
"a:schemeClr": {
|
||||||
|
_attr: {
|
||||||
|
val: "tx1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,22 @@
|
|||||||
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
import { createSchemeColor, SchemeColor } from "./scheme-color";
|
||||||
|
import { createSolidRgbColor } from "./rgb-color";
|
||||||
|
|
||||||
|
export type RgbColorOptions = {
|
||||||
|
readonly type: "rgb";
|
||||||
|
readonly value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SchemeColorOptions = {
|
||||||
|
readonly type: "scheme";
|
||||||
|
readonly value: (typeof SchemeColor)[keyof typeof SchemeColor];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SolidFillOptions = RgbColorOptions | SchemeColorOptions;
|
||||||
|
|
||||||
|
export const createSolidFill = (options: SolidFillOptions): XmlComponent =>
|
||||||
|
new BuilderElement({
|
||||||
|
name: "a:solidFill",
|
||||||
|
children: [options.type === "rgb" ? createSolidRgbColor(options) : createSchemeColor(options)],
|
||||||
|
});
|
@ -2,15 +2,15 @@
|
|||||||
import { IMediaDataTransformation } from "@file/media";
|
import { IMediaDataTransformation } from "@file/media";
|
||||||
import { XmlComponent } from "@file/xml-components";
|
import { XmlComponent } from "@file/xml-components";
|
||||||
import { Form } from "./form";
|
import { Form } from "./form";
|
||||||
// import { NoFill } from "./no-fill";
|
import { OutlineOptions, createOutline } from "./outline/outline";
|
||||||
// import { Outline } from "./outline/outline";
|
|
||||||
import { PresetGeometry } from "./preset-geometry/preset-geometry";
|
import { PresetGeometry } from "./preset-geometry/preset-geometry";
|
||||||
import { ShapePropertiesAttributes } from "./shape-properties-attributes";
|
import { ShapePropertiesAttributes } from "./shape-properties-attributes";
|
||||||
|
import { createNoFill } from "./outline/no-fill";
|
||||||
|
|
||||||
export class ShapeProperties extends XmlComponent {
|
export class ShapeProperties extends XmlComponent {
|
||||||
private readonly form: Form;
|
private readonly form: Form;
|
||||||
|
|
||||||
public constructor(transform: IMediaDataTransformation) {
|
public constructor({ outline, transform }: { readonly outline?: OutlineOptions; readonly transform: IMediaDataTransformation }) {
|
||||||
super("pic:spPr");
|
super("pic:spPr");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
@ -23,7 +23,10 @@ export class ShapeProperties extends XmlComponent {
|
|||||||
|
|
||||||
this.root.push(this.form);
|
this.root.push(this.form);
|
||||||
this.root.push(new PresetGeometry());
|
this.root.push(new PresetGeometry());
|
||||||
// this.root.push(new NoFill());
|
|
||||||
// this.root.push(new Outline());
|
if (outline) {
|
||||||
|
this.root.push(createNoFill());
|
||||||
|
this.root.push(createOutline(outline));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import { IMediaData, IMediaDataTransformation } from "@file/media";
|
|||||||
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
import { GraphicData } from "./graphic-data";
|
import { GraphicData } from "./graphic-data";
|
||||||
|
import { OutlineOptions } from "./graphic-data/pic/shape-properties/outline/outline";
|
||||||
|
|
||||||
class GraphicAttributes extends XmlAttributeComponent<{
|
class GraphicAttributes extends XmlAttributeComponent<{
|
||||||
readonly a: string;
|
readonly a: string;
|
||||||
@ -14,7 +15,15 @@ class GraphicAttributes extends XmlAttributeComponent<{
|
|||||||
export class Graphic extends XmlComponent {
|
export class Graphic extends XmlComponent {
|
||||||
private readonly data: GraphicData;
|
private readonly data: GraphicData;
|
||||||
|
|
||||||
public constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
public constructor({
|
||||||
|
mediaData,
|
||||||
|
transform,
|
||||||
|
outline,
|
||||||
|
}: {
|
||||||
|
readonly mediaData: IMediaData;
|
||||||
|
readonly transform: IMediaDataTransformation;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
|
}) {
|
||||||
super("a:graphic");
|
super("a:graphic");
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new GraphicAttributes({
|
new GraphicAttributes({
|
||||||
@ -22,7 +31,7 @@ export class Graphic extends XmlComponent {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.data = new GraphicData(mediaData, transform);
|
this.data = new GraphicData({ mediaData, transform, outline });
|
||||||
|
|
||||||
this.root.push(this.data);
|
this.root.push(this.data);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import { XmlAttributeComponent } from "@file/xml-components";
|
|
||||||
import { IDistance } from "../drawing";
|
|
||||||
|
|
||||||
// distT, distB etc have no effect on inline images, only floating
|
|
||||||
export class InlineAttributes extends XmlAttributeComponent<IDistance> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
distT: "distT",
|
|
||||||
distB: "distB",
|
|
||||||
distL: "distL",
|
|
||||||
distR: "distR",
|
|
||||||
};
|
|
||||||
}
|
|
58
src/file/drawing/inline/inline.spec.ts
Normal file
58
src/file/drawing/inline/inline.spec.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
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: {
|
||||||
|
fileName: "test.png",
|
||||||
|
stream: Buffer.from(""),
|
||||||
|
transformation: {
|
||||||
|
pixels: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
emus: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
transform: {
|
||||||
|
pixels: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
emus: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
docProperties: {
|
||||||
|
name: "test",
|
||||||
|
description: "test",
|
||||||
|
title: "test",
|
||||||
|
},
|
||||||
|
outline: { type: "solidFill", solidFillType: "rgb", value: "FFFFFF" },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"wp:inline": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"wp:effectExtent": {
|
||||||
|
_attr: {
|
||||||
|
b: 19050,
|
||||||
|
l: 19050,
|
||||||
|
r: 19050,
|
||||||
|
t: 19050,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,18 +1,19 @@
|
|||||||
// http://officeopenxml.com/drwPicInline.php
|
// http://officeopenxml.com/drwPicInline.php
|
||||||
import { IMediaData, IMediaDataTransformation } from "@file/media";
|
import { IMediaData, IMediaDataTransformation } from "@file/media";
|
||||||
import { XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
import { DocProperties, DocPropertiesOptions } from "./../doc-properties/doc-properties";
|
import { DocProperties, DocPropertiesOptions } from "./../doc-properties/doc-properties";
|
||||||
import { EffectExtent } from "./../effect-extent/effect-extent";
|
import { createEffectExtent } from "./../effect-extent/effect-extent";
|
||||||
import { Extent } from "./../extent/extent";
|
import { Extent } from "./../extent/extent";
|
||||||
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
||||||
import { Graphic } from "./../inline/graphic";
|
import { Graphic } from "./../inline/graphic";
|
||||||
import { InlineAttributes } from "./inline-attributes";
|
import { OutlineOptions } from "./graphic/graphic-data/pic/shape-properties/outline/outline";
|
||||||
|
|
||||||
interface InlineOptions {
|
type InlineOptions = {
|
||||||
readonly mediaData: IMediaData;
|
readonly mediaData: IMediaData;
|
||||||
readonly transform: IMediaDataTransformation;
|
readonly transform: IMediaDataTransformation;
|
||||||
readonly docProperties?: DocPropertiesOptions;
|
readonly docProperties?: DocPropertiesOptions;
|
||||||
}
|
readonly outline?: OutlineOptions;
|
||||||
|
};
|
||||||
|
|
||||||
// <xsd:complexType name="CT_Inline">
|
// <xsd:complexType name="CT_Inline">
|
||||||
// <xsd:sequence>
|
// <xsd:sequence>
|
||||||
@ -28,29 +29,41 @@ interface InlineOptions {
|
|||||||
// <xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
|
// <xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
|
||||||
// <xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
|
// <xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
|
||||||
// </xsd:complexType>
|
// </xsd:complexType>
|
||||||
export class Inline extends XmlComponent {
|
export const createInline = ({ mediaData, transform, docProperties, outline }: InlineOptions): XmlComponent =>
|
||||||
private readonly extent: Extent;
|
new BuilderElement({
|
||||||
private readonly graphic: Graphic;
|
name: "wp:inline",
|
||||||
|
attributes: {
|
||||||
public constructor({ mediaData, transform, docProperties }: InlineOptions) {
|
distanceTop: {
|
||||||
super("wp:inline");
|
key: "distT",
|
||||||
|
value: 0,
|
||||||
this.root.push(
|
},
|
||||||
new InlineAttributes({
|
distanceBottom: {
|
||||||
distT: 0,
|
key: "distB",
|
||||||
distB: 0,
|
value: 0,
|
||||||
distL: 0,
|
},
|
||||||
distR: 0,
|
distanceLeft: {
|
||||||
}),
|
key: "distL",
|
||||||
);
|
value: 0,
|
||||||
|
},
|
||||||
this.extent = new Extent(transform.emus.x, transform.emus.y);
|
distanceRight: {
|
||||||
this.graphic = new Graphic(mediaData, transform);
|
key: "distR",
|
||||||
|
value: 0,
|
||||||
this.root.push(this.extent);
|
},
|
||||||
this.root.push(new EffectExtent());
|
},
|
||||||
this.root.push(new DocProperties(docProperties));
|
children: [
|
||||||
this.root.push(new GraphicFrameProperties());
|
new Extent(transform.emus.x, transform.emus.y),
|
||||||
this.root.push(this.graphic);
|
createEffectExtent(
|
||||||
}
|
outline
|
||||||
}
|
? {
|
||||||
|
top: (outline.width ?? 9525) * 2,
|
||||||
|
right: (outline.width ?? 9525) * 2,
|
||||||
|
bottom: (outline.width ?? 9525) * 2,
|
||||||
|
left: (outline.width ?? 9525) * 2,
|
||||||
|
}
|
||||||
|
: { top: 0, right: 0, bottom: 0, left: 0 },
|
||||||
|
),
|
||||||
|
new DocProperties(docProperties),
|
||||||
|
new GraphicFrameProperties(),
|
||||||
|
new Graphic({ mediaData, transform, outline }),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
@ -17,6 +17,7 @@ import { Styles } from "./styles";
|
|||||||
import { ExternalStylesFactory } from "./styles/external-styles-factory";
|
import { ExternalStylesFactory } from "./styles/external-styles-factory";
|
||||||
import { DefaultStylesFactory } from "./styles/factory";
|
import { DefaultStylesFactory } from "./styles/factory";
|
||||||
import { FileChild } from "./file-child";
|
import { FileChild } from "./file-child";
|
||||||
|
import { FontWrapper } from "./fonts/font-wrapper";
|
||||||
|
|
||||||
export interface ISectionOptions {
|
export interface ISectionOptions {
|
||||||
readonly headers?: {
|
readonly headers?: {
|
||||||
@ -53,6 +54,7 @@ export class File {
|
|||||||
private readonly appProperties: AppProperties;
|
private readonly appProperties: AppProperties;
|
||||||
private readonly styles: Styles;
|
private readonly styles: Styles;
|
||||||
private readonly comments: Comments;
|
private readonly comments: Comments;
|
||||||
|
private readonly fontWrapper: FontWrapper;
|
||||||
|
|
||||||
public constructor(options: IPropertiesOptions) {
|
public constructor(options: IPropertiesOptions) {
|
||||||
this.coreProperties = new CoreProperties({
|
this.coreProperties = new CoreProperties({
|
||||||
@ -109,6 +111,8 @@ export class File {
|
|||||||
this.footnotesWrapper.View.createFootNote(parseFloat(key), options.footnotes[key].children);
|
this.footnotesWrapper.View.createFootNote(parseFloat(key), options.footnotes[key].children);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.fontWrapper = new FontWrapper(options.fonts ?? []);
|
||||||
}
|
}
|
||||||
|
|
||||||
private addSection({ headers = {}, footers = {}, children, properties }: ISectionOptions): void {
|
private addSection({ headers = {}, footers = {}, children, properties }: ISectionOptions): void {
|
||||||
@ -292,4 +296,8 @@ export class File {
|
|||||||
public get Comments(): Comments {
|
public get Comments(): Comments {
|
||||||
return this.comments;
|
return this.comments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get FontTable(): FontWrapper {
|
||||||
|
return this.fontWrapper;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
33
src/file/fonts/create-regular-font.ts
Normal file
33
src/file/fonts/create-regular-font.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
import { CharacterSet, createFont } from "./font";
|
||||||
|
|
||||||
|
export const createRegularFont = ({
|
||||||
|
name,
|
||||||
|
index,
|
||||||
|
fontKey,
|
||||||
|
characterSet,
|
||||||
|
}: {
|
||||||
|
readonly name: string;
|
||||||
|
readonly index: number;
|
||||||
|
readonly fontKey: string;
|
||||||
|
readonly characterSet?: (typeof CharacterSet)[keyof typeof CharacterSet];
|
||||||
|
}): XmlComponent =>
|
||||||
|
createFont({
|
||||||
|
name,
|
||||||
|
sig: {
|
||||||
|
usb0: "E0002AFF",
|
||||||
|
usb1: "C000247B",
|
||||||
|
usb2: "00000009",
|
||||||
|
usb3: "00000000",
|
||||||
|
csb0: "000001FF",
|
||||||
|
csb1: "00000000",
|
||||||
|
},
|
||||||
|
charset: characterSet,
|
||||||
|
family: "auto",
|
||||||
|
pitch: "variable",
|
||||||
|
embedRegular: {
|
||||||
|
fontKey,
|
||||||
|
id: `rId${index}`,
|
||||||
|
},
|
||||||
|
});
|
44
src/file/fonts/font-table.ts
Normal file
44
src/file/fonts/font-table.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
import { createRegularFont } from "./create-regular-font";
|
||||||
|
import { FontOptionsWithKey } from "./font-wrapper";
|
||||||
|
import { CharacterSet } from "./font";
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_FontsList">
|
||||||
|
// <xsd:sequence>
|
||||||
|
// <xsd:element name="font" type="CT_Font" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// </xsd:complexType>
|
||||||
|
|
||||||
|
export type FontOptions = {
|
||||||
|
readonly name: string;
|
||||||
|
readonly data: Buffer;
|
||||||
|
readonly characterSet?: (typeof CharacterSet)[keyof typeof CharacterSet];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createFontTable = (fonts: readonly FontOptionsWithKey[]): XmlComponent =>
|
||||||
|
// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_Font_topic_ID0ERNCU.html
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_fonts.html
|
||||||
|
new BuilderElement({
|
||||||
|
name: "w:fonts",
|
||||||
|
attributes: {
|
||||||
|
mc: { key: "xmlns:mc", value: "http://schemas.openxmlformats.org/markup-compatibility/2006" },
|
||||||
|
r: { key: "xmlns:r", value: "http://schemas.openxmlformats.org/officeDocument/2006/relationships" },
|
||||||
|
w: { key: "xmlns:w", value: "http://schemas.openxmlformats.org/wordprocessingml/2006/main" },
|
||||||
|
w14: { key: "xmlns:w14", value: "http://schemas.microsoft.com/office/word/2010/wordml" },
|
||||||
|
w15: { key: "xmlns:w15", value: "http://schemas.microsoft.com/office/word/2012/wordml" },
|
||||||
|
w16cex: { key: "xmlns:w16cex", value: "http://schemas.microsoft.com/office/word/2018/wordml/cex" },
|
||||||
|
w16cid: { key: "xmlns:w16cid", value: "http://schemas.microsoft.com/office/word/2016/wordml/cid" },
|
||||||
|
w16: { key: "xmlns:w16", value: "http://schemas.microsoft.com/office/word/2018/wordml" },
|
||||||
|
w16sdtdh: { key: "xmlns:w16sdtdh", value: "http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" },
|
||||||
|
w16se: { key: "xmlns:w16se", value: "http://schemas.microsoft.com/office/word/2015/wordml/symex" },
|
||||||
|
Ignorable: { key: "mc:Ignorable", value: "w14 w15 w16se w16cid w16 w16cex w16sdtdh" },
|
||||||
|
},
|
||||||
|
children: fonts.map((font, i) =>
|
||||||
|
createRegularFont({
|
||||||
|
name: font.name,
|
||||||
|
index: i + 1,
|
||||||
|
fontKey: font.fontKey,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
});
|
36
src/file/fonts/font-wrapper.ts
Normal file
36
src/file/fonts/font-wrapper.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { IViewWrapper } from "@file/document-wrapper";
|
||||||
|
import { Relationships } from "@file/relationships";
|
||||||
|
import { XmlComponent } from "@file/xml-components";
|
||||||
|
import { uniqueUuid } from "@util/convenience-functions";
|
||||||
|
|
||||||
|
import { FontOptions, createFontTable } from "./font-table";
|
||||||
|
|
||||||
|
export type FontOptionsWithKey = FontOptions & { readonly fontKey: string };
|
||||||
|
|
||||||
|
export class FontWrapper implements IViewWrapper {
|
||||||
|
private readonly fontTable: XmlComponent;
|
||||||
|
private readonly relationships: Relationships;
|
||||||
|
public readonly fontOptionsWithKey: readonly FontOptionsWithKey[] = [];
|
||||||
|
|
||||||
|
public constructor(public readonly options: readonly FontOptions[]) {
|
||||||
|
this.fontOptionsWithKey = options.map((o) => ({ ...o, fontKey: uniqueUuid() }));
|
||||||
|
this.fontTable = createFontTable(this.fontOptionsWithKey);
|
||||||
|
this.relationships = new Relationships();
|
||||||
|
|
||||||
|
for (let i = 0; i < options.length; i++) {
|
||||||
|
this.relationships.createRelationship(
|
||||||
|
i + 1,
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/font",
|
||||||
|
`fonts/${options[i].name}.odttf`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get View(): XmlComponent {
|
||||||
|
return this.fontTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get Relationships(): Relationships {
|
||||||
|
return this.relationships;
|
||||||
|
}
|
||||||
|
}
|
223
src/file/fonts/font.spec.ts
Normal file
223
src/file/fonts/font.spec.ts
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { Formatter } from "@export/formatter";
|
||||||
|
|
||||||
|
import { createFont } from "./font";
|
||||||
|
|
||||||
|
describe("font", () => {
|
||||||
|
it("should work", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
altName: "Times New Roman",
|
||||||
|
family: "roman",
|
||||||
|
charset: "00",
|
||||||
|
panose1: "02020603050405020304",
|
||||||
|
pitch: "variable",
|
||||||
|
embedRegular: {
|
||||||
|
id: "rId0",
|
||||||
|
fontKey: "00000000-0000-0000-0000-000000000000",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:font": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"w:name": "Times New Roman",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:altName": {
|
||||||
|
_attr: {
|
||||||
|
"w:val": "Times New Roman",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:panose1": {
|
||||||
|
_attr: {
|
||||||
|
"w:val": "02020603050405020304",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:charset": {
|
||||||
|
_attr: {
|
||||||
|
"w:val": "00",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:family": {
|
||||||
|
_attr: {
|
||||||
|
"w:val": "roman",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:pitch": {
|
||||||
|
_attr: {
|
||||||
|
"w:val": "variable",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:embedRegular": {
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId0",
|
||||||
|
"w:fontKey": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work for embedBold", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
embedBold: {
|
||||||
|
id: "rId0",
|
||||||
|
fontKey: "00000000-0000-0000-0000-000000000000",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"w:font": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"w:embedBold": {
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId0",
|
||||||
|
"w:fontKey": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work for embedBoldItalic", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
embedBoldItalic: {
|
||||||
|
id: "rId0",
|
||||||
|
fontKey: "00000000-0000-0000-0000-000000000000",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"w:font": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"w:embedBoldItalic": {
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId0",
|
||||||
|
"w:fontKey": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work for embedItalic", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
embedItalic: {
|
||||||
|
id: "rId0",
|
||||||
|
fontKey: "00000000-0000-0000-0000-000000000000",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"w:font": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"w:embedItalic": {
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId0",
|
||||||
|
"w:fontKey": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work for notTrueType", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
embedRegular: {
|
||||||
|
id: "rId0",
|
||||||
|
fontKey: "00000000-0000-0000-0000-000000000000",
|
||||||
|
subsetted: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"w:font": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"w:embedRegular": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId0",
|
||||||
|
"w:fontKey": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:subsetted": {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work for subsetted", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
notTrueType: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"w:font": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"w:notTrueType": {},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work without fontKey", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createFont({
|
||||||
|
name: "Times New Roman",
|
||||||
|
embedItalic: {
|
||||||
|
id: "rId0",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"w:font": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"w:embedItalic": {
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
156
src/file/fonts/font.ts
Normal file
156
src/file/fonts/font.ts
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
import { BuilderElement, createStringElement, OnOffElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_Font">
|
||||||
|
// <xsd:sequence>
|
||||||
|
// <xsd:element name="altName" type="CT_String" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="panose1" type="CT_Panose" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="charset" type="CT_Charset" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="family" type="CT_FontFamily" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="notTrueType" type="CT_OnOff" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="pitch" type="CT_Pitch" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="sig" type="CT_FontSig" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="embedRegular" type="CT_FontRel" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="embedBold" type="CT_FontRel" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="embedItalic" type="CT_FontRel" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xsd:element name="embedBoldItalic" type="CT_FontRel" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// <xsd:attribute name="name" type="s:ST_String" use="required"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_FontRel">
|
||||||
|
// <xsd:complexContent>
|
||||||
|
// <xsd:extension base="CT_Rel">
|
||||||
|
// <xsd:attribute name="fontKey" type="s:ST_Guid" />
|
||||||
|
// <xsd:attribute name="subsetted" type="s:ST_OnOff" />
|
||||||
|
// </xsd:extension>
|
||||||
|
// </xsd:complexContent>
|
||||||
|
// </xsd:complexType>
|
||||||
|
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_embedRegular-1.html
|
||||||
|
export interface IFontRelationshipOptions {
|
||||||
|
/**
|
||||||
|
* Relationship to Part
|
||||||
|
*/
|
||||||
|
readonly id: string;
|
||||||
|
/**
|
||||||
|
* Embedded Font Obfuscation Key
|
||||||
|
*/
|
||||||
|
readonly fontKey?: string;
|
||||||
|
/**
|
||||||
|
* Embedded Font Is Subsetted
|
||||||
|
*/
|
||||||
|
readonly subsetted?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CharacterSet = {
|
||||||
|
ANSI: "00",
|
||||||
|
DEFAULT: "01",
|
||||||
|
SYMBOL: "02",
|
||||||
|
MAC: "4D",
|
||||||
|
JIS: "80",
|
||||||
|
HANGUL: "81",
|
||||||
|
JOHAB: "82",
|
||||||
|
GB_2312: "86",
|
||||||
|
CHINESEBIG5: "88",
|
||||||
|
GREEK: "A1",
|
||||||
|
TURKISH: "A2",
|
||||||
|
VIETNAMESE: "A3",
|
||||||
|
HEBREW: "B1",
|
||||||
|
ARABIC: "B2",
|
||||||
|
BALTIC: "BA",
|
||||||
|
RUSSIAN: "CC",
|
||||||
|
THAI: "DE",
|
||||||
|
EASTEUROPE: "EE",
|
||||||
|
OEM: "FF",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type FontOptions = {
|
||||||
|
readonly name: string;
|
||||||
|
readonly altName?: string;
|
||||||
|
readonly panose1?: string;
|
||||||
|
readonly charset?: (typeof CharacterSet)[keyof typeof CharacterSet];
|
||||||
|
readonly family?: string;
|
||||||
|
readonly notTrueType?: boolean;
|
||||||
|
readonly pitch?: string;
|
||||||
|
readonly sig?: {
|
||||||
|
readonly usb0: string;
|
||||||
|
readonly usb1: string;
|
||||||
|
readonly usb2: string;
|
||||||
|
readonly usb3: string;
|
||||||
|
readonly csb0: string;
|
||||||
|
readonly csb1: string;
|
||||||
|
};
|
||||||
|
readonly embedRegular?: IFontRelationshipOptions;
|
||||||
|
readonly embedBold?: IFontRelationshipOptions;
|
||||||
|
readonly embedItalic?: IFontRelationshipOptions;
|
||||||
|
readonly embedBoldItalic?: IFontRelationshipOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFontRelationship = ({ id, fontKey, subsetted }: IFontRelationshipOptions, name: string): XmlComponent =>
|
||||||
|
new BuilderElement({
|
||||||
|
name,
|
||||||
|
attributes: {
|
||||||
|
id: { key: "r:id", value: id },
|
||||||
|
...(fontKey ? { fontKey: { key: "w:fontKey", value: `{${fontKey}}` } } : {}),
|
||||||
|
},
|
||||||
|
children: [...(subsetted ? [new OnOffElement("w:subsetted", subsetted)] : [])],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createFont = ({
|
||||||
|
name,
|
||||||
|
altName,
|
||||||
|
panose1,
|
||||||
|
charset,
|
||||||
|
family,
|
||||||
|
notTrueType,
|
||||||
|
pitch,
|
||||||
|
sig,
|
||||||
|
embedRegular,
|
||||||
|
embedBold,
|
||||||
|
embedItalic,
|
||||||
|
embedBoldItalic,
|
||||||
|
}: FontOptions): XmlComponent =>
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_font-1.html
|
||||||
|
new BuilderElement({
|
||||||
|
name: "w:font",
|
||||||
|
attributes: {
|
||||||
|
name: { key: "w:name", value: name },
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_altName-1.html
|
||||||
|
...(altName ? [createStringElement("w:altName", altName)] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_panose1-1.html
|
||||||
|
...(panose1 ? [createStringElement("w:panose1", panose1)] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_charset-1.html
|
||||||
|
...(charset ? [createStringElement("w:charset", charset)] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_family-1.html
|
||||||
|
...(family ? [createStringElement("w:family", family)] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_notTrueType-1.html
|
||||||
|
...(notTrueType ? [new OnOffElement("w:notTrueType", notTrueType)] : []),
|
||||||
|
...(pitch ? [createStringElement("w:pitch", pitch)] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_sig-1.html
|
||||||
|
...(sig
|
||||||
|
? [
|
||||||
|
new BuilderElement({
|
||||||
|
name: "w:sig",
|
||||||
|
attributes: {
|
||||||
|
usb0: { key: "w:usb0", value: sig.usb0 },
|
||||||
|
usb1: { key: "w:usb1", value: sig.usb1 },
|
||||||
|
usb2: { key: "w:usb2", value: sig.usb2 },
|
||||||
|
usb3: { key: "w:usb3", value: sig.usb3 },
|
||||||
|
csb0: { key: "w:csb0", value: sig.csb0 },
|
||||||
|
csb1: { key: "w:csb1", value: sig.csb1 },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_embedRegular-1.html
|
||||||
|
...(embedRegular ? [createFontRelationship(embedRegular, "w:embedRegular")] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_embedBold-1.html
|
||||||
|
...(embedBold ? [createFontRelationship(embedBold, "w:embedBold")] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_embedItalic-1.html
|
||||||
|
...(embedItalic ? [createFontRelationship(embedItalic, "w:embedItalic")] : []),
|
||||||
|
// http://www.datypic.com/sc/ooxml/e-w_embedBoldItalic-1.html
|
||||||
|
...(embedBoldItalic ? [createFontRelationship(embedBoldItalic, "w:embedBoldItalic")] : []),
|
||||||
|
],
|
||||||
|
});
|
1
src/file/fonts/index.ts
Normal file
1
src/file/fonts/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { CharacterSet } from "./font";
|
22
src/file/fonts/obfuscate-ttf-to-odttf.ts
Normal file
22
src/file/fonts/obfuscate-ttf-to-odttf.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
const obfuscatedStartOffset = 0;
|
||||||
|
const obfuscatedEndOffset = 32;
|
||||||
|
const guidSize = 32;
|
||||||
|
|
||||||
|
export const obfuscate = (buf: Buffer, fontKey: string): Buffer => {
|
||||||
|
const guid = fontKey.replace(/-/g, "");
|
||||||
|
if (guid.length !== guidSize) {
|
||||||
|
throw new Error(`Error: Cannot extract GUID from font filename: ${fontKey}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hexStrings = guid.replace(/(..)/g, "$1 ").trim().split(" ");
|
||||||
|
const hexNumbers = hexStrings.map((hexString) => parseInt(hexString, 16));
|
||||||
|
// eslint-disable-next-line functional/immutable-data
|
||||||
|
hexNumbers.reverse();
|
||||||
|
|
||||||
|
const bytesToObfuscate = buf.slice(obfuscatedStartOffset, obfuscatedEndOffset);
|
||||||
|
// eslint-disable-next-line no-bitwise
|
||||||
|
const obfuscatedBytes = bytesToObfuscate.map((byte, i) => byte ^ hexNumbers[i % hexNumbers.length]);
|
||||||
|
|
||||||
|
const out = Buffer.concat([buf.slice(0, obfuscatedStartOffset), obfuscatedBytes, buf.slice(obfuscatedEndOffset)]);
|
||||||
|
return out;
|
||||||
|
};
|
14
src/file/fonts/obsfuscate-ttf-to-odtts.spec.ts
Normal file
14
src/file/fonts/obsfuscate-ttf-to-odtts.spec.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { obfuscate } from "./obfuscate-ttf-to-odttf";
|
||||||
|
|
||||||
|
describe("obfuscate", () => {
|
||||||
|
it("should work", () => {
|
||||||
|
const buffer = obfuscate(Buffer.from(""), "00000000-0000-0000-0000-000000000000");
|
||||||
|
expect(buffer).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw error if uuid is not correct", () => {
|
||||||
|
expect(() => obfuscate(Buffer.from(""), "bad-uuid")).toThrowError();
|
||||||
|
});
|
||||||
|
});
|
@ -18,3 +18,4 @@ export * from "./shared";
|
|||||||
export * from "./border";
|
export * from "./border";
|
||||||
export * from "./vertical-align";
|
export * from "./vertical-align";
|
||||||
export * from "./checkbox";
|
export * from "./checkbox";
|
||||||
|
export * from "./fonts";
|
||||||
|
@ -3,154 +3,144 @@ import { describe, expect, it } from "vitest";
|
|||||||
import { Formatter } from "@export/formatter";
|
import { Formatter } from "@export/formatter";
|
||||||
import { HorizontalPositionAlign, VerticalPositionAlign } from "@file/shared";
|
import { HorizontalPositionAlign, VerticalPositionAlign } from "@file/shared";
|
||||||
|
|
||||||
import { FrameAnchorType, FrameProperties } from "./frame-properties";
|
import { FrameAnchorType, createFrameProperties } from "./frame-properties";
|
||||||
|
|
||||||
describe("FrameProperties", () => {
|
describe("createFrameProperties", () => {
|
||||||
describe("#constructor()", () => {
|
it("should create", () => {
|
||||||
it("should create", () => {
|
const currentFrameProperties = createFrameProperties({
|
||||||
const currentFrameProperties = new FrameProperties({
|
type: "absolute",
|
||||||
position: {
|
position: {
|
||||||
x: 1000,
|
x: 1000,
|
||||||
y: 3000,
|
y: 3000,
|
||||||
},
|
},
|
||||||
width: 4000,
|
width: 4000,
|
||||||
height: 1000,
|
height: 1000,
|
||||||
anchor: {
|
anchor: {
|
||||||
horizontal: FrameAnchorType.MARGIN,
|
horizontal: FrameAnchorType.MARGIN,
|
||||||
vertical: FrameAnchorType.MARGIN,
|
vertical: FrameAnchorType.MARGIN,
|
||||||
},
|
},
|
||||||
alignment: {
|
|
||||||
x: HorizontalPositionAlign.CENTER,
|
|
||||||
y: VerticalPositionAlign.TOP,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const tree = new Formatter().format(currentFrameProperties);
|
|
||||||
expect(tree).to.deep.equal({
|
|
||||||
"w:framePr": {
|
|
||||||
_attr: {
|
|
||||||
"w:h": 1000,
|
|
||||||
"w:hAnchor": "margin",
|
|
||||||
"w:vAnchor": "margin",
|
|
||||||
"w:w": 4000,
|
|
||||||
"w:x": 1000,
|
|
||||||
"w:xAlign": "center",
|
|
||||||
"w:y": 3000,
|
|
||||||
"w:yAlign": "top",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create with the space attribute", () => {
|
const tree = new Formatter().format(currentFrameProperties);
|
||||||
const currentFrameProperties = new FrameProperties({
|
expect(tree).to.deep.equal({
|
||||||
position: {
|
"w:framePr": {
|
||||||
x: 1000,
|
_attr: {
|
||||||
y: 3000,
|
"w:h": 1000,
|
||||||
|
"w:hAnchor": "margin",
|
||||||
|
"w:vAnchor": "margin",
|
||||||
|
"w:w": 4000,
|
||||||
|
"w:x": 1000,
|
||||||
|
"w:y": 3000,
|
||||||
},
|
},
|
||||||
width: 4000,
|
},
|
||||||
height: 1000,
|
});
|
||||||
anchor: {
|
});
|
||||||
horizontal: FrameAnchorType.MARGIN,
|
|
||||||
vertical: FrameAnchorType.MARGIN,
|
|
||||||
},
|
|
||||||
alignment: {
|
|
||||||
x: HorizontalPositionAlign.CENTER,
|
|
||||||
y: VerticalPositionAlign.TOP,
|
|
||||||
},
|
|
||||||
space: {
|
|
||||||
horizontal: 100,
|
|
||||||
vertical: 200,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const tree = new Formatter().format(currentFrameProperties);
|
it("should create with the space attribute", () => {
|
||||||
expect(tree).to.deep.equal({
|
const currentFrameProperties = createFrameProperties({
|
||||||
"w:framePr": {
|
type: "absolute",
|
||||||
_attr: {
|
position: {
|
||||||
"w:h": 1000,
|
x: 1000,
|
||||||
"w:hAnchor": "margin",
|
y: 3000,
|
||||||
"w:vAnchor": "margin",
|
},
|
||||||
"w:w": 4000,
|
width: 4000,
|
||||||
"w:x": 1000,
|
height: 1000,
|
||||||
"w:xAlign": "center",
|
anchor: {
|
||||||
"w:y": 3000,
|
horizontal: FrameAnchorType.MARGIN,
|
||||||
"w:yAlign": "top",
|
vertical: FrameAnchorType.MARGIN,
|
||||||
"w:hSpace": 100,
|
},
|
||||||
"w:vSpace": 200,
|
space: {
|
||||||
},
|
horizontal: 100,
|
||||||
},
|
vertical: 200,
|
||||||
});
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create without x and y", () => {
|
const tree = new Formatter().format(currentFrameProperties);
|
||||||
const currentFrameProperties = new FrameProperties({
|
expect(tree).to.deep.equal({
|
||||||
width: 4000,
|
"w:framePr": {
|
||||||
height: 1000,
|
_attr: {
|
||||||
anchor: {
|
"w:h": 1000,
|
||||||
horizontal: FrameAnchorType.MARGIN,
|
"w:hAnchor": "margin",
|
||||||
vertical: FrameAnchorType.MARGIN,
|
"w:vAnchor": "margin",
|
||||||
|
"w:w": 4000,
|
||||||
|
"w:x": 1000,
|
||||||
|
"w:y": 3000,
|
||||||
|
"w:hSpace": 100,
|
||||||
|
"w:vSpace": 200,
|
||||||
},
|
},
|
||||||
alignment: {
|
},
|
||||||
x: HorizontalPositionAlign.CENTER,
|
});
|
||||||
y: VerticalPositionAlign.TOP,
|
});
|
||||||
},
|
|
||||||
space: {
|
|
||||||
horizontal: 100,
|
|
||||||
vertical: 200,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const tree = new Formatter().format(currentFrameProperties);
|
it("should create without x and y", () => {
|
||||||
expect(tree).to.deep.equal({
|
const currentFrameProperties = createFrameProperties({
|
||||||
"w:framePr": {
|
type: "alignment",
|
||||||
_attr: {
|
width: 4000,
|
||||||
"w:h": 1000,
|
height: 1000,
|
||||||
"w:hAnchor": "margin",
|
anchor: {
|
||||||
"w:vAnchor": "margin",
|
horizontal: FrameAnchorType.MARGIN,
|
||||||
"w:w": 4000,
|
vertical: FrameAnchorType.MARGIN,
|
||||||
"w:xAlign": "center",
|
},
|
||||||
"w:yAlign": "top",
|
alignment: {
|
||||||
"w:hSpace": 100,
|
x: HorizontalPositionAlign.CENTER,
|
||||||
"w:vSpace": 200,
|
y: VerticalPositionAlign.TOP,
|
||||||
},
|
},
|
||||||
},
|
space: {
|
||||||
});
|
horizontal: 100,
|
||||||
|
vertical: 200,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create without alignments", () => {
|
const tree = new Formatter().format(currentFrameProperties);
|
||||||
const currentFrameProperties = new FrameProperties({
|
expect(tree).to.deep.equal({
|
||||||
position: {
|
"w:framePr": {
|
||||||
x: 1000,
|
_attr: {
|
||||||
y: 3000,
|
"w:h": 1000,
|
||||||
|
"w:hAnchor": "margin",
|
||||||
|
"w:vAnchor": "margin",
|
||||||
|
"w:w": 4000,
|
||||||
|
"w:xAlign": "center",
|
||||||
|
"w:yAlign": "top",
|
||||||
|
"w:hSpace": 100,
|
||||||
|
"w:vSpace": 200,
|
||||||
},
|
},
|
||||||
width: 4000,
|
},
|
||||||
height: 1000,
|
});
|
||||||
anchor: {
|
});
|
||||||
horizontal: FrameAnchorType.MARGIN,
|
|
||||||
vertical: FrameAnchorType.MARGIN,
|
|
||||||
},
|
|
||||||
space: {
|
|
||||||
horizontal: 100,
|
|
||||||
vertical: 200,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const tree = new Formatter().format(currentFrameProperties);
|
it("should create without alignments", () => {
|
||||||
expect(tree).to.deep.equal({
|
const currentFrameProperties = createFrameProperties({
|
||||||
"w:framePr": {
|
type: "absolute",
|
||||||
_attr: {
|
position: {
|
||||||
"w:h": 1000,
|
x: 1000,
|
||||||
"w:hAnchor": "margin",
|
y: 3000,
|
||||||
"w:vAnchor": "margin",
|
},
|
||||||
"w:w": 4000,
|
width: 4000,
|
||||||
"w:x": 1000,
|
height: 1000,
|
||||||
"w:y": 3000,
|
anchor: {
|
||||||
"w:hSpace": 100,
|
horizontal: FrameAnchorType.MARGIN,
|
||||||
"w:vSpace": 200,
|
vertical: FrameAnchorType.MARGIN,
|
||||||
},
|
},
|
||||||
|
space: {
|
||||||
|
horizontal: 100,
|
||||||
|
vertical: 200,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const tree = new Formatter().format(currentFrameProperties);
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:framePr": {
|
||||||
|
_attr: {
|
||||||
|
"w:h": 1000,
|
||||||
|
"w:hAnchor": "margin",
|
||||||
|
"w:vAnchor": "margin",
|
||||||
|
"w:w": 4000,
|
||||||
|
"w:x": 1000,
|
||||||
|
"w:y": 3000,
|
||||||
|
"w:hSpace": 100,
|
||||||
|
"w:vSpace": 200,
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// http://officeopenxml.com/WPparagraph-textFrames.php
|
// http://officeopenxml.com/WPparagraph-textFrames.php
|
||||||
import { HorizontalPositionAlign, VerticalPositionAlign } from "@file/shared/alignment";
|
import { HorizontalPositionAlign, VerticalPositionAlign } from "@file/shared/alignment";
|
||||||
import { HeightRule } from "@file/table";
|
import { HeightRule } from "@file/table";
|
||||||
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
export const DropCapType = {
|
export const DropCapType = {
|
||||||
NONE: "none",
|
NONE: "none",
|
||||||
@ -44,6 +44,7 @@ interface IBaseFrameOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IXYFrameOptions extends IBaseFrameOptions {
|
export interface IXYFrameOptions extends IBaseFrameOptions {
|
||||||
|
readonly type: "absolute";
|
||||||
readonly position: {
|
readonly position: {
|
||||||
readonly x: number;
|
readonly x: number;
|
||||||
readonly y: number;
|
readonly y: number;
|
||||||
@ -51,6 +52,7 @@ export interface IXYFrameOptions extends IBaseFrameOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IAlignmentFrameOptions extends IBaseFrameOptions {
|
export interface IAlignmentFrameOptions extends IBaseFrameOptions {
|
||||||
|
readonly type: "alignment";
|
||||||
readonly alignment: {
|
readonly alignment: {
|
||||||
readonly x: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign];
|
readonly x: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign];
|
||||||
readonly y: (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign];
|
readonly y: (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign];
|
||||||
@ -61,7 +63,24 @@ export interface IAlignmentFrameOptions extends IBaseFrameOptions {
|
|||||||
// https://stackoverflow.com/q/46370222/3481582
|
// https://stackoverflow.com/q/46370222/3481582
|
||||||
export type IFrameOptions = IXYFrameOptions | IAlignmentFrameOptions;
|
export type IFrameOptions = IXYFrameOptions | IAlignmentFrameOptions;
|
||||||
|
|
||||||
export class FramePropertiesAttributes extends XmlAttributeComponent<{
|
// <xsd:complexType name="CT_FramePr">
|
||||||
|
// <xsd:attribute name="dropCap" type="ST_DropCap" use="optional"/>
|
||||||
|
// <xsd:attribute name="lines" type="ST_DecimalNumber" use="optional"/>
|
||||||
|
// <xsd:attribute name="w" type="s:ST_TwipsMeasure" use="optional"/>
|
||||||
|
// <xsd:attribute name="h" type="s:ST_TwipsMeasure" use="optional"/>
|
||||||
|
// <xsd:attribute name="vSpace" type="s:ST_TwipsMeasure" use="optional"/>
|
||||||
|
// <xsd:attribute name="hSpace" type="s:ST_TwipsMeasure" use="optional"/>
|
||||||
|
// <xsd:attribute name="wrap" type="ST_Wrap" use="optional"/>
|
||||||
|
// <xsd:attribute name="hAnchor" type="ST_HAnchor" use="optional"/>
|
||||||
|
// <xsd:attribute name="vAnchor" type="ST_VAnchor" use="optional"/>
|
||||||
|
// <xsd:attribute name="x" type="ST_SignedTwipsMeasure" use="optional"/>
|
||||||
|
// <xsd:attribute name="xAlign" type="s:ST_XAlign" use="optional"/>
|
||||||
|
// <xsd:attribute name="y" type="ST_SignedTwipsMeasure" use="optional"/>
|
||||||
|
// <xsd:attribute name="yAlign" type="s:ST_YAlign" use="optional"/>
|
||||||
|
// <xsd:attribute name="hRule" type="ST_HeightRule" use="optional"/>
|
||||||
|
// <xsd:attribute name="anchorLock" type="s:ST_OnOff" use="optional"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
type FramePropertiesAttributes = {
|
||||||
readonly anchorLock?: boolean;
|
readonly anchorLock?: boolean;
|
||||||
readonly dropCap?: (typeof DropCapType)[keyof typeof DropCapType];
|
readonly dropCap?: (typeof DropCapType)[keyof typeof DropCapType];
|
||||||
readonly width: number;
|
readonly width: number;
|
||||||
@ -77,47 +96,71 @@ export class FramePropertiesAttributes extends XmlAttributeComponent<{
|
|||||||
readonly rule?: (typeof HeightRule)[keyof typeof HeightRule];
|
readonly rule?: (typeof HeightRule)[keyof typeof HeightRule];
|
||||||
readonly alignmentX?: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign];
|
readonly alignmentX?: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign];
|
||||||
readonly alignmentY?: (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign];
|
readonly alignmentY?: (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign];
|
||||||
}> {
|
};
|
||||||
protected readonly xmlKeys = {
|
|
||||||
anchorLock: "w:anchorLock",
|
|
||||||
dropCap: "w:dropCap",
|
|
||||||
width: "w:w",
|
|
||||||
height: "w:h",
|
|
||||||
x: "w:x",
|
|
||||||
y: "w:y",
|
|
||||||
anchorHorizontal: "w:hAnchor",
|
|
||||||
anchorVertical: "w:vAnchor",
|
|
||||||
spaceHorizontal: "w:hSpace",
|
|
||||||
spaceVertical: "w:vSpace",
|
|
||||||
rule: "w:hRule",
|
|
||||||
alignmentX: "w:xAlign",
|
|
||||||
alignmentY: "w:yAlign",
|
|
||||||
lines: "w:lines",
|
|
||||||
wrap: "w:wrap",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export class FrameProperties extends XmlComponent {
|
export const createFrameProperties = (options: IFrameOptions): XmlComponent =>
|
||||||
public constructor(options: IFrameOptions) {
|
new BuilderElement<FramePropertiesAttributes>({
|
||||||
super("w:framePr");
|
name: "w:framePr",
|
||||||
this.root.push(
|
attributes: {
|
||||||
new FramePropertiesAttributes({
|
anchorLock: {
|
||||||
anchorLock: options.anchorLock,
|
key: "w:anchorLock",
|
||||||
dropCap: options.dropCap,
|
value: options.anchorLock,
|
||||||
width: options.width,
|
},
|
||||||
height: options.height,
|
dropCap: {
|
||||||
x: (options as IXYFrameOptions).position ? (options as IXYFrameOptions).position.x : undefined,
|
key: "w:dropCap",
|
||||||
y: (options as IXYFrameOptions).position ? (options as IXYFrameOptions).position.y : undefined,
|
value: options.dropCap,
|
||||||
anchorHorizontal: options.anchor.horizontal,
|
},
|
||||||
anchorVertical: options.anchor.vertical,
|
width: {
|
||||||
spaceHorizontal: options.space?.horizontal,
|
key: "w:w",
|
||||||
spaceVertical: options.space?.vertical,
|
value: options.width,
|
||||||
rule: options.rule,
|
},
|
||||||
alignmentX: (options as IAlignmentFrameOptions).alignment ? (options as IAlignmentFrameOptions).alignment.x : undefined,
|
height: {
|
||||||
alignmentY: (options as IAlignmentFrameOptions).alignment ? (options as IAlignmentFrameOptions).alignment.y : undefined,
|
key: "w:h",
|
||||||
lines: options.lines,
|
value: options.height,
|
||||||
wrap: options.wrap,
|
},
|
||||||
}),
|
x: {
|
||||||
);
|
key: "w:x",
|
||||||
}
|
value: (options as IXYFrameOptions).position ? (options as IXYFrameOptions).position.x : undefined,
|
||||||
}
|
},
|
||||||
|
y: {
|
||||||
|
key: "w:y",
|
||||||
|
value: (options as IXYFrameOptions).position ? (options as IXYFrameOptions).position.y : undefined,
|
||||||
|
},
|
||||||
|
anchorHorizontal: {
|
||||||
|
key: "w:hAnchor",
|
||||||
|
value: options.anchor.horizontal,
|
||||||
|
},
|
||||||
|
anchorVertical: {
|
||||||
|
key: "w:vAnchor",
|
||||||
|
value: options.anchor.vertical,
|
||||||
|
},
|
||||||
|
spaceHorizontal: {
|
||||||
|
key: "w:hSpace",
|
||||||
|
value: options.space?.horizontal,
|
||||||
|
},
|
||||||
|
spaceVertical: {
|
||||||
|
key: "w:vSpace",
|
||||||
|
value: options.space?.vertical,
|
||||||
|
},
|
||||||
|
rule: {
|
||||||
|
key: "w:hRule",
|
||||||
|
value: options.rule,
|
||||||
|
},
|
||||||
|
alignmentX: {
|
||||||
|
key: "w:xAlign",
|
||||||
|
value: (options as IAlignmentFrameOptions).alignment ? (options as IAlignmentFrameOptions).alignment.x : undefined,
|
||||||
|
},
|
||||||
|
alignmentY: {
|
||||||
|
key: "w:yAlign",
|
||||||
|
value: (options as IAlignmentFrameOptions).alignment ? (options as IAlignmentFrameOptions).alignment.y : undefined,
|
||||||
|
},
|
||||||
|
lines: {
|
||||||
|
key: "w:lines",
|
||||||
|
value: options.lines,
|
||||||
|
},
|
||||||
|
wrap: {
|
||||||
|
key: "w:wrap",
|
||||||
|
value: options.wrap,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
@ -2,7 +2,7 @@ import { SpaceType } from "@file/shared";
|
|||||||
import { XmlComponent } from "@file/xml-components";
|
import { XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
import { TextAttributes } from "../run/text-attributes";
|
import { TextAttributes } from "../run/text-attributes";
|
||||||
import { IPageReferenceOptions } from "./pageref-properties";
|
import { IPageReferenceOptions } from "./pageref";
|
||||||
|
|
||||||
export class PageReferenceFieldInstruction extends XmlComponent {
|
export class PageReferenceFieldInstruction extends XmlComponent {
|
||||||
public constructor(bookmarkId: string, options: IPageReferenceOptions = {}) {
|
public constructor(bookmarkId: string, options: IPageReferenceOptions = {}) {
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
// Options according to https://www.ecma-international.org/publications/standards/Ecma-376.htm (at Part 1, Page 1234)
|
|
||||||
|
|
||||||
export interface IPageReferenceOptions {
|
|
||||||
/**
|
|
||||||
* \h option - Creates a hyperlink to the bookmarked paragraph.
|
|
||||||
*/
|
|
||||||
readonly hyperlink?: boolean;
|
|
||||||
/**
|
|
||||||
* \p option - Causes the field to display its position relative to the source
|
|
||||||
* bookmark. If the PAGEREF field is on the same page as the
|
|
||||||
* bookmark, it omits "on page #" and returns "above" or "below"
|
|
||||||
* only. If the PAGEREF field is not on the same page as the
|
|
||||||
* bookmark, the string "on page #" is used.
|
|
||||||
*/
|
|
||||||
readonly useRelativePosition?: boolean;
|
|
||||||
}
|
|
@ -2,7 +2,22 @@
|
|||||||
import { Begin, End } from "@file/paragraph/run/field";
|
import { Begin, End } from "@file/paragraph/run/field";
|
||||||
import { Run } from "../run";
|
import { Run } from "../run";
|
||||||
import { PageReferenceFieldInstruction } from "./pageref-field-instruction";
|
import { PageReferenceFieldInstruction } from "./pageref-field-instruction";
|
||||||
import type { IPageReferenceOptions } from "./pageref-properties";
|
|
||||||
|
// Options according to https://www.ecma-international.org/publications/standards/Ecma-376.htm (at Part 1, Page 1234)
|
||||||
|
export type IPageReferenceOptions = {
|
||||||
|
/**
|
||||||
|
* \h option - Creates a hyperlink to the bookmarked paragraph.
|
||||||
|
*/
|
||||||
|
readonly hyperlink?: boolean;
|
||||||
|
/**
|
||||||
|
* \p option - Causes the field to display its position relative to the source
|
||||||
|
* bookmark. If the PAGEREF field is on the same page as the
|
||||||
|
* bookmark, it omits "on page #" and returns "above" or "below"
|
||||||
|
* only. If the PAGEREF field is not on the same page as the
|
||||||
|
* bookmark, the string "on page #" is used.
|
||||||
|
*/
|
||||||
|
readonly useRelativePosition?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export class PageReference extends Run {
|
export class PageReference extends Run {
|
||||||
public constructor(bookmarkId: string, options: IPageReferenceOptions = {}) {
|
public constructor(bookmarkId: string, options: IPageReferenceOptions = {}) {
|
||||||
|
@ -890,10 +890,7 @@ describe("Paragraph", () => {
|
|||||||
it("should set frame attribute", () => {
|
it("should set frame attribute", () => {
|
||||||
const paragraph = new Paragraph({
|
const paragraph = new Paragraph({
|
||||||
frame: {
|
frame: {
|
||||||
position: {
|
type: "alignment",
|
||||||
x: 1000,
|
|
||||||
y: 3000,
|
|
||||||
},
|
|
||||||
width: 4000,
|
width: 4000,
|
||||||
height: 1000,
|
height: 1000,
|
||||||
anchor: {
|
anchor: {
|
||||||
@ -918,9 +915,7 @@ describe("Paragraph", () => {
|
|||||||
"w:hAnchor": "margin",
|
"w:hAnchor": "margin",
|
||||||
"w:vAnchor": "margin",
|
"w:vAnchor": "margin",
|
||||||
"w:w": 4000,
|
"w:w": 4000,
|
||||||
"w:x": 1000,
|
|
||||||
"w:xAlign": "center",
|
"w:xAlign": "center",
|
||||||
"w:y": 3000,
|
|
||||||
"w:yAlign": "top",
|
"w:yAlign": "top",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -159,6 +159,21 @@ describe("ParagraphProperties", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should create with the overflowPunct property", () => {
|
||||||
|
const properties = new ParagraphProperties({
|
||||||
|
overflowPunctuation: true,
|
||||||
|
});
|
||||||
|
const tree = new Formatter().format(properties);
|
||||||
|
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:pPr": [
|
||||||
|
{
|
||||||
|
"w:overflowPunct": {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("should create with the run property", () => {
|
it("should create with the run property", () => {
|
||||||
const properties = new ParagraphProperties({
|
const properties = new ParagraphProperties({
|
||||||
run: {
|
run: {
|
||||||
|
@ -13,7 +13,7 @@ import { HeadingLevel, Style } from "./formatting/style";
|
|||||||
import { TabStop, TabStopDefinition, TabStopType } from "./formatting/tab-stop";
|
import { TabStop, TabStopDefinition, TabStopType } from "./formatting/tab-stop";
|
||||||
import { NumberProperties } from "./formatting/unordered-list";
|
import { NumberProperties } from "./formatting/unordered-list";
|
||||||
import { WordWrap } from "./formatting/word-wrap";
|
import { WordWrap } from "./formatting/word-wrap";
|
||||||
import { FrameProperties, IFrameOptions } from "./frame/frame-properties";
|
import { createFrameProperties, IFrameOptions } from "./frame/frame-properties";
|
||||||
import { OutlineLevel } from "./links";
|
import { OutlineLevel } from "./links";
|
||||||
import { IRunOptions, RunProperties } from ".";
|
import { IRunOptions, RunProperties } from ".";
|
||||||
|
|
||||||
@ -60,6 +60,7 @@ export interface IParagraphPropertiesOptions extends IParagraphStylePropertiesOp
|
|||||||
readonly frame?: IFrameOptions;
|
readonly frame?: IFrameOptions;
|
||||||
readonly suppressLineNumbers?: boolean;
|
readonly suppressLineNumbers?: boolean;
|
||||||
readonly wordWrap?: boolean;
|
readonly wordWrap?: boolean;
|
||||||
|
readonly overflowPunctuation?: boolean;
|
||||||
readonly scale?: number;
|
readonly scale?: number;
|
||||||
/**
|
/**
|
||||||
* This element specifies whether inter-character spacing shall automatically be adjusted between regions of numbers and regions of East Asian text in the current paragraph. These regions shall be determined by the Unicode character values of the text content within the paragraph.
|
* This element specifies whether inter-character spacing shall automatically be adjusted between regions of numbers and regions of East Asian text in the current paragraph. These regions shall be determined by the Unicode character values of the text content within the paragraph.
|
||||||
@ -116,7 +117,7 @@ export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.frame) {
|
if (options.frame) {
|
||||||
this.push(new FrameProperties(options.frame));
|
this.push(createFrameProperties(options.frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.widowControl !== undefined) {
|
if (options.widowControl !== undefined) {
|
||||||
@ -152,6 +153,10 @@ export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
|
|||||||
this.push(new WordWrap());
|
this.push(new WordWrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.overflowPunctuation) {
|
||||||
|
this.push(new OnOffElement("w:overflowPunct", options.overflowPunctuation));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FIX: Multitab support for Libre Writer
|
* FIX: Multitab support for Libre Writer
|
||||||
* Ensure there is only one w:tabs tag with multiple w:tab
|
* Ensure there is only one w:tabs tag with multiple w:tab
|
||||||
|
@ -3,6 +3,7 @@ import { uniqueId } from "@util/convenience-functions";
|
|||||||
import { IContext, IXmlableObject } from "@file/xml-components";
|
import { IContext, IXmlableObject } from "@file/xml-components";
|
||||||
import { DocPropertiesOptions } from "@file/drawing/doc-properties/doc-properties";
|
import { DocPropertiesOptions } from "@file/drawing/doc-properties/doc-properties";
|
||||||
|
|
||||||
|
import { OutlineOptions } from "../../drawing/inline/graphic/graphic-data/pic/shape-properties/outline/outline";
|
||||||
import { Drawing, IFloating } from "../../drawing";
|
import { Drawing, IFloating } from "../../drawing";
|
||||||
import { IMediaTransformation } from "../../media";
|
import { IMediaTransformation } from "../../media";
|
||||||
import { IMediaData } from "../../media/data";
|
import { IMediaData } from "../../media/data";
|
||||||
@ -13,6 +14,7 @@ export interface IImageOptions {
|
|||||||
readonly transformation: IMediaTransformation;
|
readonly transformation: IMediaTransformation;
|
||||||
readonly floating?: IFloating;
|
readonly floating?: IFloating;
|
||||||
readonly altText?: DocPropertiesOptions;
|
readonly altText?: DocPropertiesOptions;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ImageRun extends Run {
|
export class ImageRun extends Run {
|
||||||
@ -39,7 +41,11 @@ export class ImageRun extends Run {
|
|||||||
rotation: options.transformation.rotation ? options.transformation.rotation * 60000 : undefined,
|
rotation: options.transformation.rotation ? options.transformation.rotation * 60000 : undefined,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const drawing = new Drawing(this.imageData, { floating: options.floating, docProperties: options.altText });
|
const drawing = new Drawing(this.imageData, {
|
||||||
|
floating: options.floating,
|
||||||
|
docProperties: options.altText,
|
||||||
|
outline: options.outline,
|
||||||
|
});
|
||||||
|
|
||||||
this.root.push(drawing);
|
this.root.push(drawing);
|
||||||
}
|
}
|
||||||
@ -64,7 +70,9 @@ export class ImageRun extends Run {
|
|||||||
.split("")
|
.split("")
|
||||||
.map((c) => c.charCodeAt(0)),
|
.map((c) => c.charCodeAt(0)),
|
||||||
);
|
);
|
||||||
|
/* c8 ignore next 6 */
|
||||||
} else {
|
} else {
|
||||||
|
// Not possible to test this branch in NodeJS
|
||||||
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
|
||||||
const b = require("buf" + "fer");
|
const b = require("buf" + "fer");
|
||||||
return new b.Buffer(dataURI, "base64");
|
return new b.Buffer(dataURI, "base64");
|
||||||
|
@ -2,11 +2,11 @@ import { describe, expect, it } from "vitest";
|
|||||||
|
|
||||||
import { Formatter } from "@export/formatter";
|
import { Formatter } from "@export/formatter";
|
||||||
|
|
||||||
import { NumberOfPages, NumberOfPagesSection, Page } from "./page-number";
|
import { CurrentSection, NumberOfPages, NumberOfPagesSection, Page } from "./page-number";
|
||||||
|
|
||||||
describe("Page", () => {
|
describe("Page", () => {
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
it("uses the font name for both ascii and hAnsi", () => {
|
it("should work", () => {
|
||||||
const tree = new Formatter().format(new Page());
|
const tree = new Formatter().format(new Page());
|
||||||
expect(tree).to.deep.equal({ "w:instrText": [{ _attr: { "xml:space": "preserve" } }, "PAGE"] });
|
expect(tree).to.deep.equal({ "w:instrText": [{ _attr: { "xml:space": "preserve" } }, "PAGE"] });
|
||||||
});
|
});
|
||||||
@ -15,7 +15,7 @@ describe("Page", () => {
|
|||||||
|
|
||||||
describe("NumberOfPages", () => {
|
describe("NumberOfPages", () => {
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
it("uses the font name for both ascii and hAnsi", () => {
|
it("should work", () => {
|
||||||
const tree = new Formatter().format(new NumberOfPages());
|
const tree = new Formatter().format(new NumberOfPages());
|
||||||
expect(tree).to.deep.equal({ "w:instrText": [{ _attr: { "xml:space": "preserve" } }, "NUMPAGES"] });
|
expect(tree).to.deep.equal({ "w:instrText": [{ _attr: { "xml:space": "preserve" } }, "NUMPAGES"] });
|
||||||
});
|
});
|
||||||
@ -24,9 +24,18 @@ describe("NumberOfPages", () => {
|
|||||||
|
|
||||||
describe("NumberOfPagesSection", () => {
|
describe("NumberOfPagesSection", () => {
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
it("uses the font name for both ascii and hAnsi", () => {
|
it("should work", () => {
|
||||||
const tree = new Formatter().format(new NumberOfPagesSection());
|
const tree = new Formatter().format(new NumberOfPagesSection());
|
||||||
expect(tree).to.deep.equal({ "w:instrText": [{ _attr: { "xml:space": "preserve" } }, "SECTIONPAGES"] });
|
expect(tree).to.deep.equal({ "w:instrText": [{ _attr: { "xml:space": "preserve" } }, "SECTIONPAGES"] });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("CurrentSection", () => {
|
||||||
|
describe("#constructor()", () => {
|
||||||
|
it("should work", () => {
|
||||||
|
const tree = new Formatter().format(new CurrentSection());
|
||||||
|
expect(tree).to.deep.equal({ "w:instrText": [{ _attr: { "xml:space": "preserve" } }, "SECTION"] });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -26,3 +26,11 @@ export class NumberOfPagesSection extends XmlComponent {
|
|||||||
this.root.push("SECTIONPAGES");
|
this.root.push("SECTIONPAGES");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class CurrentSection extends XmlComponent {
|
||||||
|
public constructor() {
|
||||||
|
super("w:instrText");
|
||||||
|
this.root.push(new TextAttributes({ space: SpaceType.PRESERVE }));
|
||||||
|
this.root.push("SECTION");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -432,6 +432,23 @@ describe("Run", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("#section", () => {
|
||||||
|
it("should set the run to the RTL mode", () => {
|
||||||
|
const run = new Run({
|
||||||
|
children: [PageNumber.CURRENT_SECTION],
|
||||||
|
});
|
||||||
|
const tree = new Formatter().format(run);
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:r": [
|
||||||
|
{ "w:fldChar": { _attr: { "w:fldCharType": "begin" } } },
|
||||||
|
{ "w:instrText": [{ _attr: { "xml:space": "preserve" } }, "SECTION"] },
|
||||||
|
{ "w:fldChar": { _attr: { "w:fldCharType": "separate" } } },
|
||||||
|
{ "w:fldChar": { _attr: { "w:fldCharType": "end" } } },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("#style", () => {
|
describe("#style", () => {
|
||||||
it("should set the style to the given styleId", () => {
|
it("should set the style to the given styleId", () => {
|
||||||
const run = new Run({
|
const run = new Run({
|
||||||
|
@ -6,7 +6,7 @@ import { FieldInstruction } from "@file/table-of-contents/field-instruction";
|
|||||||
|
|
||||||
import { Break } from "./break";
|
import { Break } from "./break";
|
||||||
import { Begin, End, Separate } from "./field";
|
import { Begin, End, Separate } from "./field";
|
||||||
import { NumberOfPages, NumberOfPagesSection, Page } from "./page-number";
|
import { NumberOfPages, NumberOfPagesSection, Page, CurrentSection } from "./page-number";
|
||||||
import { IRunPropertiesOptions, RunProperties } from "./properties";
|
import { IRunPropertiesOptions, RunProperties } from "./properties";
|
||||||
import { Text } from "./run-components/text";
|
import { Text } from "./run-components/text";
|
||||||
import {
|
import {
|
||||||
@ -103,6 +103,7 @@ export const PageNumber = {
|
|||||||
CURRENT: "CURRENT",
|
CURRENT: "CURRENT",
|
||||||
TOTAL_PAGES: "TOTAL_PAGES",
|
TOTAL_PAGES: "TOTAL_PAGES",
|
||||||
TOTAL_PAGES_IN_SECTION: "TOTAL_PAGES_IN_SECTION",
|
TOTAL_PAGES_IN_SECTION: "TOTAL_PAGES_IN_SECTION",
|
||||||
|
CURRENT_SECTION: "SECTION",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
@ -143,6 +144,12 @@ export class Run extends XmlComponent {
|
|||||||
this.root.push(new Separate());
|
this.root.push(new Separate());
|
||||||
this.root.push(new End());
|
this.root.push(new End());
|
||||||
break;
|
break;
|
||||||
|
case PageNumber.CURRENT_SECTION:
|
||||||
|
this.root.push(new Begin());
|
||||||
|
this.root.push(new CurrentSection());
|
||||||
|
this.root.push(new Separate());
|
||||||
|
this.root.push(new End());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
this.root.push(new Text(child));
|
this.root.push(new Text(child));
|
||||||
break;
|
break;
|
||||||
|
@ -17,7 +17,8 @@ export type RelationshipType =
|
|||||||
| "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"
|
| "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"
|
||||||
| "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
|
| "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
|
||||||
| "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes"
|
| "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes"
|
||||||
| "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
|
| "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"
|
||||||
|
| "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font";
|
||||||
|
|
||||||
export const TargetModeType = {
|
export const TargetModeType = {
|
||||||
EXTERNAL: "External",
|
EXTERNAL: "External",
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { XmlComponent } from "@file/xml-components";
|
import { XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
import { IRunOptions, RunProperties } from "../../index";
|
|
||||||
import { Break } from "../../paragraph/run/break";
|
import { Break } from "../../paragraph/run/break";
|
||||||
import { Begin, End, Separate } from "../../paragraph/run/field";
|
import { Begin, End, Separate } from "../../paragraph/run/field";
|
||||||
import { PageNumber } from "../../paragraph/run/run";
|
import { IRunOptions, PageNumber } from "../../paragraph/run/run";
|
||||||
import { ChangeAttributes, IChangedAttributesProperties } from "../track-revision";
|
import { ChangeAttributes, IChangedAttributesProperties } from "../track-revision";
|
||||||
|
import { RunProperties } from "../../paragraph/run/properties";
|
||||||
import { DeletedNumberOfPages, DeletedNumberOfPagesSection, DeletedPage } from "./deleted-page-number";
|
import { DeletedNumberOfPages, DeletedNumberOfPagesSection, DeletedPage } from "./deleted-page-number";
|
||||||
import { DeletedText } from "./deleted-text";
|
import { DeletedText } from "./deleted-text";
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ export const convertToXmlComponent = (element: XmlElement): ImportedXmlComponent
|
|||||||
return element.text as string;
|
return element.text as string;
|
||||||
default:
|
default:
|
||||||
return undefined;
|
return undefined;
|
||||||
|
/* c8 ignore next 2 */
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,6 +55,14 @@ export class StringValueElement extends XmlComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const createStringElement = (name: string, value: string): XmlComponent =>
|
||||||
|
new BuilderElement({
|
||||||
|
name,
|
||||||
|
attributes: {
|
||||||
|
value: { key: "w:val", value },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// This represents various number element types.
|
// This represents various number element types.
|
||||||
export class NumberValueElement extends XmlComponent {
|
export class NumberValueElement extends XmlComponent {
|
||||||
public constructor(name: string, val: number) {
|
public constructor(name: string, val: number) {
|
||||||
@ -82,17 +90,23 @@ export class StringContainer extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class BuilderElement<T extends AttributeData> extends XmlComponent {
|
export class BuilderElement<T extends AttributeData> extends XmlComponent {
|
||||||
public constructor(options: {
|
public constructor({
|
||||||
|
name,
|
||||||
|
attributes,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
readonly attributes?: AttributePayload<T>;
|
readonly attributes?: AttributePayload<T>;
|
||||||
readonly children?: readonly XmlComponent[];
|
readonly children?: readonly XmlComponent[];
|
||||||
}) {
|
}) {
|
||||||
super(options.name);
|
super(name);
|
||||||
|
|
||||||
if (options.attributes) {
|
if (attributes) {
|
||||||
this.root.push(new NextAttributeComponent(options.attributes));
|
this.root.push(new NextAttributeComponent(attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Children
|
if (children) {
|
||||||
|
this.root.push(...children);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,9 @@ export abstract class XmlComponent extends BaseXmlComponent {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Do not use this method. It is only used internally by the library. It will be removed in a future version.
|
||||||
|
*/
|
||||||
public addChildElement(child: XmlComponent | string): XmlComponent {
|
public addChildElement(child: XmlComponent | string): XmlComponent {
|
||||||
this.root.push(child);
|
this.root.push(child);
|
||||||
|
|
||||||
|
@ -1,6 +1,16 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
import { convertInchesToTwip, convertMillimetersToTwip, uniqueId, uniqueNumericIdCreator } from "./convenience-functions";
|
import {
|
||||||
|
abstractNumUniqueNumericIdGen,
|
||||||
|
bookmarkUniqueNumericIdGen,
|
||||||
|
concreteNumUniqueNumericIdGen,
|
||||||
|
convertInchesToTwip,
|
||||||
|
convertMillimetersToTwip,
|
||||||
|
docPropertiesUniqueNumericIdGen,
|
||||||
|
uniqueId,
|
||||||
|
uniqueNumericIdCreator,
|
||||||
|
uniqueUuid,
|
||||||
|
} from "./convenience-functions";
|
||||||
|
|
||||||
describe("Utility", () => {
|
describe("Utility", () => {
|
||||||
describe("#convertMillimetersToTwip", () => {
|
describe("#convertMillimetersToTwip", () => {
|
||||||
@ -24,9 +34,47 @@ describe("Utility", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("#abstractNumUniqueNumericIdGen", () => {
|
||||||
|
it("should generate a unique incrementing ID", () => {
|
||||||
|
const uniqueNumericId = abstractNumUniqueNumericIdGen();
|
||||||
|
expect(uniqueNumericId()).to.equal(1);
|
||||||
|
expect(uniqueNumericId()).to.equal(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#concreteNumUniqueNumericIdGen", () => {
|
||||||
|
it("should generate a unique incrementing ID", () => {
|
||||||
|
const uniqueNumericId = concreteNumUniqueNumericIdGen();
|
||||||
|
expect(uniqueNumericId()).to.equal(2);
|
||||||
|
expect(uniqueNumericId()).to.equal(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#docPropertiesUniqueNumericIdGen", () => {
|
||||||
|
it("should generate a unique incrementing ID", () => {
|
||||||
|
const uniqueNumericId = docPropertiesUniqueNumericIdGen();
|
||||||
|
expect(uniqueNumericId()).to.equal(1);
|
||||||
|
expect(uniqueNumericId()).to.equal(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#bookmarkUniqueNumericIdGen", () => {
|
||||||
|
it("should generate a unique incrementing ID", () => {
|
||||||
|
const uniqueNumericId = bookmarkUniqueNumericIdGen();
|
||||||
|
expect(uniqueNumericId()).to.equal(1);
|
||||||
|
expect(uniqueNumericId()).to.equal(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("#uniqueId", () => {
|
describe("#uniqueId", () => {
|
||||||
it("should generate a unique pseudorandom ID", () => {
|
it("should generate a unique pseudorandom ID", () => {
|
||||||
expect(uniqueId()).to.not.be.empty;
|
expect(uniqueId()).to.not.be.empty;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("#uniqueUuid", () => {
|
||||||
|
it("should generate a unique pseudorandom ID", () => {
|
||||||
|
expect(uniqueUuid()).to.not.be.empty;
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { nanoid } from "nanoid/non-secure";
|
import { nanoid, customAlphabet } from "nanoid/non-secure";
|
||||||
|
|
||||||
// Twip - twentieths of a point
|
// Twip - twentieths of a point
|
||||||
export const convertMillimetersToTwip = (millimeters: number): number => Math.floor((millimeters / 25.4) * 72 * 20);
|
export const convertMillimetersToTwip = (millimeters: number): number => Math.floor((millimeters / 25.4) * 72 * 20);
|
||||||
@ -23,3 +23,7 @@ export const docPropertiesUniqueNumericIdGen = (): UniqueNumericIdCreator => uni
|
|||||||
export const bookmarkUniqueNumericIdGen = (): UniqueNumericIdCreator => uniqueNumericIdCreator();
|
export const bookmarkUniqueNumericIdGen = (): UniqueNumericIdCreator => uniqueNumericIdCreator();
|
||||||
|
|
||||||
export const uniqueId = (): string => nanoid().toLowerCase();
|
export const uniqueId = (): string => nanoid().toLowerCase();
|
||||||
|
|
||||||
|
const generateUuidPart = (count: number): string => customAlphabet("1234567890abcdef", count)();
|
||||||
|
export const uniqueUuid = (): string =>
|
||||||
|
`${generateUuidPart(8)}-${generateUuidPart(4)}-${generateUuidPart(4)}-${generateUuidPart(4)}-${generateUuidPart(12)}`;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { defineConfig } from "vitest/config";
|
import { configDefaults, defineConfig } from "vitest/config";
|
||||||
import { resolve } from "path";
|
import { resolve } from "path";
|
||||||
import tsconfigPaths from "vite-tsconfig-paths";
|
import tsconfigPaths from "vite-tsconfig-paths";
|
||||||
import dts from "vite-plugin-dts";
|
import dts from "vite-plugin-dts";
|
||||||
@ -26,6 +26,7 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
minify: false,
|
minify: false,
|
||||||
|
target: "es2015",
|
||||||
lib: {
|
lib: {
|
||||||
entry: [resolve(__dirname, "src/index.ts")],
|
entry: [resolve(__dirname, "src/index.ts")],
|
||||||
name: "docx",
|
name: "docx",
|
||||||
@ -60,10 +61,31 @@ export default defineConfig({
|
|||||||
coverage: {
|
coverage: {
|
||||||
provider: "v8",
|
provider: "v8",
|
||||||
reporter: ["text", "json", "html"],
|
reporter: ["text", "json", "html"],
|
||||||
statements: 99.93,
|
thresholds: {
|
||||||
branches: 98.85,
|
statements: 99.98,
|
||||||
functions: 100,
|
branches: 99.15,
|
||||||
lines: 99.93,
|
functions: 100,
|
||||||
|
lines: 99.98,
|
||||||
|
},
|
||||||
|
exclude: [
|
||||||
|
...configDefaults.exclude,
|
||||||
|
'**/build/**',
|
||||||
|
'**/demo/**',
|
||||||
|
'**/docs/**',
|
||||||
|
'**/scripts/**',
|
||||||
|
'**/src/**/index.ts',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
|
include: [
|
||||||
|
'**/src/**/*.spec.ts',
|
||||||
|
'**/packages/**/*.spec.ts'
|
||||||
|
],
|
||||||
|
exclude: [
|
||||||
|
...configDefaults.exclude,
|
||||||
|
'**/build/**',
|
||||||
|
'**/demo/**',
|
||||||
|
'**/docs/**',
|
||||||
|
'**/scripts/**'
|
||||||
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user