Compare commits

..

132 Commits
8.2.0 ... 8.5.0

Author SHA1 Message Date
7570fc2bf5 Version bump (#2496) 2023-12-31 14:35:06 +00:00
6929dee846 Revery demo 14 (#2495) 2023-12-31 14:22:22 +00:00
d4ac2a08ee Make demos synchronous (#2494) 2023-12-31 14:14:41 +00:00
010ef05ce3 Feat/embedded fonts (#2174)
* #239 Embedded fonts

* Add boilerplate for font table

* Fix linting

* Fix linting

* Fix odttf naming

* Correct writing of fonts to relationships and font table

new uuid function

* Add font to run

* Add demo

Fix tests

* Add character set support

* Add tests

* Write tests
2023-12-30 02:23:54 +00:00
fa401297da Re-name variables (#2486) 2023-12-29 23:52:43 +00:00
ce0e9936c3 build(deps-dev): bump @typescript-eslint/eslint-plugin (#2488)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 6.15.0 to 6.16.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.16.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-29 23:51:46 +00:00
c13e9938cf Set target to es2015 in vite config (#2492)
* Set target to es2015 in vite config

* Remove document
2023-12-29 23:51:31 +00:00
b8f97553b3 #933 Discriminated union for frame alignment (#2477) 2023-12-29 15:07:42 +00:00
2550da199d build(deps-dev): bump vite-tsconfig-paths from 4.2.2 to 4.2.3 (#2493)
Bumps [vite-tsconfig-paths](https://github.com/aleclarson/vite-tsconfig-paths) from 4.2.2 to 4.2.3.
- [Release notes](https://github.com/aleclarson/vite-tsconfig-paths/releases)
- [Commits](https://github.com/aleclarson/vite-tsconfig-paths/compare/v4.2.2...v4.2.3)

---
updated-dependencies:
- dependency-name: vite-tsconfig-paths
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-29 15:06:48 +00:00
682b679bdb build(deps-dev): bump @typescript-eslint/parser from 6.15.0 to 6.16.0 (#2489)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.15.0 to 6.16.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.16.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-28 22:06:50 +00:00
e0fd7e751c build(deps-dev): bump cspell from 8.2.3 to 8.2.4 (#2490)
Bumps [cspell](https://github.com/streetsidesoftware/cspell) from 8.2.3 to 8.2.4.
- [Release notes](https://github.com/streetsidesoftware/cspell/releases)
- [Changelog](https://github.com/streetsidesoftware/cspell/blob/main/CHANGELOG.md)
- [Commits](https://github.com/streetsidesoftware/cspell/compare/v8.2.3...v8.2.4)

---
updated-dependencies:
- dependency-name: cspell
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-28 22:06:24 +00:00
9b57db4716 build(deps-dev): bump vite-plugin-node-polyfills from 0.9.0 to 0.19.0 (#2491)
Bumps [vite-plugin-node-polyfills](https://github.com/davidmyersdev/vite-plugin-node-polyfills) from 0.9.0 to 0.19.0.
- [Release notes](https://github.com/davidmyersdev/vite-plugin-node-polyfills/releases)
- [Commits](https://github.com/davidmyersdev/vite-plugin-node-polyfills/compare/v0.9.0...v0.19.0)

---
updated-dependencies:
- dependency-name: vite-plugin-node-polyfills
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-28 22:05:59 +00:00
d23f453d28 Add image borders (#2472)
* Add image borders

* Fix prettier

* Fix spelling

* Fix spelling

* Finish feature

* Update demo

* Try and fix demo 14
2023-12-27 20:20:45 +00:00
6c28f8bab0 Page number in section (#2485)
* Page number in section

* Inline Lorem Ipsum

* Re-name current page in section to current section
2023-12-25 22:29:32 +00:00
10b87b5a70 Run demo GitHub Action in parallel (#2484)
* Run demo GitHub Action in parallel

* Fix path of action yml

* Move checkout to demo action

* Prettier format

* Specifying shell

* Try to fix uses

* Fix spelling issue

* Fix demo

* Downloading artifacts too unreliable

Building instead

* Re-name step

Re-use action elsewhere
2023-12-25 15:29:13 +00:00
6b6f9d7ed4 Use standard script names for test and prettier (#2483) 2023-12-25 13:02:00 +00:00
0434d00ff7 build(deps-dev): bump prettier from 3.0.0 to 3.1.1 (#2480)
Bumps [prettier](https://github.com/prettier/prettier) from 3.0.0 to 3.1.1.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.0.0...3.1.1)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-25 12:44:20 +00:00
7e3acc25b9 build(deps-dev): bump cspell from 7.3.8 to 8.2.3 (#2482)
Bumps [cspell](https://github.com/streetsidesoftware/cspell) from 7.3.8 to 8.2.3.
- [Release notes](https://github.com/streetsidesoftware/cspell/releases)
- [Changelog](https://github.com/streetsidesoftware/cspell/blob/main/CHANGELOG.md)
- [Commits](https://github.com/streetsidesoftware/cspell/compare/v7.3.8...v8.2.3)

---
updated-dependencies:
- dependency-name: cspell
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-25 12:38:24 +00:00
62ad8f12b7 build(deps-dev): bump vite-plugin-dts from 3.6.4 to 3.7.0 (#2481)
Bumps [vite-plugin-dts](https://github.com/qmhc/vite-plugin-dts) from 3.6.4 to 3.7.0.
- [Release notes](https://github.com/qmhc/vite-plugin-dts/releases)
- [Changelog](https://github.com/qmhc/vite-plugin-dts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/qmhc/vite-plugin-dts/compare/v3.6.4...v3.7.0)

---
updated-dependencies:
- dependency-name: vite-plugin-dts
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-25 12:38:07 +00:00
a6a656f1a0 build(deps-dev): bump jsdom from 22.1.0 to 23.0.1 (#2479)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 22.1.0 to 23.0.1.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Changelog](https://github.com/jsdom/jsdom/blob/main/Changelog.md)
- [Commits](https://github.com/jsdom/jsdom/compare/22.1.0...23.0.1)

---
updated-dependencies:
- dependency-name: jsdom
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-25 12:37:56 +00:00
1bf36009e8 #916 Add overflow punctuation (#2478)
* #916 Add overflow punctuation

* Fix tests
2023-12-25 04:09:54 +00:00
86bdf3e199 build(deps-dev): bump @types/xml from 1.0.8 to 1.0.11 (#2464)
Bumps [@types/xml](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/xml) from 1.0.8 to 1.0.11.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/xml)

---
updated-dependencies:
- dependency-name: "@types/xml"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-25 02:58:48 +00:00
a3c796aae3 Add deprecation warning to addChildElement (#2476) 2023-12-25 02:54:46 +00:00
dbe0586f70 build(deps-dev): bump typedoc from 0.24.8 to 0.25.4 (#2466)
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.24.8 to 0.25.4.
- [Release notes](https://github.com/TypeStrong/TypeDoc/releases)
- [Changelog](https://github.com/TypeStrong/typedoc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/TypeDoc/compare/v0.24.8...v0.25.4)

---
updated-dependencies:
- dependency-name: typedoc
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-25 02:48:33 +00:00
7e2538dffc build(deps): bump @types/node from 20.8.6 to 20.10.5 (#2463)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.8.6 to 20.10.5.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-25 02:48:20 +00:00
c3080ff9d9 Update vitest (#2475)
* Update vitest

* Update vite test config

* Fix coverage metrics and bump coverage
2023-12-25 02:47:43 +00:00
772fc8462a build(deps-dev): bump eslint-plugin-jsdoc from 46.8.2 to 46.9.1 (#2468)
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 46.8.2 to 46.9.1.
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Changelog](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.releaserc)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v46.8.2...v46.9.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-25 01:56:30 +00:00
e194780cd1 build(deps-dev): bump @vitest/ui from 0.33.0 to 0.34.7 (#2467)
Bumps [@vitest/ui](https://github.com/vitest-dev/vitest/tree/HEAD/packages/ui) from 0.33.0 to 0.34.7.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v0.34.7/packages/ui)

---
updated-dependencies:
- dependency-name: "@vitest/ui"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-25 01:56:22 +00:00
5b80ea32d7 build(deps-dev): bump @typescript-eslint/parser from 6.9.1 to 6.15.0 (#2462)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.9.1 to 6.15.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.15.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-25 01:56:12 +00:00
31b7e07ab3 build(deps-dev): bump @types/prompt from 1.1.5 to 1.1.8 (#2465)
Bumps [@types/prompt](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/prompt) from 1.1.5 to 1.1.8.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/prompt)

---
updated-dependencies:
- dependency-name: "@types/prompt"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-25 01:55:56 +00:00
939d418af1 build(deps-dev): bump @typescript-eslint/eslint-plugin (#2461)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 6.9.1 to 6.15.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.15.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-25 01:55:46 +00:00
4258dd2a2e build(deps-dev): bump typescript from 5.1.6 to 5.3.3 (#2469)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.1.6 to 5.3.3.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.1.6...v5.3.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-25 01:55:38 +00:00
b7334a1ab5 Version bump 2023-12-25 01:52:12 +00:00
9229f45d59 Downgrade Build to ES2015 (#2473) 2023-12-25 01:50:26 +00:00
2bd4aacdd5 #2388 - Add default tab stop (#2470)
* #2388 - Check for undefined rather than falsey

* Add default tab stop

* Add back tab stop positions

* Add test for default tab stop
2023-12-24 03:37:36 +00:00
abbd695a8f Version bump 2023-12-22 01:32:44 +00:00
f7b98bcde8 build(deps-dev): bump eslint-plugin-functional from 5.0.8 to 6.0.0 (#2409)
* build(deps-dev): bump eslint-plugin-functional from 5.0.8 to 6.0.0

Bumps [eslint-plugin-functional](https://github.com/eslint-functional/eslint-plugin-functional) from 5.0.8 to 6.0.0.
- [Release notes](https://github.com/eslint-functional/eslint-plugin-functional/releases)
- [Changelog](https://github.com/eslint-functional/eslint-plugin-functional/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint-functional/eslint-plugin-functional/compare/v5.0.8...v6.0.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-functional
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Remove assumeTypes

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dolan Miu <dolan_miu@hotmail.com>
2023-12-22 01:31:34 +00:00
a756a7697c Change all project enums to objects with as const (#2445)
* feat: change all enums to as const objects

* Add word to dictionary

---------

Co-authored-by: Dolan Miu <dolan_miu@hotmail.com>
2023-12-22 01:25:00 +00:00
fd1ea5b4dc build(deps-dev): bump eslint-plugin-unicorn from 48.0.1 to 50.0.1 (#2458)
Bumps [eslint-plugin-unicorn](https://github.com/sindresorhus/eslint-plugin-unicorn) from 48.0.1 to 50.0.1.
- [Release notes](https://github.com/sindresorhus/eslint-plugin-unicorn/releases)
- [Commits](https://github.com/sindresorhus/eslint-plugin-unicorn/compare/v48.0.1...v50.0.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-unicorn
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-22 01:21:22 +00:00
d83e089cd3 add run options to ParagraphPropertiesOptions (#2457) 2023-12-22 01:21:12 +00:00
33715cc50c build(deps-dev): bump vite from 4.5.0 to 5.0.10 (#2455)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.5.0 to 5.0.10.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.0.10/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-22 01:20:42 +00:00
f3f1f2d0b1 build(deps-dev): bump eslint from 8.45.0 to 8.56.0 (#2454)
Bumps [eslint](https://github.com/eslint/eslint) from 8.45.0 to 8.56.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.45.0...v8.56.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-22 01:20:33 +00:00
c35e706fa8 build(deps-dev): bump eslint-plugin-import from 2.27.5 to 2.29.1 (#2453)
Bumps [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import) from 2.27.5 to 2.29.1.
- [Release notes](https://github.com/import-js/eslint-plugin-import/releases)
- [Changelog](https://github.com/import-js/eslint-plugin-import/blob/main/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-plugin-import/compare/v2.27.5...v2.29.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-import
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-22 01:20:25 +00:00
35cebfe1a2 build(deps-dev): bump vite-tsconfig-paths from 4.2.0 to 4.2.2 (#2442)
Bumps [vite-tsconfig-paths](https://github.com/aleclarson/vite-tsconfig-paths) from 4.2.0 to 4.2.2.
- [Release notes](https://github.com/aleclarson/vite-tsconfig-paths/releases)
- [Commits](https://github.com/aleclarson/vite-tsconfig-paths/compare/v4.2.0...v4.2.2)

---
updated-dependencies:
- dependency-name: vite-tsconfig-paths
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-22 01:20:17 +00:00
d04c42cbe8 Use esm for ts-node (#2459)
* Use esm for ts-node

* Add esm flag

* Change tsconfig properties

* Use tsx rather than ts-node

* Use tsx

* Remove ts-node
2023-12-22 01:10:54 +00:00
8744e613ac Merge pull request #2438 from dolanmiu/dependabot/npm_and_yarn/vite-4.5.1
build(deps-dev): bump vite from 4.5.0 to 4.5.1
2023-12-21 23:52:36 +00:00
cbeecbf3e1 Merge pull request #2435 from dolanmiu/dependabot/npm_and_yarn/nanoid-5.0.4
build(deps): bump nanoid from 4.0.2 to 5.0.4
2023-12-21 23:52:28 +00:00
f8ab2d1701 Merge pull request #2433 from dolanmiu/dependabot/npm_and_yarn/vite-plugin-dts-3.6.4
build(deps-dev): bump vite-plugin-dts from 3.3.1 to 3.6.4
2023-12-21 23:52:20 +00:00
adc5c6f594 Merge pull request #2419 from dolanmiu/dependabot/npm_and_yarn/types/unzipper-0.10.9
build(deps-dev): bump @types/unzipper from 0.10.6 to 0.10.9
2023-12-21 23:52:14 +00:00
c9524cc497 Merge pull request #2418 from dolanmiu/dependabot/npm_and_yarn/inquirer-and-types/inquirer-9.2.12
build(deps-dev): bump inquirer and @types/inquirer
2023-12-21 23:52:06 +00:00
90de6ba7e1 Merge pull request #2407 from dolanmiu/dependabot/npm_and_yarn/vitest/coverage-v8-0.34.6
build(deps-dev): bump @vitest/coverage-v8 from 0.33.0 to 0.34.6
2023-12-21 23:51:57 +00:00
78d74ae60b Merge pull request #2439 from morlay/master
Run prop snapToGrid should be false
2023-12-06 12:09:40 +00:00
579593a467 Run prop snapToGrid should be false 2023-12-06 10:15:46 +08:00
b5393dadae build(deps-dev): bump vite from 4.5.0 to 4.5.1
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.5.0 to 4.5.1.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v4.5.1/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.5.1/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-06 00:01:15 +00:00
528ab1933e build(deps): bump nanoid from 4.0.2 to 5.0.4
Bumps [nanoid](https://github.com/ai/nanoid) from 4.0.2 to 5.0.4.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/4.0.2...5.0.4)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 11:15:37 +00:00
36181f8c91 build(deps-dev): bump vite-plugin-dts from 3.3.1 to 3.6.4
Bumps [vite-plugin-dts](https://github.com/qmhc/vite-plugin-dts) from 3.3.1 to 3.6.4.
- [Release notes](https://github.com/qmhc/vite-plugin-dts/releases)
- [Changelog](https://github.com/qmhc/vite-plugin-dts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/qmhc/vite-plugin-dts/compare/v3.3.1...v3.6.4)

---
updated-dependencies:
- dependency-name: vite-plugin-dts
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-30 11:36:50 +00:00
45af681db1 build(deps-dev): bump @types/unzipper from 0.10.6 to 0.10.9
Bumps [@types/unzipper](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/unzipper) from 0.10.6 to 0.10.9.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/unzipper)

---
updated-dependencies:
- dependency-name: "@types/unzipper"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-08 12:04:31 +00:00
ad6b482136 build(deps-dev): bump inquirer and @types/inquirer
Bumps [inquirer](https://github.com/SBoudrias/Inquirer.js) and [@types/inquirer](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/inquirer). These dependencies needed to be updated together.

Updates `inquirer` from 9.2.11 to 9.2.12
- [Release notes](https://github.com/SBoudrias/Inquirer.js/releases)
- [Commits](https://github.com/SBoudrias/Inquirer.js/compare/inquirer@9.2.11...inquirer@9.2.12)

Updates `@types/inquirer` from 9.0.3 to 9.0.7
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/inquirer)

---
updated-dependencies:
- dependency-name: inquirer
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: "@types/inquirer"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-08 11:59:29 +00:00
a6e1c2b019 build(deps-dev): bump @vitest/coverage-v8 from 0.33.0 to 0.34.6
Bumps [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) from 0.33.0 to 0.34.6.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v0.34.6/packages/coverage-v8)

---
updated-dependencies:
- dependency-name: "@vitest/coverage-v8"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-02 11:15:26 +00:00
3eb98533ae Version bump 2023-11-02 03:02:21 +00:00
f5f021834e Merge pull request #2403 from dolanmiu/feature/bump-eslint-plugin
Upgrade @typescript-eslint/parser
2023-11-02 03:01:55 +00:00
35702c3f77 Upgrade @typescript-eslint/parser 2023-11-01 22:52:41 +00:00
8fbbd571ad Merge pull request #2402 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-6.9.1
build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.60.1 to 6.9.1
2023-11-01 22:27:36 +00:00
2dd228be69 build(deps-dev): bump @typescript-eslint/eslint-plugin
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.60.1 to 6.9.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.9.1/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-01 21:16:40 +00:00
562835cfe7 Merge pull request #2401 from dolanmiu/dependabot/npm_and_yarn/vite-4.5.0
build(deps-dev): bump vite from 4.3.9 to 4.5.0
2023-11-01 21:15:57 +00:00
6bac06e84d Merge pull request #2382 from dolanmiu/dependabot/npm_and_yarn/cspell-7.3.8
build(deps-dev): bump cspell from 6.31.1 to 7.3.8
2023-11-01 21:15:33 +00:00
88436168ee Merge pull request #2400 from dolanmiu/dependabot/npm_and_yarn/browserify-sign-4.2.2
build(deps-dev): bump browserify-sign from 4.2.1 to 4.2.2
2023-11-01 21:15:26 +00:00
0c3206d2e2 Merge pull request #2350 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-jsdoc-46.8.2
build(deps-dev): bump eslint-plugin-jsdoc from 46.4.4 to 46.8.2
2023-11-01 21:15:08 +00:00
033debd339 Merge pull request #2303 from dolanmiu/dependabot/npm_and_yarn/execa-8.0.1
build(deps-dev): bump execa from 7.1.1 to 8.0.1
2023-11-01 21:15:00 +00:00
d4f160732a Use Record instead of Object 2023-11-01 20:56:02 +00:00
4238fc9ab4 build(deps-dev): bump execa from 7.1.1 to 8.0.1
Bumps [execa](https://github.com/sindresorhus/execa) from 7.1.1 to 8.0.1.
- [Release notes](https://github.com/sindresorhus/execa/releases)
- [Commits](https://github.com/sindresorhus/execa/compare/v7.1.1...v8.0.1)

---
updated-dependencies:
- dependency-name: execa
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-01 20:55:59 +00:00
0d042b8dd1 build(deps-dev): bump vite from 4.3.9 to 4.5.0
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.3.9 to 4.5.0.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.5.0/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-01 20:55:35 +00:00
afdd5f2d8f Merge pull request #2383 from dolanmiu/dependabot/npm_and_yarn/types/node-20.8.6
build(deps): bump @types/node from 20.4.2 to 20.8.6
2023-11-01 20:55:29 +00:00
70c7b3d1b3 Merge pull request #2374 from dolanmiu/dependabot/npm_and_yarn/postcss-8.4.31
build(deps-dev): bump postcss from 8.4.23 to 8.4.31
2023-11-01 20:55:22 +00:00
7b1cd5fe86 build(deps-dev): bump browserify-sign from 4.2.1 to 4.2.2
Bumps [browserify-sign](https://github.com/crypto-browserify/browserify-sign) from 4.2.1 to 4.2.2.
- [Changelog](https://github.com/browserify/browserify-sign/blob/main/CHANGELOG.md)
- [Commits](https://github.com/crypto-browserify/browserify-sign/compare/v4.2.1...v4.2.2)

---
updated-dependencies:
- dependency-name: browserify-sign
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-01 20:55:02 +00:00
09ab169ffd Merge pull request #2359 from dolanmiu/dependabot/npm_and_yarn/glob-10.3.10
build(deps-dev): bump glob from 10.3.1 to 10.3.10
2023-11-01 20:55:01 +00:00
35a82cf12e Merge pull request #2333 from dolanmiu/dependabot/npm_and_yarn/inquirer-9.2.11
build(deps-dev): bump inquirer from 9.2.7 to 9.2.11
2023-11-01 20:54:54 +00:00
8d33cb01dd Merge pull request #2268 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-unicorn-48.0.1
build(deps-dev): bump eslint-plugin-unicorn from 47.0.0 to 48.0.1
2023-11-01 20:54:35 +00:00
438d11dd86 Merge pull request #2387 from wilkmaia/fix/patch-styling
Fix style being missed on patchDocument
2023-11-01 20:54:23 +00:00
d23b0d0789 Fix coverage 2023-11-01 20:40:30 +00:00
1fa8c7ac82 Merge pull request #2397 from hom/master
fix: #2082 Numbering instance restart number not work since v8.0.0 and work well in v7.8.2
2023-10-27 00:41:01 +01:00
3d6ead0359 Merge pull request #2 from hom/fix/#2082 2023-10-27 03:59:58 +08:00
379050dccd Merge pull request #1 from dolanmiu/master 2023-10-27 03:31:07 +08:00
f9d1c197cf Merge pull request #2379 from rahon6000/master
changed default section margin from inch to Twip
2023-10-20 22:10:03 +01:00
a89ee463e6 Fix style being missed on patchDocument
There were scenarios in which patching a document would result in loss
of style for the template runs and, possibly, their right-adjacent run
as well (post-splitting). That was due to the run style elements not
being added to the newly created runs.

This commit addresses this issue by introducing a new, optional, flag
for the `patchDocument` function: `keepOriginalStyles`. It defaults to
`false` (current behavior) and, when `true`, ensures that there is no
loss of styling.

This should address https://github.com/dolanmiu/docx/issues/2293.
2023-10-18 12:58:01 -03:00
036caaacc8 build(deps): bump @types/node from 20.4.2 to 20.8.6
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.4.2 to 20.8.6.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-16 11:53:19 +00:00
80c37afe2b build(deps-dev): bump cspell from 6.31.1 to 7.3.8
Bumps [cspell](https://github.com/streetsidesoftware/cspell) from 6.31.1 to 7.3.8.
- [Release notes](https://github.com/streetsidesoftware/cspell/releases)
- [Changelog](https://github.com/streetsidesoftware/cspell/blob/main/CHANGELOG.md)
- [Commits](https://github.com/streetsidesoftware/cspell/compare/v6.31.1...v7.3.8)

---
updated-dependencies:
- dependency-name: cspell
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-16 11:52:24 +00:00
3a36d912fe changed default section margin from inch to Twip 2023-10-12 12:14:13 +09:00
c741d5d8ac build(deps-dev): bump postcss from 8.4.23 to 8.4.31
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.23 to 8.4.31.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.23...8.4.31)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-07 19:43:49 +00:00
0fa7dd13ad build(deps-dev): bump glob from 10.3.1 to 10.3.10
Bumps [glob](https://github.com/isaacs/node-glob) from 10.3.1 to 10.3.10.
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v10.3.1...v10.3.10)

---
updated-dependencies:
- dependency-name: glob
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-27 11:43:28 +00:00
d5d80550e7 Version bump 2023-09-26 23:00:51 +01:00
23a0a59454 Use .mjs for ESM 2023-09-26 22:59:32 +01:00
066aa56f6a build(deps-dev): bump eslint-plugin-jsdoc from 46.4.4 to 46.8.2
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 46.4.4 to 46.8.2.
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Changelog](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.releaserc)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v46.4.4...v46.8.2)

---
updated-dependencies:
- dependency-name: eslint-plugin-jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-21 11:59:15 +00:00
3997b7a5d6 fix: #2082 Numbering instance restart number not work since v8.0.0 and work well in v7.8.2 2023-09-13 17:08:59 +08:00
ccc391607a Merge pull request #2331 from hshoja/doc/update-style-with-xml
Update styling with xml  docs
2023-09-11 21:04:32 +01:00
9577192d41 build(deps-dev): bump inquirer from 9.2.7 to 9.2.11
Bumps [inquirer](https://github.com/SBoudrias/Inquirer.js) from 9.2.7 to 9.2.11.
- [Release notes](https://github.com/SBoudrias/Inquirer.js/releases)
- [Commits](https://github.com/SBoudrias/Inquirer.js/compare/inquirer@9.2.7...inquirer@9.2.11)

---
updated-dependencies:
- dependency-name: inquirer
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-11 11:40:53 +00:00
968c3aed0f Update styling-with-xml doc 2023-09-10 15:57:48 +02:00
9c7a80729b Merge branch 'master' of github.com:dolanmiu/docx 2023-08-06 20:10:11 +01:00
5f26ca1c94 Update numbering docs 2023-08-06 20:10:03 +01:00
f2b1587bff build(deps-dev): bump eslint-plugin-unicorn from 47.0.0 to 48.0.1
Bumps [eslint-plugin-unicorn](https://github.com/sindresorhus/eslint-plugin-unicorn) from 47.0.0 to 48.0.1.
- [Release notes](https://github.com/sindresorhus/eslint-plugin-unicorn/releases)
- [Commits](https://github.com/sindresorhus/eslint-plugin-unicorn/compare/v47.0.0...v48.0.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-unicorn
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-26 11:15:05 +00:00
3b9f80fb1a Merge pull request #2259 from dolanmiu/feat/bump-prettier
Bump prettier
2023-07-21 22:13:17 +01:00
8da57bec51 Bump prettier
Fix new prettier issues
2023-07-21 20:11:52 +01:00
63db9f290c Version bump 2023-07-20 22:44:30 +01:00
e8bd4bd6c6 Merge pull request #2256 from dolanmiu/feature/tweak-build
Remove default browser export
2023-07-20 22:42:56 +01:00
28d93b0c42 Remove default browser export
Fixes Angular issue
2023-07-20 20:46:53 +01:00
95f8e37006 Version bump 2023-07-19 02:10:13 +01:00
87083cb264 Merge pull request #2240 from dolanmiu/dependabot/npm_and_yarn/vite-plugin-dts-3.3.1
build(deps-dev): bump vite-plugin-dts from 2.3.0 to 3.3.1
2023-07-19 01:49:10 +01:00
1e8dc95c9c Merge pull request #2227 from dolanmiu/dependabot/npm_and_yarn/vitest/ui-0.33.0
build(deps-dev): bump @vitest/ui from 0.32.2 to 0.33.0
2023-07-19 01:49:04 +01:00
abfa242c28 build(deps-dev): bump @vitest/ui from 0.32.2 to 0.33.0
Bumps [@vitest/ui](https://github.com/vitest-dev/vitest/tree/HEAD/packages/ui) from 0.32.2 to 0.33.0.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v0.33.0/packages/ui)

---
updated-dependencies:
- dependency-name: "@vitest/ui"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 00:37:38 +00:00
56b5414152 build(deps-dev): bump vite-plugin-dts from 2.3.0 to 3.3.1
Bumps [vite-plugin-dts](https://github.com/qmhc/vite-plugin-dts) from 2.3.0 to 3.3.1.
- [Release notes](https://github.com/qmhc/vite-plugin-dts/releases)
- [Changelog](https://github.com/qmhc/vite-plugin-dts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/qmhc/vite-plugin-dts/compare/v2.3.0...v3.3.1)

---
updated-dependencies:
- dependency-name: vite-plugin-dts
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 00:37:28 +00:00
8f46060be2 Merge pull request #2235 from dolanmiu/dependabot/npm_and_yarn/types/node-20.4.2
build(deps): bump @types/node from 20.3.2 to 20.4.2
2023-07-19 01:36:41 +01:00
93b17ca2af Merge pull request #2226 from dolanmiu/dependabot/npm_and_yarn/vitest/coverage-v8-0.33.0
build(deps-dev): bump @vitest/coverage-v8 from 0.32.2 to 0.33.0
2023-07-19 01:36:27 +01:00
66008115b8 build(deps-dev): bump @vitest/coverage-v8 from 0.32.2 to 0.33.0
Bumps [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) from 0.32.2 to 0.33.0.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v0.33.0/packages/coverage-v8)

---
updated-dependencies:
- dependency-name: "@vitest/coverage-v8"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 00:23:34 +00:00
55697a7c32 build(deps): bump @types/node from 20.3.2 to 20.4.2
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.3.2 to 20.4.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 00:22:54 +00:00
e9b259db6b Merge pull request #2241 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-jsdoc-46.4.4
build(deps-dev): bump eslint-plugin-jsdoc from 46.4.2 to 46.4.4
2023-07-19 01:22:29 +01:00
55c51f7af1 Merge pull request #2238 from dolanmiu/dependabot/npm_and_yarn/eslint-8.45.0
build(deps-dev): bump eslint from 8.43.0 to 8.45.0
2023-07-19 01:22:22 +01:00
4e7fd6a6dc Merge pull request #2242 from dolanmiu/dependabot/npm_and_yarn/esbuild/win32-x64-0.18.14
build(deps-dev): bump @esbuild/win32-x64 from 0.18.10 to 0.18.14
2023-07-19 01:22:06 +01:00
6294ec448f Merge pull request #2234 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/parser-5.62.0
build(deps-dev): bump @typescript-eslint/parser from 5.60.1 to 5.62.0
2023-07-19 01:21:48 +01:00
668198b5d1 Merge pull request #2228 from dolanmiu/dependabot/npm_and_yarn/vitest-0.33.0
build(deps-dev): bump vitest from 0.32.2 to 0.33.0
2023-07-19 01:21:41 +01:00
56b2ffe706 Merge pull request #2209 from dolanmiu/dependabot/npm_and_yarn/typescript-5.1.6
build(deps-dev): bump typescript from 5.1.3 to 5.1.6
2023-07-19 01:21:35 +01:00
2ab06ffe36 Merge pull request #2244 from dolanmiu/feature/build-fixes
Fix `vite` build issues
2023-07-19 01:19:15 +01:00
0c51082bb9 Add logging output to demo 2023-07-18 21:07:19 +01:00
9a9a2019f6 Do not polyfill buffer 2023-07-18 21:06:35 +01:00
d94348f5ca Export correct type in patchDocument 2023-07-18 20:49:43 +01:00
4c10741862 build(deps-dev): bump @esbuild/win32-x64 from 0.18.10 to 0.18.14
Bumps [@esbuild/win32-x64](https://github.com/evanw/esbuild) from 0.18.10 to 0.18.14.
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.18.10...v0.18.14)

---
updated-dependencies:
- dependency-name: "@esbuild/win32-x64"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-18 11:17:06 +00:00
222a25e4e2 Compile umd version as .js format 2023-07-18 01:53:56 +01:00
5fd4490c4f build(deps-dev): bump eslint-plugin-jsdoc from 46.4.2 to 46.4.4
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 46.4.2 to 46.4.4.
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Changelog](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.releaserc)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v46.4.2...v46.4.4)

---
updated-dependencies:
- dependency-name: eslint-plugin-jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-17 11:58:39 +00:00
e1cc65cb97 build(deps-dev): bump eslint from 8.43.0 to 8.45.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.43.0 to 8.45.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.43.0...v8.45.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-17 11:57:25 +00:00
991f837bc1 build(deps-dev): bump @typescript-eslint/parser from 5.60.1 to 5.62.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.60.1 to 5.62.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.62.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-11 11:42:13 +00:00
87b3035465 build(deps-dev): bump vitest from 0.32.2 to 0.33.0
Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 0.32.2 to 0.33.0.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v0.33.0/packages/vitest)

---
updated-dependencies:
- dependency-name: vitest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-07 11:26:34 +00:00
4498305a6c Remove gitter from README 2023-07-04 12:38:54 +01:00
cac7abba91 build(deps-dev): bump typescript from 5.1.3 to 5.1.6
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.1.3 to 5.1.6.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/commits)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-30 11:39:27 +00:00
145 changed files with 7815 additions and 6111 deletions

View File

@ -17,9 +17,11 @@
"dolan", "dolan",
"execa", "execa",
"falsey", "falsey",
"horz",
"iife", "iife",
"Initializable", "Initializable",
"iroha", "iroha",
"JOHAB",
"jsonify", "jsonify",
"jszip", "jszip",
"NUMPAGES", "NUMPAGES",
@ -53,7 +55,8 @@
"\\.to\\.include\\.members\\(\\[[^\\]]+]\\)", "\\.to\\.include\\.members\\(\\[[^\\]]+]\\)",
"/new [a-zA-Z]+\\({[^£]+}\\)/g", "/new [a-zA-Z]+\\({[^£]+}\\)/g",
"/<element name=\"[a-z]+\"/gi", "/<element name=\"[a-z]+\"/gi",
"/<attribute name=\"[a-z]+\"/gi" "/<attribute name=\"[a-z]+\"/gi",
"/key: \".+\"/"
], ],
"ignorePaths": ["package.json", "docs/api", "*.docx", "build"], "ignorePaths": ["package.json", "docs/api", "*.docx", "build"],
"allowCompoundWords": true, "allowCompoundWords": true,

View File

@ -7,7 +7,6 @@ parser: "@typescript-eslint/parser"
parserOptions: parserOptions:
project: project:
- tsconfig.json - tsconfig.json
- demo/tsconfig.json
sourceType: module sourceType: module
plugins: plugins:
- eslint-plugin-import - eslint-plugin-import
@ -93,6 +92,7 @@ rules:
format: format:
- camelCase - camelCase
- PascalCase - PascalCase
- UPPER_CASE # for constants
filter: filter:
regex: (^[a-z]+:.+)|_attr|[0-9] regex: (^[a-z]+:.+)|_attr|[0-9]
match: false match: false
@ -214,8 +214,7 @@ rules:
valid-typeof: "off" valid-typeof: "off"
functional/immutable-data: functional/immutable-data:
- error - error
- assumeTypes: true - ignoreImmediateMutation: true
ignoreImmediateMutation: true
ignoreAccessorPattern: ignoreAccessorPattern:
- "**.root*" - "**.root*"
- "**.numberingReferences*" - "**.numberingReferences*"

View 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

View 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

View File

@ -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

View File

@ -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 run: npm run run-ts -- ./demo/1-basic.ts
- name: Download Artifact - uses: "./.github/actions/validate-docx"
uses: actions/download-artifact@master - run: npm run run-ts -- ./demo/2-declaritive-styles.ts
with: - uses: "./.github/actions/validate-docx"
name: build - run: npm run run-ts -- ./demo/3-numbering-and-bullet-points.ts
path: build - uses: "./.github/actions/validate-docx"
- name: Run Demo - run: npm run run-ts -- ./demo/4-basic-table.ts
run: npm run ts-node -- ./demo/1-basic.ts - uses: "./.github/actions/validate-docx"
- name: Extract Word Document - run: npm run run-ts -- ./demo/5-images.ts
run: npm run extract - uses: "./.github/actions/validate-docx"
- name: Validate XML - run: npm run run-ts -- ./demo/6-page-borders.ts
uses: ChristophWurst/xmllint-action@v1 - uses: "./.github/actions/validate-docx"
with: - run: npm run run-ts -- ./demo/7-landscape.ts
xml-file: build/extracted-doc/word/document.xml - uses: "./.github/actions/validate-docx"
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - run: npm run run-ts -- ./demo/8-header-footer.ts
- name: Run Demo - uses: "./.github/actions/validate-docx"
run: npm run ts-node -- ./demo/2-declaritive-styles.ts - run: npm run run-ts -- ./demo/9-images-in-header-and-footer.ts
- name: Extract Word Document - uses: "./.github/actions/validate-docx"
run: npm run extract - run: npm run run-ts -- ./demo/10-my-cv.ts
- name: Validate XML - uses: "./.github/actions/validate-docx"
uses: ChristophWurst/xmllint-action@v1 - run: npm run run-ts -- ./demo/11-declaritive-styles-2.ts
with: - uses: "./.github/actions/validate-docx"
xml-file: build/extracted-doc/word/document.xml - run: npm run run-ts -- ./demo/12-scaling-images.ts
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - uses: "./.github/actions/validate-docx"
- name: Run Demo - run: npm run run-ts -- ./demo/13-xml-styles.ts
run: npm run ts-node -- ./demo/3-numbering-and-bullet-points.ts - uses: "./.github/actions/validate-docx"
- name: Extract Word Document - run: npm run run-ts -- ./demo/14-page-numbers.ts
run: npm run extract - uses: "./.github/actions/validate-docx"
- name: Validate XML - run: npm run run-ts -- ./demo/15-page-break-before.ts
uses: ChristophWurst/xmllint-action@v1 - uses: "./.github/actions/validate-docx"
with: - run: npm run run-ts -- ./demo/16-multiple-sections.ts
xml-file: build/extracted-doc/word/document.xml - uses: "./.github/actions/validate-docx"
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - run: npm run run-ts -- ./demo/17-footnotes.ts
- name: Run Demo
run: npm run ts-node -- ./demo/4-basic-table.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/5-images.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/6-page-borders.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/7-landscape.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/8-header-footer.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/9-images-in-header-and-footer.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/10-my-cv.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/11-declaritive-styles-2.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/12-scaling-images.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/13-xml-styles.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/14-page-numbers.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/15-page-break-before.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/16-multiple-sections.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/17-footnotes.ts
- name: Extract Word Document
run: npm run extract
# element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected. # element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected.
# - name: Validate XML # - uses: "./.github/actions/validate-docx"
# uses: ChristophWurst/xmllint-action@v1 - run: npm run run-ts -- ./demo/18-image-from-buffer.ts
# with: - uses: "./.github/actions/validate-docx"
# xml-file: build/extracted-doc/word/document.xml - run: npm run run-ts -- ./demo/19-export-to-base64.ts
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/18-image-from-buffer.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/19-export-to-base64.ts
# Base 64 No longer works, abruptly. Node issue? # Base 64 No longer works, abruptly. Node issue?
# - name: Extract Word Document # - uses: "./.github/actions/validate-docx"
# run: npm run extract - run: npm run run-ts -- ./demo/20-table-cell-borders.ts
# - name: Validate XML - uses: "./.github/actions/validate-docx"
# uses: ChristophWurst/xmllint-action@v1 - run: npm run run-ts -- ./demo/21-bookmarks.ts
# with:
# xml-file: build/extracted-doc/word/document.xml
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/20-table-cell-borders.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/21-bookmarks.ts
- name: Extract Word Document
run: npm run extract
# Bad ID - need numeric ID # Bad ID - need numeric ID
# - name: Validate XML # - uses: "./.github/actions/validate-docx"
# uses: ChristophWurst/xmllint-action@v1 - run: npm run run-ts -- ./demo/22-right-to-left-text.ts
# with: - uses: "./.github/actions/validate-docx"
# xml-file: build/extracted-doc/word/document.xml - run: npm run run-ts -- ./demo/23-base64-images.ts
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - uses: "./.github/actions/validate-docx"
- name: Run Demo - run: npm run run-ts -- ./demo/24-images-to-table-cell.ts
run: npm run ts-node -- ./demo/22-right-to-left-text.ts - uses: "./.github/actions/validate-docx"
- name: Extract Word Document - run: npm run run-ts -- ./demo/25-table-xml-styles.ts
run: npm run extract - uses: "./.github/actions/validate-docx"
- name: Validate XML - run: npm run run-ts -- ./demo/26-paragraph-borders.ts
uses: ChristophWurst/xmllint-action@v1 - uses: "./.github/actions/validate-docx"
with: - run: npm run run-ts -- ./demo/27-declaritive-styles-3.ts
xml-file: build/extracted-doc/word/document.xml - uses: "./.github/actions/validate-docx"
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - run: npm run run-ts -- ./demo/28-table-of-contents.ts
- name: Run Demo - uses: "./.github/actions/validate-docx"
run: npm run ts-node -- ./demo/23-base64-images.ts - run: npm run run-ts -- ./demo/29-numbered-lists.ts
- name: Extract Word Document - uses: "./.github/actions/validate-docx"
run: npm run extract - run: npm run run-ts -- ./demo/31-tables.ts
- name: Validate XML - uses: "./.github/actions/validate-docx"
uses: ChristophWurst/xmllint-action@v1 - run: npm run run-ts -- ./demo/32-merge-and-shade-table-cells.ts
with: - uses: "./.github/actions/validate-docx"
xml-file: build/extracted-doc/word/document.xml - run: npm run run-ts -- ./demo/33-sequential-captions.ts
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - uses: "./.github/actions/validate-docx"
- name: Run Demo - run: npm run run-ts -- ./demo/34-floating-tables.ts
run: npm run ts-node -- ./demo/24-images-to-table-cell.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/25-table-xml-styles.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/26-paragraph-borders.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/27-declaritive-styles-3.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/28-table-of-contents.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/29-numbered-lists.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/31-tables.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/32-merge-and-shade-table-cells.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/33-sequential-captions.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/34-floating-tables.ts
- name: Extract Word Document
run: npm run extract
# element tblpPr: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tblpPr', attribute 'overlap': The attribute 'overlap' is not allowed. # element tblpPr: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tblpPr', attribute 'overlap': The attribute 'overlap' is not allowed.
# element tblpPr: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tblpPr': Element content is not allowed, because the content type is empty. # element tblpPr: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tblpPr': Element content is not allowed, because the content type is empty.
# - name: Validate XML # - uses: "./.github/actions/validate-docx"
# uses: ChristophWurst/xmllint-action@v1 - run: npm run run-ts -- ./demo/35-hyperlinks.ts
# with: - uses: "./.github/actions/validate-docx"
# xml-file: build/extracted-doc/word/document.xml - run: npm run run-ts -- ./demo/36-image-to-table-cell.ts
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - uses: "./.github/actions/validate-docx"
- name: Run Demo - run: npm run run-ts -- ./demo/37-images-to-header-and-footer.ts
run: npm run ts-node -- ./demo/35-hyperlinks.ts - uses: "./.github/actions/validate-docx"
- name: Extract Word Document - run: npm run run-ts -- ./demo/38-text-wrapping.ts
run: npm run extract - uses: "./.github/actions/validate-docx"
- name: Validate XML - run: npm run run-ts -- ./demo/39-page-numbers.ts
uses: ChristophWurst/xmllint-action@v1 - uses: "./.github/actions/validate-docx"
with: - run: npm run run-ts -- ./demo/40-line-numbers.ts
xml-file: build/extracted-doc/word/document.xml - uses: "./.github/actions/validate-docx"
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - run: npm run run-ts -- ./demo/41-merge-table-cells-2.ts
- name: Run Demo - uses: "./.github/actions/validate-docx"
run: npm run ts-node -- ./demo/36-image-to-table-cell.ts - run: npm run run-ts -- ./demo/42-restart-page-numbers.ts
- name: Extract Word Document - uses: "./.github/actions/validate-docx"
run: npm run extract - run: npm run run-ts -- ./demo/43-images-to-table-cell-2.ts
- name: Validate XML - uses: "./.github/actions/validate-docx"
uses: ChristophWurst/xmllint-action@v1 - run: npm run run-ts -- ./demo/44-multiple-columns.ts
with: - uses: "./.github/actions/validate-docx"
xml-file: build/extracted-doc/word/document.xml - run: npm run run-ts -- ./demo/45-highlighting-text.ts
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - uses: "./.github/actions/validate-docx"
- name: Run Demo - run: npm run run-ts -- ./demo/46-shading-text.ts
run: npm run ts-node -- ./demo/37-images-to-header-and-footer.ts - uses: "./.github/actions/validate-docx"
- name: Extract Word Document - run: npm run run-ts -- ./demo/47-number-of-total-pages-section.ts
run: npm run extract - uses: "./.github/actions/validate-docx"
- name: Validate XML - run: npm run run-ts -- ./demo/48-vertical-align.ts
uses: ChristophWurst/xmllint-action@v1 - uses: "./.github/actions/validate-docx"
with: - run: npm run run-ts -- ./demo/49-table-borders.ts
xml-file: build/extracted-doc/word/document.xml - uses: "./.github/actions/validate-docx"
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - run: npm run run-ts -- ./demo/50-readme-demo.ts
- name: Run Demo - uses: "./.github/actions/validate-docx"
run: npm run ts-node -- ./demo/38-text-wrapping.ts - run: npm run run-ts -- ./demo/51-character-styles.ts
- name: Extract Word Document - uses: "./.github/actions/validate-docx"
run: npm run extract - run: npm run run-ts -- ./demo/52-japanese.ts
- name: Validate XML - uses: "./.github/actions/validate-docx"
uses: ChristophWurst/xmllint-action@v1 - run: npm run run-ts -- ./demo/53-chinese.ts
with: - uses: "./.github/actions/validate-docx"
xml-file: build/extracted-doc/word/document.xml - run: npm run run-ts -- ./demo/54-custom-properties.ts
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - uses: "./.github/actions/validate-docx"
- name: Run Demo - run: npm run run-ts -- ./demo/55-math.ts
run: npm run ts-node -- ./demo/39-page-numbers.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/40-line-numbers.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/41-merge-table-cells-2.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/42-restart-page-numbers.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/43-images-to-table-cell-2.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/44-multiple-columns.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/45-highlighting-text.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/46-shading-text.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/47-number-of-total-pages-section.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/48-vertical-align.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/49-table-borders.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/50-readme-demo.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/51-character-styles.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/52-japanese.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/53-chinese.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/54-custom-properties.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/55-math.ts
- name: Extract Word Document
run: npm run extract
#: element subHide: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}subHide': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}ctrlPr ). #: element subHide: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}subHide': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}ctrlPr ).
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sub ). #: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sub ).
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sup ). #: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sup ).
#: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sub ). #: element e: Schemas validity error : Element '{http://schemas.openxmlformats.org/officeDocument/2006/math}e': This element is not expected. Expected is ( {http://schemas.openxmlformats.org/officeDocument/2006/math}sub ).
# - name: Validate XML # - uses: "./.github/actions/validate-docx"
# uses: ChristophWurst/xmllint-action@v1 - run: npm run run-ts -- ./demo/56-background-color.ts
# with: - uses: "./.github/actions/validate-docx"
# xml-file: build/extracted-doc/word/document.xml - run: npm run run-ts -- ./demo/57-add-parent-numbered-lists.ts
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - uses: "./.github/actions/validate-docx"
- name: Run Demo - run: npm run run-ts -- ./demo/58-section-types.ts
run: npm run ts-node -- ./demo/56-background-color.ts - uses: "./.github/actions/validate-docx"
- name: Extract Word Document - run: npm run run-ts -- ./demo/59-header-footer-margins.ts
run: npm run extract - uses: "./.github/actions/validate-docx"
- name: Validate XML - run: npm run run-ts -- ./demo/60-track-revisions.ts
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/57-add-parent-numbered-lists.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/58-section-types.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/59-header-footer-margins.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/60-track-revisions.ts
- name: Extract Word Document
run: npm run extract
# element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected. # element r: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}r': This element is not expected.
# - name: Validate XML # - uses: "./.github/actions/validate-docx"
# uses: ChristophWurst/xmllint-action@v1 - run: npm run run-ts -- ./demo/61-text-frame.ts
# with:
# xml-file: build/extracted-doc/word/document.xml
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/61-text-frame.ts
- name: Extract Word Document
run: npm run extract
# element left: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}left': This element is not expected. Expected is one of ( {http://schemas.openxmlformats.org/wordprocessingml/2006/main}right, {http://schemas.openxmlformats.org/wordprocessingml/2006/main}between, {http://schemas.openxmlformats.org/wordprocessingml/2006/main}bar ). # element left: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}left': This element is not expected. Expected is one of ( {http://schemas.openxmlformats.org/wordprocessingml/2006/main}right, {http://schemas.openxmlformats.org/wordprocessingml/2006/main}between, {http://schemas.openxmlformats.org/wordprocessingml/2006/main}bar ).
# - name: Validate XML # - uses: "./.github/actions/validate-docx"
# uses: ChristophWurst/xmllint-action@v1 - run: npm run run-ts -- ./demo/62-paragraph-spacing.ts
# with: - uses: "./.github/actions/validate-docx"
# xml-file: build/extracted-doc/word/document.xml - run: npm run run-ts -- ./demo/63-odd-even-header-footer.ts
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - uses: "./.github/actions/validate-docx"
- name: Run Demo - run: npm run run-ts -- ./demo/64-complex-numbering-text.ts
run: npm run ts-node -- ./demo/62-paragraph-spacing.ts - uses: "./.github/actions/validate-docx"
- name: Extract Word Document - run: npm run run-ts -- ./demo/65-page-sizes.ts
run: npm run extract - uses: "./.github/actions/validate-docx"
- name: Validate XML - run: npm run run-ts -- ./demo/66-fields.ts
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/63-odd-even-header-footer.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/64-complex-numbering-text.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/65-page-sizes.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/66-fields.ts
- name: Extract Word Document
run: npm run extract
# element bookmarkStart: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}bookmarkStart', attribute '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}id': '-irrswq-ln94j4fdgdjxs' is not a valid value of the atomic type '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ST_DecimalNumber'. # element bookmarkStart: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}bookmarkStart', attribute '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}id': '-irrswq-ln94j4fdgdjxs' is not a valid value of the atomic type '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ST_DecimalNumber'.
# element bookmarkEnd: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}bookmarkEnd', attribute '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}id': '-irrswq-ln94j4fdgdjxs' is not a valid value of the atomic type '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ST_DecimalNumber'. # element bookmarkEnd: Schemas validity error : Element '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}bookmarkEnd', attribute '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}id': '-irrswq-ln94j4fdgdjxs' is not a valid value of the atomic type '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ST_DecimalNumber'.
# - name: Validate XML # - uses: "./.github/actions/validate-docx"
# uses: ChristophWurst/xmllint-action@v1 - run: npm run run-ts -- ./demo/67-column-break.ts
# with: - uses: "./.github/actions/validate-docx"
# xml-file: build/extracted-doc/word/document.xml - run: npm run run-ts -- ./demo/68-numbering-instances-and-starting-number.ts
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - uses: "./.github/actions/validate-docx"
- name: Run Demo - run: npm run run-ts -- ./demo/69-different-width-columns.ts
run: npm run ts-node -- ./demo/67-column-break.ts - uses: "./.github/actions/validate-docx"
- name: Extract Word Document - run: npm run run-ts -- ./demo/70-line-numbers-suppression.ts
run: npm run extract - uses: "./.github/actions/validate-docx"
- name: Validate XML - run: npm run run-ts -- ./demo/71-page-borders-2.ts
uses: ChristophWurst/xmllint-action@v1 - uses: "./.github/actions/validate-docx"
with: - run: npm run run-ts -- ./demo/72-word-wrap.ts
xml-file: build/extracted-doc/word/document.xml - uses: "./.github/actions/validate-docx"
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - run: npm run run-ts -- ./demo/73-comments.ts
- name: Run Demo - uses: "./.github/actions/validate-docx"
run: npm run ts-node -- ./demo/68-numbering-instances-and-starting-number.ts - run: npm run run-ts -- ./demo/74-nodejs-stream.ts
- name: Extract Word Document # - uses: "./.github/actions/validate-docx"
run: npm run extract # run: npm run run-ts -- ./demo/75-tab-stops.ts
- name: Validate XML # - uses: "./.github/actions/validate-docx"
uses: ChristophWurst/xmllint-action@v1 - run: npm run run-ts -- ./demo/76-compatibility.ts
with: - uses: "./.github/actions/validate-docx"
xml-file: build/extracted-doc/word/document.xml - run: npm run run-ts -- ./demo/77-side-by-side-tables.ts
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - uses: "./.github/actions/validate-docx"
- name: Run Demo - run: npm run run-ts -- ./demo/78-thai-distributed.ts
run: npm run ts-node -- ./demo/69-different-width-columns.ts - uses: "./.github/actions/validate-docx"
- name: Extract Word Document - run: npm run run-ts -- ./demo/79-table-from-data-source.ts
run: npm run extract - uses: "./.github/actions/validate-docx"
- name: Validate XML - run: npm run run-ts -- ./demo/80-thai-distributed.ts
uses: ChristophWurst/xmllint-action@v1 - uses: "./.github/actions/validate-docx"
with: - run: npm run run-ts -- ./demo/81-continuous-header.ts
xml-file: build/extracted-doc/word/document.xml - uses: "./.github/actions/validate-docx"
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd - run: npm run run-ts -- ./demo/82-new-headers-new-section.ts
- name: Run Demo - uses: "./.github/actions/validate-docx"
run: npm run ts-node -- ./demo/70-line-numbers-suppression.ts - run: npm run run-ts -- ./demo/83-setting-languages.ts
- name: Extract Word Document - uses: "./.github/actions/validate-docx"
run: npm run extract - run: npm run run-ts -- ./demo/84-positional-tabs.ts
- name: Validate XML - uses: "./.github/actions/validate-docx"
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/71-page-borders-2.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/72-word-wrap.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/73-comments.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/73-comments.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
# - name: Run Demo
# run: npm run ts-node -- ./demo/75-tab-stops.ts
# - name: Extract Word Document
# run: npm run extract
# - name: Validate XML
# uses: ChristophWurst/xmllint-action@v1
# with:
# xml-file: build/extracted-doc/word/document.xml
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/76-compatibility.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/77-side-by-side-tables.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/78-thai-distributed.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/79-table-from-data-source.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/80-thai-distributed.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/81-continuous-header.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/82-new-headers-new-section.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/83-setting-languages.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/84-positional-tabs.ts
- name: Extract Word Document
run: npm run extract
- name: Validate XML
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd

16
.vscode/launch.json vendored
View File

@ -1,18 +1,4 @@
{ {
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": []
{
"name": "Run Demo",
"type": "node",
"request": "launch",
"runtimeArgs": [
"-r",
"${workspaceFolder}/node_modules/ts-node/register",
"-r",
"${workspaceFolder}/node_modules/tsconfig-paths/register"
],
"cwd": "${workspaceRoot}",
"program": "${workspaceFolder}/demo/85-template-document.ts"
}
]
} }

20
.vscode/tasks.json vendored
View File

@ -2,23 +2,5 @@
// See https://go.microsoft.com/fwlink/?LinkId=733558 // See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format // for the documentation about the tasks.json format
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": []
{
"type": "typescript",
"tsconfig": "tsconfig.json",
"option": "watch",
"problemMatcher": [
"$tsc-watch"
]
},
{
"type": "npm",
"script": "ts-node",
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
}
}
]
} }

View File

@ -12,7 +12,6 @@
[![Downloads per month][downloads-image]][downloads-url] [![Downloads per month][downloads-image]][downloads-url]
[![GitHub Action Workflow Status][github-actions-workflow-image]][github-actions-workflow-url] [![GitHub Action Workflow Status][github-actions-workflow-image]][github-actions-workflow-url]
[![Known Vulnerabilities][snky-image]][snky-url] [![Known Vulnerabilities][snky-image]][snky-url]
[![Chat on Gitter][gitter-image]][gitter-url]
[![PRs Welcome][pr-image]][pr-url] [![PRs Welcome][pr-image]][pr-url]
[![codecov][codecov-image]][codecov-url] [![codecov][codecov-image]][codecov-url]
@ -107,8 +106,6 @@ Made with 💖
[github-actions-workflow-url]: https://github.com/dolanmiu/docx/actions [github-actions-workflow-url]: https://github.com/dolanmiu/docx/actions
[snky-image]: https://snyk.io/test/github/dolanmiu/docx/badge.svg [snky-image]: https://snyk.io/test/github/dolanmiu/docx/badge.svg
[snky-url]: https://snyk.io/test/github/dolanmiu/docx [snky-url]: https://snyk.io/test/github/dolanmiu/docx
[gitter-image]: https://badges.gitter.im/dolanmiu/docx.svg
[gitter-url]: https://gitter.im/docx-lib/Lobby
[pr-image]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg [pr-image]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg
[pr-url]: http://makeapullrequest.com [pr-url]: http://makeapullrequest.com
[codecov-image]: https://codecov.io/gh/dolanmiu/docx/branch/master/graph/badge.svg [codecov-image]: https://codecov.io/gh/dolanmiu/docx/branch/master/graph/badge.svg

View File

@ -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],
}), }),
], ],
}), }),

View File

@ -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),
},
}), }),
], ],
}), }),

View File

@ -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,
}),
],
}),
], ],
}, },
], ],

View File

@ -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);
}); });

View File

@ -18,6 +18,7 @@ const receiptTabStops = [
const twoTabStops = [{ type: TabStopType.RIGHT, position: TabStopPosition.MAX }]; const twoTabStops = [{ type: TabStopType.RIGHT, position: TabStopPosition.MAX }];
const doc = new Document({ const doc = new Document({
defaultTabStop: 0,
sections: [ sections: [
{ {
properties: {}, properties: {},

40
demo/91-custom-fonts.ts Normal file
View 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);
});

View 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

Binary file not shown.

View File

@ -1,7 +1,7 @@
<!DOCTYPE html> <!doctype html>
<html> <html>
<head> <head>
<script src="../build/index.umd.cjs"></script> <script src="../build/index.umd.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js"></script>
</head> </head>

View File

@ -5,9 +5,9 @@ import inquirer from "inquirer";
import { $ } from "execa"; import { $ } from "execa";
export type Answers = { export type Answers = {
type: "list" | "number"; readonly type: "list" | "number";
demoNumber?: number; readonly demoNumber?: number;
demoFile?: number; readonly demoFile?: number;
}; };
const dir = "./demo"; const dir = "./demo";
@ -15,8 +15,7 @@ const fileNames = fs.readdirSync(dir);
const keys = fileNames.map((f) => path.parse(f).name); const keys = fileNames.map((f) => path.parse(f).name);
const getFileNumber = (file: string): number => { const getFileNumber = (file: string): number => {
const nameParts = file.split("-"); const [firstPart] = file.split("-");
const firstPart = nameParts[0];
return Number(firstPart); return Number(firstPart);
}; };
@ -35,15 +34,15 @@ const answers = await inquirer.prompt<Answers>([
name: "demoFile", name: "demoFile",
message: "What demo do you wish to run?", message: "What demo do you wish to run?",
choices: demoFiles, choices: demoFiles,
filter: (input) => parseInt(input.split("-")[0]), filter: (input) => parseInt(input.split("-")[0], 10),
when: (answers) => answers.type === "list", when: (a) => a.type === "list",
}, },
{ {
type: "number", type: "number",
name: "demoNumber", name: "demoNumber",
message: "What demo do you wish to run? (Enter a number)", message: "What demo do you wish to run? (Enter a number)",
default: 1, default: 1,
when: (answers) => answers.type === "number", when: (a) => a.type === "number",
}, },
]); ]);
@ -56,6 +55,7 @@ if (files.length === 0) {
const filePath = path.join(dir, files[0]); const filePath = path.join(dir, files[0]);
console.log(`Running demo ${demoNumber}: ${files[0]}`); console.log(`Running demo ${demoNumber}: ${files[0]}`);
await $`ts-node --project demo/tsconfig.json ${filePath}`; const { stdout } = await $`tsx ${filePath}`;
console.log(stdout);
console.log("Successfully created document!"); console.log("Successfully created document!");
} }

View File

@ -7,4 +7,4 @@
} }
}, },
"include": ["../demo"] "include": ["../demo"]
} }

View File

@ -1,5 +1,7 @@
# Bullets and Numbering # Bullets and Numbering
!> Bullets and Numbering requires an understanding of [Sections](usage/sections.md) and [Paragraphs](usage/paragraph.md).
`docx` is quite flexible in its bullets and numbering system, allowing `docx` is quite flexible in its bullets and numbering system, allowing
the user great freedom in how bullets and numbers are to be styled and the user great freedom in how bullets and numbers are to be styled and
displayed. E.g., numbers can be shown using Arabic numerals, roman displayed. E.g., numbers can be shown using Arabic numerals, roman
@ -8,112 +10,128 @@ format also supports re-using bullets/numbering styles throughout the
document, so that different lists using the same style need not document, so that different lists using the same style need not
redefine them. redefine them.
Because of this flexibility, bullets and numbering in DOCX involves a ## Configuration
couple of moving pieces:
1. Document-level bullets/numbering definitions (abstract) Numbering is configured by adding config into `Document`:
2. Document-level bullets/numbering definitions (concrete)
3. Paragraph-level bullets/numbering selection
## Document-level bullets/numbering definitions (abstract)
Every document contains a set of abstract bullets/numbering
definitions which define the formatting and layout of paragraphs using
those bullets/numbering. An abstract numbering system defines how
bullets/numbers are to be shown for lists, including any sublists that
may be used. Thus each abstract definition includes a series of
_levels_ which form a sequence starting at 0 indicating the top-level
list look and increasing from there to describe the sublists, then
sub-sublists, etc. Each level includes the following properties:
* **level**: This is its 0-based index in the definition stack
* **numberFormat**: This indicates how the bullet or number should be
generated. Options include `bullet` (meaning don't count), `decimal`
(arabic numerals), `upperRoman`, `lowerRoman`, `hex`, and many
more.
* **levelText**: This is a format string using the output of the
`numberFormat` function and generating a string to insert before
every item in the list. You may use `%1`, `%2`, ... to reference the
numbers from each numbering level before this one. Thus a level
text of `%d)` with a number format of `lowerLetter` would result in
the sequence "a)", "b)", ...
* and a few others, which you can see in the OOXML spec section 17.9.6
## Document-level bullets/numbering definitions (concrete)
Concrete definitions are sort of like concrete subclasses of the
abstract definitions. They indicate their parent and are allowed to
override certain level definitions. Thus two lists that differ only in
how sub-sub-lists are to be displayed can share the same abstract
numbering definition and have slightly different concrete definitions.
## Paragraph-level bullets/numbering selection
In order to use a bullets/numbering definition (which must be
concrete), paragraphs need to select it, similar to applying a CSS
class to an element, using both the concrete numbering definition ID
and the level number that the paragraph should be at. Additionally, MS
Word and LibreOffice typically apply a "ListParagraph" style to
paragraphs that are being numbered.
## Using bullets/numbering in `docx`
`docx` includes a pre-defined bullet style which you can add to your
paragraphs using `para.bullets()`. If you require different bullet
styles or numbering of any kind, you'll have to use the
`docx.Numbering` class.
First you need to create a new numbering container class and use it to
create your abstract numbering style, define your levels, and create
your concrete numbering style:
```ts ```ts
const numbering = new docx.Numbering(); new Document({
numbering: {
const abstractNum = numbering.createAbstractNumbering(); config: [...]
abstractNum.createLevel(0, "upperRoman", "%1", "start").addParagraphProperty(new Indent(720, 260)); }
abstractNum.createLevel(1, "decimal", "%2.", "start").addParagraphProperty(new Indent(1440, 980)); })
abstractNum.createLevel(2, "lowerLetter", "%3)", "start").addParagraphProperty(new Indent(2160, 1700));
const concrete = numbering.createConcreteNumbering(abstractNum);
``` ```
You can then apply your concrete style to paragraphs using the Each `config` entry includes the following properties:
`setNumbering` method:
. Each level includes the following properties:
| Property | Type | Notes | Possible Values |
| --------- | ----------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| reference | `string` | Required | A unique `string` |
| levels | `ILevelOptions[]` | Required | a series of _levels_ which form a sequence starting at 0 indicating the top-level list look and increasing from there to describe the sublists, then sub-sublists, etc |
### Level Options
Levels define the numbering definition itself, what it looks like, the indention, the alignment and the style. The reason why it is an array is because it allows the ability to create sub-lists. A sub list will have a different configuration because you may want the sub-list to have a different indentation or different bullet.
| Property | Type | Notes | Possible Values |
| --------- | ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| level | `number` | Required | The list level this definition is for. `0` is for the root level, `1` is for a sub list, `2` is for a sub-sub-list etc. |
| format | `LevelFormat` | Optional | `DECIMAL`, `UPPER_ROMAN`, `LOWER_ROMAN`, `UPPER_LETTER`, `LOWER_LETTER`, `ORDINAL`, `CARDINAL_TEXT`, `ORDINAL_TEXT`, `HEX`, `CHICAGO`, `IDEOGRAPH__DIGITAL`, `JAPANESE_COUNTING`, `AIUEO`, `IROHA`, `DECIMAL_FULL_WIDTH`, `DECIMAL_HALF_WIDTH`, `JAPANESE_LEGAL`, `JAPANESE_DIGITAL_TEN_THOUSAND`, `DECIMAL_ENCLOSED_CIRCLE`, `DECIMAL_FULL_WIDTH2`, `AIUEO_FULL_WIDTH`, `IROHA_FULL_WIDTH`, `DECIMAL_ZERO`, `BULLET`, `GANADA`, `CHOSUNG`, `DECIMAL_ENCLOSED_FULLSTOP`, `DECIMAL_ENCLOSED_PARENTHESES`, `DECIMAL_ENCLOSED_CIRCLE_CHINESE`, `IDEOGRAPH_ENCLOSED_CIRCLE`, `IDEOGRAPH_TRADITIONAL`, `IDEOGRAPH_ZODIAC`, `IDEOGRAPH_ZODIAC_TRADITIONAL`, `TAIWANESE_COUNTING`, `IDEOGRAPH_LEGAL_TRADITIONAL`, `TAIWANESE_COUNTING_THOUSAND`, `TAIWANESE_DIGITAL`, `CHINESE_COUNTING`, `CHINESE_LEGAL_SIMPLIFIED`, `CHINESE_COUNTING_THOUSAND`, `KOREAN_DIGITAL`, `KOREAN_COUNTING`, `KOREAN_LEGAL`, `KOREAN_DIGITAL2`, `VIETNAMESE_COUNTING`, `RUSSIAN_LOWER`, `RUSSIAN_UPPER`, `NONE`, `NUMBER_IN_DASH`, `HEBREW1`, `HEBREW2`, `ARABIC_ALPHA`, `ARABIC_ABJAD`, `HINDI_VOWELS`, `HINDI_CONSONANTS`, `HINDI_NUMBERS`, `HINDI_COUNTING`, `THAI_LETTERS`, `THAI_NUMBERS`, `THAI_COUNTING`, `BAHT_TEXT`, `DOLLAR_TEXT`, `CUSTOM` |
| text | `string` | Optional | A unique `string` to describe the shape of the bullet |
| alignment | `string` | Required | `START`, `CENTER`, `END`, `BOTH`, `MEDIUM_KASHIDA`, `DISTRIBUTE`, `NUM_TAB`, `HIGH_KASHIDA`, `LOW_KASHIDA`, `THAI_DISTRIBUTE`, `LEFT`, `RIGHT`, `JUSTIFIED` |
| style | `string` | Optional | [Sections](usage/styling-with-js.md) |
## Using ordered lists in `docx`
Add a `numbering` section to the `Document` to numbering style, define your levels. Use `LevelFormat.UPPER_ROMAN` for the `format` in `levels`:
```ts ```ts
topLevelP.setNumbering(concrete, 0); const doc = new Document({
subP.setNumbering(concrete, 1); ...
subSubP.setNumbering(concrete, 2); numbering: {
config: [
{
reference: "my-numbering",
levels: [
{
level: 0,
format: LevelFormat.UPPER_ROMAN,
text: "%1",
alignment: AlignmentType.START,
style: {
paragraph: {
indent: { left: 2880, hanging: 2420 },
},
},
},
...
],
},
],
},
...
});
``` ```
## Unindent numbering And then on a `Paragraph`, we can add use the numbering created:
Default:1. test
After:1.test
Use default numbering have indent,If you want unindent numbering
How to custom number see the demo:
https://runkit.com/dolanmiu/docx-demo3
```ts ```ts
new Paragraph({
enum LevelSuffix { text: "Hey you!",
NOTHING = "nothing", numbering: {
SPACE = "space", reference: "my-numbering",
TAB = "tab" level: 0,
} },
}),
// custom numbering
const levels=[
{
level: 0,
format: "decimal",
text: "%1.",
alignment: AlignmentType.START,
suffix: LevelSuffix.NOTHING, // Cancel intent
}]
``` ```
## Un-ordered lists / Bullet points
Add a `numbering` section to the `Document` to numbering style, define your levels. Use `LevelFormat.BULLET` for the `format` in `levels`:
```ts
const doc = new Document({
...
numbering: {
config: [
{
reference: "my-bullet-points",
levels: [
{
level: 0,
format: LevelFormat.BULLET,
text: "\u1F60",
alignment: AlignmentType.LEFT,
style: {
paragraph: {
indent: { left: convertInchesToTwip(0.5), hanging: convertInchesToTwip(0.25) },
},
},
},
],
},
],
},
...
});
```
And then on a `Paragraph`, we can add use the numbering created:
```ts
new Paragraph({
text: "Hey you!",
numbering: {
reference: "my-bullet-points",
level: 0,
},
}),
```
## Full Example
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/3-numbering-and-bullet-points.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/3-numbering-and-bullet-points.ts_

View File

@ -9,11 +9,16 @@
![image](https://user-images.githubusercontent.com/2917613/41195113-65edebfa-6c1f-11e8-97b4-77de2d60044a.png) ![image](https://user-images.githubusercontent.com/2917613/41195113-65edebfa-6c1f-11e8-97b4-77de2d60044a.png)
![image](https://user-images.githubusercontent.com/2917613/41195126-ca99c36c-6c1f-11e8-9e58-19e5f69b3b87.png) ![image](https://user-images.githubusercontent.com/2917613/41195126-ca99c36c-6c1f-11e8-9e58-19e5f69b3b87.png)
*Note*: Font and color selection from the theme are currently not supported.
3. You can even create a totally new `Style`: 3. You can even create a totally new `Style`:
![image](https://user-images.githubusercontent.com/2917613/41195135-f0f7862a-6c1f-11e8-8be4-dd6d8fe5be03.png) ![image](https://user-images.githubusercontent.com/2917613/41195135-f0f7862a-6c1f-11e8-8be4-dd6d8fe5be03.png)
![image](https://user-images.githubusercontent.com/2917613/41195139-0ec52130-6c20-11e8-8fae-f6b44b43fdf8.png) ![image](https://user-images.githubusercontent.com/2917613/41195139-0ec52130-6c20-11e8-8fae-f6b44b43fdf8.png)
*Note*: When selecting the style type, it is important to consider the component being used.
4. Save 4. Save
5. Re-name the saved `.docx` file to `.zip` and un-zip 5. Re-name the saved `.docx` file to `.zip` and un-zip
6. Find `styles.xml` 6. Find `styles.xml`

8657
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,17 @@
{ {
"name": "docx", "name": "docx",
"version": "8.2.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.cjs", "main": "build/index.umd.js",
"module": "./build/index.js", "module": "./build/index.mjs",
"types": "./build/index.d.ts", "types": "./build/index.d.ts",
"exports": { "exports": {
".": { ".": {
"browser": {
"default": "./build/index.umd.cjs"
},
"require": "./build/index.cjs", "require": "./build/index.cjs",
"types": "./build/index.d.ts", "types": "./build/index.d.ts",
"import": "./build/index.js", "import": "./build/index.mjs",
"default": "./build/index.js" "default": "./build/index.mjs"
} }
}, },
"files": [ "files": [
@ -23,21 +20,21 @@
"scripts": { "scripts": {
"build": "tsc && vite build", "build": "tsc && vite build",
"test": "vitest --ui --coverage", "test": "vitest --ui --coverage",
"test.ci": "vitest run --coverage", "test:ci": "vitest run --coverage",
"prepublishOnly": "npm run build --omit=dev", "prepublishOnly": "npm run build --omit=dev",
"lint": "eslint --ext .ts src", "lint": "eslint --ext .ts src",
"predemo": "npm run build", "predemo": "npm run build",
"demo": "ts-node --project demo/tsconfig.json ./demo/index.ts", "demo": "tsx ./demo/index.ts",
"typedoc": "typedoc src/index.ts --tsconfig tsconfig.typedoc.json", "typedoc": "typedoc src/index.ts --tsconfig tsconfig.typedoc.json",
"style": "prettier -l \"{src,scripts,demo}/**/*.{ts,html}\"", "prettier": "prettier -l \"{src,scripts,demo}/**/*.{ts,html}\"",
"style.fix": "npm run style -- --write", "prettier:fix": "npm run prettier -- --write",
"cspell": "cspell \"{src,demo,docs,scripts}/**/*.{ts,scss,html,md}\" && cspell \"./*.*\"", "cspell": "cspell \"{src,demo,docs,scripts}/**/*.{ts,scss,html,md}\" && cspell \"./*.*\"",
"serve.docs": "cd docs && docsify serve", "serve.docs": "cd docs && docsify serve",
"extract": "ts-node scripts/extract-document.ts", "extract": "tsx scripts/extract-document.ts",
"ts-node": "ts-node --project demo/tsconfig.json" "run-ts": "tsx"
}, },
"pre-commit": [ "pre-commit": [
"style", "prettier",
"lint" "lint"
], ],
"repository": { "repository": {
@ -58,9 +55,8 @@
], ],
"dependencies": { "dependencies": {
"@types/node": "^20.3.1", "@types/node": "^20.3.1",
"fflate": "^0.8.0",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"nanoid": "^4.0.2", "nanoid": "^5.0.4",
"xml": "^1.0.1", "xml": "^1.0.1",
"xml-js": "^1.6.8" "xml-js": "^1.6.8"
}, },
@ -71,40 +67,39 @@
}, },
"homepage": "https://docx.js.org", "homepage": "https://docx.js.org",
"devDependencies": { "devDependencies": {
"@esbuild/win32-x64": "^0.18.3",
"@types/inquirer": "^9.0.3", "@types/inquirer": "^9.0.3",
"@types/prompt": "^1.1.1", "@types/prompt": "^1.1.1",
"@types/unzipper": "^0.10.4", "@types/unzipper": "^0.10.4",
"@types/xml": "^1.0.8", "@types/xml": "^1.0.8",
"@typescript-eslint/eslint-plugin": "^5.36.1", "@typescript-eslint/eslint-plugin": "^6.9.1",
"@typescript-eslint/parser": "^5.36.1", "@typescript-eslint/parser": "^6.9.1",
"@vitest/coverage-v8": "^0.32.0", "@vitest/coverage-v8": "^1.1.0",
"@vitest/ui": "^0.32.0", "@vitest/ui": "^1.1.0",
"cspell": "^6.2.2", "cspell": "^8.2.3",
"docsify-cli": "^4.3.0", "docsify-cli": "^4.3.0",
"eslint": "^8.23.0", "eslint": "^8.23.0",
"eslint-plugin-functional": "^5.0.8", "eslint-plugin-functional": "^6.0.0",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsdoc": "^46.2.6", "eslint-plugin-jsdoc": "^46.2.6",
"eslint-plugin-no-null": "^1.0.2", "eslint-plugin-no-null": "^1.0.2",
"eslint-plugin-prefer-arrow": "^1.2.3", "eslint-plugin-prefer-arrow": "^1.2.3",
"eslint-plugin-unicorn": "^47.0.0", "eslint-plugin-unicorn": "^50.0.1",
"execa": "^7.1.1", "execa": "^8.0.1",
"glob": "^10.2.7", "glob": "^10.2.7",
"inquirer": "^9.2.7", "inquirer": "^9.2.7",
"jsdom": "^22.1.0", "jsdom": "^23.0.1",
"pre-commit": "^1.2.2", "pre-commit": "^1.2.2",
"prettier": "^2.3.1", "prettier": "^3.1.1",
"ts-node": "^10.2.1",
"tsconfig-paths": "^4.0.0", "tsconfig-paths": "^4.0.0",
"typedoc": "^0.24.8", "tsx": "^4.7.0",
"typescript": "5.1.3", "typedoc": "^0.25.4",
"typescript": "5.3.3",
"unzipper": "^0.10.11", "unzipper": "^0.10.11",
"vite": "^4.3.2", "vite": "^5.0.10",
"vite-plugin-dts": "^2.3.0", "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.32.0" "vitest": "^1.1.0"
}, },
"engines": { "engines": {
"node": ">=10" "node": ">=10"

View File

@ -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);
});
}); });
}); });

View File

@ -2,6 +2,7 @@ import JSZip from "jszip";
import xml from "xml"; import xml from "xml";
import { File } from "@file/file"; import { File } from "@file/file";
import { obfuscate } from "@file/fonts/obfuscate-ttf-to-odttf";
import { Formatter } from "../formatter"; import { Formatter } from "../formatter";
import { ImageReplacer } from "./image-replacer"; import { ImageReplacer } from "./image-replacer";
@ -31,6 +32,8 @@ interface IXmlifyedFileMapping {
readonly FootNotesRelationships: IXmlifyedFile; readonly FootNotesRelationships: IXmlifyedFile;
readonly Settings: IXmlifyedFile; readonly Settings: IXmlifyedFile;
readonly Comments?: IXmlifyedFile; readonly Comments?: IXmlifyedFile;
readonly FontTable?: IXmlifyedFile;
readonly FontTableRelationships?: IXmlifyedFile;
} }
export class Compiler { export class Compiler {
@ -44,7 +47,7 @@ export class Compiler {
this.numberingReplacer = new NumberingReplacer(); this.numberingReplacer = new NumberingReplacer();
} }
public compile(file: File, prettifyXml?: PrettifyType): JSZip { public compile(file: File, prettifyXml?: (typeof PrettifyType)[keyof typeof PrettifyType]): JSZip {
const zip = new JSZip(); const zip = new JSZip();
const xmlifiedFileMapping = this.xmlifyFile(file, prettifyXml); const xmlifiedFileMapping = this.xmlifyFile(file, prettifyXml);
const map = new Map<string, IXmlifyedFile | readonly IXmlifyedFile[]>(Object.entries(xmlifiedFileMapping)); const map = new Map<string, IXmlifyedFile | readonly IXmlifyedFile[]>(Object.entries(xmlifiedFileMapping));
@ -63,10 +66,15 @@ 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;
} }
private xmlifyFile(file: File, prettify?: PrettifyType): IXmlifyedFileMapping { private xmlifyFile(file: File, prettify?: (typeof PrettifyType)[keyof typeof PrettifyType]): IXmlifyedFileMapping {
const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1; const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
const documentXmlData = xml( const documentXmlData = xml(
@ -439,6 +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",
},
}; };
} }
} }

View File

@ -6,18 +6,21 @@ import { Compiler } from "./next-compiler";
/** /**
* Use blanks to prettify * Use blanks to prettify
*/ */
export enum PrettifyType { export const PrettifyType = {
NONE = "", NONE: "",
WITH_2_BLANKS = " ", WITH_2_BLANKS: " ",
WITH_4_BLANKS = " ", WITH_4_BLANKS: " ",
WITH_TAB = "\t", // eslint-disable-next-line @typescript-eslint/naming-convention
} WITH_TAB: "\t",
} as const;
const convertPrettifyType = (prettify?: boolean | PrettifyType): PrettifyType | undefined => const convertPrettifyType = (
prettify?: boolean | (typeof PrettifyType)[keyof typeof PrettifyType],
): (typeof PrettifyType)[keyof typeof PrettifyType] | undefined =>
prettify === true ? PrettifyType.WITH_2_BLANKS : prettify === false ? undefined : prettify; prettify === true ? PrettifyType.WITH_2_BLANKS : prettify === false ? undefined : prettify;
export class Packer { export class Packer {
public static async toString(file: File, prettify?: boolean | PrettifyType): Promise<string> { public static async toString(file: File, prettify?: boolean | (typeof PrettifyType)[keyof typeof PrettifyType]): Promise<string> {
const zip = this.compiler.compile(file, convertPrettifyType(prettify)); const zip = this.compiler.compile(file, convertPrettifyType(prettify));
const zipData = await zip.generateAsync({ const zipData = await zip.generateAsync({
type: "string", type: "string",
@ -28,7 +31,7 @@ export class Packer {
return zipData; return zipData;
} }
public static async toBuffer(file: File, prettify?: boolean | PrettifyType): Promise<Buffer> { public static async toBuffer(file: File, prettify?: boolean | (typeof PrettifyType)[keyof typeof PrettifyType]): Promise<Buffer> {
const zip = this.compiler.compile(file, convertPrettifyType(prettify)); const zip = this.compiler.compile(file, convertPrettifyType(prettify));
const zipData = await zip.generateAsync({ const zipData = await zip.generateAsync({
type: "nodebuffer", type: "nodebuffer",
@ -39,7 +42,7 @@ export class Packer {
return zipData; return zipData;
} }
public static async toBase64String(file: File, prettify?: boolean | PrettifyType): Promise<string> { public static async toBase64String(file: File, prettify?: boolean | (typeof PrettifyType)[keyof typeof PrettifyType]): Promise<string> {
const zip = this.compiler.compile(file, convertPrettifyType(prettify)); const zip = this.compiler.compile(file, convertPrettifyType(prettify));
const zipData = await zip.generateAsync({ const zipData = await zip.generateAsync({
type: "base64", type: "base64",
@ -50,7 +53,7 @@ export class Packer {
return zipData; return zipData;
} }
public static async toBlob(file: File, prettify?: boolean | PrettifyType): Promise<Blob> { public static async toBlob(file: File, prettify?: boolean | (typeof PrettifyType)[keyof typeof PrettifyType]): Promise<Blob> {
const zip = this.compiler.compile(file, convertPrettifyType(prettify)); const zip = this.compiler.compile(file, convertPrettifyType(prettify));
const zipData = await zip.generateAsync({ const zipData = await zip.generateAsync({
type: "blob", type: "blob",
@ -61,7 +64,7 @@ export class Packer {
return zipData; return zipData;
} }
public static toStream(file: File, prettify?: boolean | PrettifyType): Stream { public static toStream(file: File, prettify?: boolean | (typeof PrettifyType)[keyof typeof PrettifyType]): Stream {
const stream = new Stream(); const stream = new Stream();
const zip = this.compiler.compile(file, convertPrettifyType(prettify)); const zip = this.compiler.compile(file, convertPrettifyType(prettify));

View File

@ -23,7 +23,7 @@ import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
import { eighthPointMeasureValue, hexColorValue, pointMeasureValue } from "@util/values"; import { eighthPointMeasureValue, hexColorValue, pointMeasureValue } from "@util/values";
export interface IBorderOptions { export interface IBorderOptions {
readonly style: BorderStyle; readonly style: (typeof BorderStyle)[keyof typeof BorderStyle];
/** Border color, in hex (eg 'FF00AA') */ /** Border color, in hex (eg 'FF00AA') */
readonly color?: string; readonly color?: string;
/** Size of the border in 1/8 pt */ /** Size of the border in 1/8 pt */
@ -55,32 +55,34 @@ class BordersAttributes extends XmlAttributeComponent<IBorderOptions> {
}; };
} }
export enum BorderStyle { /* eslint-disable @typescript-eslint/naming-convention */
SINGLE = "single", export const BorderStyle = {
DASH_DOT_STROKED = "dashDotStroked", SINGLE: "single",
DASHED = "dashed", DASH_DOT_STROKED: "dashDotStroked",
DASH_SMALL_GAP = "dashSmallGap", DASHED: "dashed",
DOT_DASH = "dotDash", DASH_SMALL_GAP: "dashSmallGap",
DOT_DOT_DASH = "dotDotDash", DOT_DASH: "dotDash",
DOTTED = "dotted", DOT_DOT_DASH: "dotDotDash",
DOUBLE = "double", DOTTED: "dotted",
DOUBLE_WAVE = "doubleWave", DOUBLE: "double",
INSET = "inset", DOUBLE_WAVE: "doubleWave",
NIL = "nil", INSET: "inset",
NONE = "none", NIL: "nil",
OUTSET = "outset", NONE: "none",
THICK = "thick", OUTSET: "outset",
THICK_THIN_LARGE_GAP = "thickThinLargeGap", THICK: "thick",
THICK_THIN_MEDIUM_GAP = "thickThinMediumGap", THICK_THIN_LARGE_GAP: "thickThinLargeGap",
THICK_THIN_SMALL_GAP = "thickThinSmallGap", THICK_THIN_MEDIUM_GAP: "thickThinMediumGap",
THIN_THICK_LARGE_GAP = "thinThickLargeGap", THICK_THIN_SMALL_GAP: "thickThinSmallGap",
THIN_THICK_MEDIUM_GAP = "thinThickMediumGap", THIN_THICK_LARGE_GAP: "thinThickLargeGap",
THIN_THICK_SMALL_GAP = "thinThickSmallGap", THIN_THICK_MEDIUM_GAP: "thinThickMediumGap",
THIN_THICK_THIN_LARGE_GAP = "thinThickThinLargeGap", THIN_THICK_SMALL_GAP: "thinThickSmallGap",
THIN_THICK_THIN_MEDIUM_GAP = "thinThickThinMediumGap", THIN_THICK_THIN_LARGE_GAP: "thinThickThinLargeGap",
THIN_THICK_THIN_SMALL_GAP = "thinThickThinSmallGap", THIN_THICK_THIN_MEDIUM_GAP: "thinThickThinMediumGap",
THREE_D_EMBOSS = "threeDEmboss", THIN_THICK_THIN_SMALL_GAP: "thinThickThinSmallGap",
THREE_D_ENGRAVE = "threeDEngrave", THREE_D_EMBOSS: "threeDEmboss",
TRIPLE = "triple", THREE_D_ENGRAVE: "threeDEngrave",
WAVE = "wave", TRIPLE: "triple",
} WAVE: "wave",
} as const;
/* eslint-enable */

View File

@ -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",

View File

@ -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 {

View File

@ -1,5 +1,6 @@
import { ICommentsOptions } from "@file/paragraph/run/comment-run"; import { ICommentsOptions } from "@file/paragraph/run/comment-run";
import { ICompatibilityOptions } from "@file/settings/compatibility"; import { ICompatibilityOptions } from "@file/settings/compatibility";
import { FontOptions } from "@file/fonts/font-table";
import { StringContainer, XmlComponent } from "@file/xml-components"; import { StringContainer, XmlComponent } from "@file/xml-components";
import { dateTimeValue } from "@util/values"; import { dateTimeValue } from "@util/values";
@ -39,6 +40,8 @@ export interface IPropertiesOptions {
readonly compatibility?: ICompatibilityOptions; readonly compatibility?: ICompatibilityOptions;
readonly customProperties?: readonly ICustomPropertyOptions[]; readonly customProperties?: readonly ICustomPropertyOptions[];
readonly evenAndOddHeaderAndFooters?: boolean; readonly evenAndOddHeaderAndFooters?: boolean;
readonly defaultTabStop?: number;
readonly fonts?: readonly FontOptions[];
} }
// <xs:element name="coreProperties" type="CT_CoreProperties"/> // <xs:element name="coreProperties" type="CT_CoreProperties"/>

View File

@ -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;
} }

View File

@ -17,14 +17,17 @@ import { decimalNumber } from "@util/values";
// <xsd:attribute name="charSpace" type="ST_DecimalNumber"/> // <xsd:attribute name="charSpace" type="ST_DecimalNumber"/>
// </xsd:complexType> // </xsd:complexType>
export enum DocumentGridType { /* eslint-disable @typescript-eslint/naming-convention */
DEFAULT = "default", export const DocumentGridType = {
LINES = "lines", DEFAULT: "default",
LINES_AND_CHARS = "linesAndChars", LINES: "lines",
SNAP_TO_CHARS = "snapToChars", LINES_AND_CHARS: "linesAndChars",
} SNAP_TO_CHARS: "snapToChars",
} as const;
/* eslint-enable */
export interface IDocGridAttributesProperties { export interface IDocGridAttributesProperties {
readonly type?: DocumentGridType; readonly type?: (typeof DocumentGridType)[keyof typeof DocumentGridType];
readonly linePitch?: number; readonly linePitch?: number;
readonly charSpace?: number; readonly charSpace?: number;
} }
@ -38,7 +41,7 @@ export class DocGridAttributes extends XmlAttributeComponent<IDocGridAttributesP
} }
export class DocumentGrid extends XmlComponent { export class DocumentGrid extends XmlComponent {
public constructor(linePitch: number, charSpace?: number, type?: DocumentGridType) { public constructor(linePitch: number, charSpace?: number, type?: (typeof DocumentGridType)[keyof typeof DocumentGridType]) {
super("w:docGrid"); super("w:docGrid");
this.root.push( this.root.push(

View File

@ -7,11 +7,11 @@ import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
// <xsd:enumeration value="first"/> // <xsd:enumeration value="first"/>
// </xsd:restriction> // </xsd:restriction>
// </xsd:simpleType> // </xsd:simpleType>
export enum HeaderFooterReferenceType { export const HeaderFooterReferenceType = {
DEFAULT = "default", DEFAULT: "default",
FIRST = "first", FIRST: "first",
EVEN = "even", EVEN: "even",
} } as const;
// </xsd:complexType> // </xsd:complexType>
// <xsd:group name="EG_HdrFtrReferences"> // <xsd:group name="EG_HdrFtrReferences">
@ -33,12 +33,12 @@ export enum HeaderFooterReferenceType {
// </xsd:complexType> // </xsd:complexType>
export interface IHeaderFooterOptions { export interface IHeaderFooterOptions {
readonly type?: HeaderFooterReferenceType; readonly type?: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType];
readonly id?: number; readonly id?: number;
} }
class FooterReferenceAttributes extends XmlAttributeComponent<{ class FooterReferenceAttributes extends XmlAttributeComponent<{
readonly type: HeaderFooterReferenceType; readonly type: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType];
readonly id: string; readonly id: string;
}> { }> {
protected readonly xmlKeys = { protected readonly xmlKeys = {
@ -47,12 +47,13 @@ class FooterReferenceAttributes extends XmlAttributeComponent<{
}; };
} }
export enum HeaderFooterType { export const HeaderFooterType = {
HEADER = "w:headerReference", HEADER: "w:headerReference",
FOOTER = "w:footerReference", FOOTER: "w:footerReference",
} } as const;
export class HeaderFooterReference extends XmlComponent { export class HeaderFooterReference extends XmlComponent {
public constructor(type: HeaderFooterType, options: IHeaderFooterOptions) { public constructor(type: (typeof HeaderFooterType)[keyof typeof HeaderFooterType], options: IHeaderFooterOptions) {
super(type); super(type);
this.root.push( this.root.push(

View File

@ -1,5 +1,5 @@
// http://officeopenxml.com/WPsectionLineNumbering.php // http://officeopenxml.com/WPsectionLineNumbering.php
import { NextAttributeComponent, XmlComponent } from "@file/xml-components"; import { BuilderElement, XmlComponent } from "@file/xml-components";
import { decimalNumber, PositiveUniversalMeasure, twipsMeasureValue } from "@util/values"; import { decimalNumber, PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
// <xsd:simpleType name="ST_LineNumberRestart"> // <xsd:simpleType name="ST_LineNumberRestart">
@ -9,11 +9,14 @@ import { decimalNumber, PositiveUniversalMeasure, twipsMeasureValue } from "@uti
// <xsd:enumeration value="continuous"/> // <xsd:enumeration value="continuous"/>
// </xsd:restriction> // </xsd:restriction>
// </xsd:simpleType> // </xsd:simpleType>
export enum LineNumberRestartFormat {
NEW_PAGE = "newPage", /* eslint-disable @typescript-eslint/naming-convention */
NEW_SECTION = "newSection", export const LineNumberRestartFormat = {
CONTINUOUS = "continuous", NEW_PAGE: "newPage",
} NEW_SECTION: "newSection",
CONTINUOUS: "continuous",
} as const;
/* eslint-enable */
// <xsd:complexType name="CT_LineNumber"> // <xsd:complexType name="CT_LineNumber">
// <xsd:attribute name="countBy" type="ST_DecimalNumber" use="optional"/> // <xsd:attribute name="countBy" type="ST_DecimalNumber" use="optional"/>
@ -22,28 +25,23 @@ export enum LineNumberRestartFormat {
// <xsd:attribute name="restart" type="ST_LineNumberRestart" use="optional" default="newPage"/> // <xsd:attribute name="restart" type="ST_LineNumberRestart" use="optional" default="newPage"/>
// </xsd:complexType> // </xsd:complexType>
export interface ILineNumberAttributes { export type ILineNumberAttributes = {
readonly countBy?: number; readonly countBy?: number;
readonly start?: number; readonly start?: number;
readonly restart?: LineNumberRestartFormat; readonly restart?: (typeof LineNumberRestartFormat)[keyof typeof LineNumberRestartFormat];
readonly distance?: number | PositiveUniversalMeasure; readonly distance?: number | PositiveUniversalMeasure;
} };
export class LineNumberType extends XmlComponent { export const createLineNumberType = ({ countBy, start, restart, distance }: ILineNumberAttributes): XmlComponent =>
public constructor({ countBy, start, restart, distance }: ILineNumberAttributes) { new BuilderElement<ILineNumberAttributes>({
super("w:lnNumType"); name: "w:lnNumType",
this.root.push( attributes: {
new NextAttributeComponent<{ 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?: 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) },
}),
);
}
}

View File

@ -9,11 +9,14 @@ import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent } from "@file/xml-comp
// <xsd:enumeration value="notFirstPage"/> // <xsd:enumeration value="notFirstPage"/>
// </xsd:restriction> // </xsd:restriction>
// </xsd:simpleType> // </xsd:simpleType>
export enum PageBorderDisplay {
ALL_PAGES = "allPages", /* eslint-disable @typescript-eslint/naming-convention */
FIRST_PAGE = "firstPage", export const PageBorderDisplay = {
NOT_FIRST_PAGE = "notFirstPage", ALL_PAGES: "allPages",
} FIRST_PAGE: "firstPage",
NOT_FIRST_PAGE: "notFirstPage",
} as const;
/* eslint-enable */
// <xsd:simpleType name="ST_PageBorderOffset"> // <xsd:simpleType name="ST_PageBorderOffset">
// <xsd:restriction base="xsd:string"> // <xsd:restriction base="xsd:string">
@ -21,10 +24,10 @@ export enum PageBorderDisplay {
// <xsd:enumeration value="text"/> // <xsd:enumeration value="text"/>
// </xsd:restriction> // </xsd:restriction>
// </xsd:simpleType> // </xsd:simpleType>
export enum PageBorderOffsetFrom { export const PageBorderOffsetFrom = {
PAGE = "page", PAGE: "page",
TEXT = "text", TEXT: "text",
} } as const;
// <xsd:simpleType name="ST_PageBorderZOrder"> // <xsd:simpleType name="ST_PageBorderZOrder">
// <xsd:restriction base="xsd:string"> // <xsd:restriction base="xsd:string">
@ -32,15 +35,15 @@ export enum PageBorderOffsetFrom {
// <xsd:enumeration value="back"/> // <xsd:enumeration value="back"/>
// </xsd:restriction> // </xsd:restriction>
// </xsd:simpleType> // </xsd:simpleType>
export enum PageBorderZOrder { export const PageBorderZOrder = {
BACK = "back", BACK: "back",
FRONT = "front", FRONT: "front",
} } as const;
export interface IPageBorderAttributes { export interface IPageBorderAttributes {
readonly display?: PageBorderDisplay; readonly display?: (typeof PageBorderDisplay)[keyof typeof PageBorderDisplay];
readonly offsetFrom?: PageBorderOffsetFrom; readonly offsetFrom?: (typeof PageBorderOffsetFrom)[keyof typeof PageBorderOffsetFrom];
readonly zOrder?: PageBorderZOrder; readonly zOrder?: (typeof PageBorderZOrder)[keyof typeof PageBorderZOrder];
} }
export interface IPageBordersOptions { export interface IPageBordersOptions {

View File

@ -12,18 +12,22 @@ import { decimalNumber } from "@util/values";
// <xsd:enumeration value="enDash"/> // <xsd:enumeration value="enDash"/>
// </xsd:restriction> // </xsd:restriction>
// </xsd:simpleType> // </xsd:simpleType>
export enum PageNumberSeparator {
HYPHEN = "hyphen", /* eslint-disable @typescript-eslint/naming-convention */
PERIOD = "period", export const PageNumberSeparator = {
COLON = "colon", HYPHEN: "hyphen",
EM_DASH = "emDash", PERIOD: "period",
EN_DASH = "endash", COLON: "colon",
} EM_DASH: "emDash",
EN_DASH: "endash",
} as const;
/* eslint-enable */
export interface IPageNumberTypeAttributes { export interface IPageNumberTypeAttributes {
readonly start?: number; readonly start?: number;
readonly formatType?: NumberFormat; readonly formatType?: (typeof NumberFormat)[keyof typeof NumberFormat];
readonly separator?: PageNumberSeparator; readonly separator?: (typeof PageNumberSeparator)[keyof typeof PageNumberSeparator];
} }
// <xsd:complexType name="CT_PageNumber"> // <xsd:complexType name="CT_PageNumber">
@ -40,6 +44,7 @@ export class PageNumberTypeAttributes extends XmlAttributeComponent<IPageNumberT
separator: "w:chapSep", separator: "w:chapSep",
}; };
} }
export class PageNumberType extends XmlComponent { export class PageNumberType extends XmlComponent {
public constructor({ start, formatType, separator }: IPageNumberTypeAttributes) { public constructor({ start, formatType, separator }: IPageNumberTypeAttributes) {
super("w:pgNumType"); super("w:pgNumType");

View File

@ -7,10 +7,10 @@ import { PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
// <xsd:enumeration value="landscape"/> // <xsd:enumeration value="landscape"/>
// </xsd:restriction> // </xsd:restriction>
// </xsd:simpleType> // </xsd:simpleType>
export enum PageOrientation { export const PageOrientation = {
PORTRAIT = "portrait", PORTRAIT: "portrait",
LANDSCAPE = "landscape", LANDSCAPE: "landscape",
} } as const;
// <xsd:complexType name="CT_PageSz"> // <xsd:complexType name="CT_PageSz">
// <xsd:attribute name="w" type="s:ST_TwipsMeasure"/> // <xsd:attribute name="w" type="s:ST_TwipsMeasure"/>
@ -21,11 +21,15 @@ export enum PageOrientation {
export type IPageSizeAttributes = { export type IPageSizeAttributes = {
readonly width?: number | PositiveUniversalMeasure; readonly width?: number | PositiveUniversalMeasure;
readonly height?: number | PositiveUniversalMeasure; readonly height?: number | PositiveUniversalMeasure;
readonly orientation?: PageOrientation; readonly orientation?: (typeof PageOrientation)[keyof typeof PageOrientation];
}; };
export class PageSize extends XmlComponent { export class PageSize extends XmlComponent {
public constructor(width: number | PositiveUniversalMeasure, height: number | PositiveUniversalMeasure, orientation: PageOrientation) { public constructor(
width: number | PositiveUniversalMeasure,
height: number | PositiveUniversalMeasure,
orientation: (typeof PageOrientation)[keyof typeof PageOrientation],
) {
super("w:pgSz"); super("w:pgSz");
const flip = orientation === PageOrientation.LANDSCAPE; const flip = orientation === PageOrientation.LANDSCAPE;

View File

@ -1,16 +1,21 @@
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
export enum PageTextDirectionType { /* eslint-disable @typescript-eslint/naming-convention */
LEFT_TO_RIGHT_TOP_TO_BOTTOM = "lrTb", export const PageTextDirectionType = {
TOP_TO_BOTTOM_RIGHT_TO_LEFT = "tbRl", LEFT_TO_RIGHT_TOP_TO_BOTTOM: "lrTb",
} TOP_TO_BOTTOM_RIGHT_TO_LEFT: "tbRl",
} as const;
class PageTextDirectionAttributes extends XmlAttributeComponent<{ readonly val: PageTextDirectionType }> { /* eslint-enable */
class PageTextDirectionAttributes extends XmlAttributeComponent<{
readonly val: (typeof PageTextDirectionType)[keyof typeof PageTextDirectionType];
}> {
protected readonly xmlKeys = { val: "w:val" }; protected readonly xmlKeys = { val: "w:val" };
} }
export class PageTextDirection extends XmlComponent { export class PageTextDirection extends XmlComponent {
public constructor(value: PageTextDirectionType) { public constructor(value: (typeof PageTextDirectionType)[keyof typeof PageTextDirectionType]) {
super("w:textDirection"); super("w:textDirection");
this.root.push( this.root.push(

View File

@ -10,19 +10,22 @@ import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
// <xsd:enumeration value="oddPage"/> // <xsd:enumeration value="oddPage"/>
// </xsd:restriction> // </xsd:restriction>
// </xsd:simpleType> // </xsd:simpleType>
export enum SectionType {
NEXT_PAGE = "nextPage", /* eslint-disable @typescript-eslint/naming-convention */
NEXT_COLUMN = "nextColumn", export const SectionType = {
CONTINUOUS = "continuous", NEXT_PAGE: "nextPage",
EVEN_PAGE = "evenPage", NEXT_COLUMN: "nextColumn",
ODD_PAGE = "oddPage", CONTINUOUS: "continuous",
} EVEN_PAGE: "evenPage",
ODD_PAGE: "oddPage",
} as const;
/* eslint-enable */
// <xsd:complexType name="CT_SectType"> // <xsd:complexType name="CT_SectType">
// <xsd:attribute name="val" type="ST_SectionMark"/> // <xsd:attribute name="val" type="ST_SectionMark"/>
// </xsd:complexType> // </xsd:complexType>
export class SectionTypeAttributes extends XmlAttributeComponent<{ export class SectionTypeAttributes extends XmlAttributeComponent<{
readonly val: SectionType; readonly val: (typeof SectionType)[keyof typeof SectionType];
}> { }> {
protected readonly xmlKeys = { protected readonly xmlKeys = {
val: "w:val", val: "w:val",
@ -30,7 +33,7 @@ export class SectionTypeAttributes extends XmlAttributeComponent<{
} }
export class Type extends XmlComponent { export class Type extends XmlComponent {
public constructor(value: SectionType) { public constructor(value: (typeof SectionType)[keyof typeof SectionType]) {
super("w:type"); super("w:type");
this.root.push(new SectionTypeAttributes({ val: value })); this.root.push(new SectionTypeAttributes({ val: value }));
} }

View File

@ -5,12 +5,11 @@ import { FooterWrapper } from "@file/footer-wrapper";
import { HeaderWrapper } from "@file/header-wrapper"; import { HeaderWrapper } from "@file/header-wrapper";
import { VerticalAlign, VerticalAlignElement } from "@file/vertical-align"; import { VerticalAlign, VerticalAlignElement } from "@file/vertical-align";
import { OnOffElement, XmlComponent } from "@file/xml-components"; import { OnOffElement, XmlComponent } from "@file/xml-components";
import { PositiveUniversalMeasure, UniversalMeasure } from "@util/values";
import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./properties/header-footer-reference"; import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./properties/header-footer-reference";
import { Columns, IColumnsAttributes } from "./properties/columns"; import { Columns, IColumnsAttributes } from "./properties/columns";
import { DocumentGrid, IDocGridAttributesProperties } from "./properties/doc-grid"; import { DocumentGrid, IDocGridAttributesProperties } from "./properties/doc-grid";
import { ILineNumberAttributes, LineNumberType } from "./properties/line-number"; import { ILineNumberAttributes, createLineNumberType } from "./properties/line-number";
import { IPageBordersOptions, PageBorders } from "./properties/page-borders"; import { IPageBordersOptions, PageBorders } from "./properties/page-borders";
import { IPageMarginAttributes, PageMargin } from "./properties/page-margin"; import { IPageMarginAttributes, PageMargin } from "./properties/page-margin";
import { IPageNumberTypeAttributes, PageNumberType } from "./properties/page-number"; import { IPageNumberTypeAttributes, PageNumberType } from "./properties/page-number";
@ -30,16 +29,16 @@ export interface ISectionPropertiesOptions {
readonly margin?: IPageMarginAttributes; readonly margin?: IPageMarginAttributes;
readonly pageNumbers?: IPageNumberTypeAttributes; readonly pageNumbers?: IPageNumberTypeAttributes;
readonly borders?: IPageBordersOptions; readonly borders?: IPageBordersOptions;
readonly textDirection?: PageTextDirectionType; readonly textDirection?: (typeof PageTextDirectionType)[keyof typeof PageTextDirectionType];
}; };
readonly grid?: IDocGridAttributesProperties; readonly grid?: IDocGridAttributesProperties;
readonly headerWrapperGroup?: IHeaderFooterGroup<HeaderWrapper>; readonly headerWrapperGroup?: IHeaderFooterGroup<HeaderWrapper>;
readonly footerWrapperGroup?: IHeaderFooterGroup<FooterWrapper>; readonly footerWrapperGroup?: IHeaderFooterGroup<FooterWrapper>;
readonly lineNumbers?: ILineNumberAttributes; readonly lineNumbers?: ILineNumberAttributes;
readonly titlePage?: boolean; readonly titlePage?: boolean;
readonly verticalAlign?: VerticalAlign; readonly verticalAlign?: (typeof VerticalAlign)[keyof typeof VerticalAlign];
readonly column?: IColumnsAttributes; readonly column?: IColumnsAttributes;
readonly type?: SectionType; readonly type?: (typeof SectionType)[keyof typeof SectionType];
} }
// <xsd:complexType name="CT_SectPr"> // <xsd:complexType name="CT_SectPr">
@ -76,10 +75,10 @@ export interface ISectionPropertiesOptions {
// </xsd:group> // </xsd:group>
export const sectionMarginDefaults = { export const sectionMarginDefaults = {
TOP: "1in" as UniversalMeasure, TOP: 1440,
RIGHT: "1in" as PositiveUniversalMeasure, RIGHT: 1440,
BOTTOM: "1in" as UniversalMeasure, BOTTOM: 1440,
LEFT: "1in" as PositiveUniversalMeasure, LEFT: 1440,
HEADER: 708, HEADER: 708,
FOOTER: 708, FOOTER: 708,
GUTTER: 0, GUTTER: 0,
@ -138,7 +137,7 @@ export class SectionProperties extends XmlComponent {
} }
if (lineNumbers) { if (lineNumbers) {
this.root.push(new LineNumberType(lineNumbers)); this.root.push(createLineNumberType(lineNumbers));
} }
this.root.push(new PageNumberType(pageNumbers)); this.root.push(new PageNumberType(pageNumbers));
@ -163,7 +162,7 @@ export class SectionProperties extends XmlComponent {
} }
private addHeaderFooterGroup( private addHeaderFooterGroup(
type: HeaderFooterType, type: (typeof HeaderFooterType)[keyof typeof HeaderFooterType],
group: IHeaderFooterGroup<HeaderWrapper> | IHeaderFooterGroup<FooterWrapper>, group: IHeaderFooterGroup<HeaderWrapper> | IHeaderFooterGroup<FooterWrapper>,
): void { ): void {
if (group.default) { if (group.default) {

View File

@ -80,6 +80,7 @@ export class Document extends XmlComponent {
} }
public add(item: Paragraph | Table | TableOfContents | ConcreteHyperlink): Document { public add(item: Paragraph | Table | TableOfContents | ConcreteHyperlink): Document {
// eslint-disable-next-line functional/immutable-data
this.body.push(item); this.body.push(item);
return this; return this;
} }

View File

@ -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;

View File

@ -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 }));
} }
} }

View File

@ -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 }));
} }
} }
} }

View File

@ -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",
};
}

View File

@ -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,
},
},
});

View File

@ -3,7 +3,11 @@ import { HorizontalPositionAlign, VerticalPositionAlign } from "@file/shared/ali
import { XmlComponent } from "@file/xml-components"; import { XmlComponent } from "@file/xml-components";
export class Align extends XmlComponent { export class Align extends XmlComponent {
public constructor(value: HorizontalPositionAlign | VerticalPositionAlign) { public constructor(
value:
| (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign]
| (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign],
) {
super("wp:align"); super("wp:align");
this.root.push(value); this.root.push(value);
} }

View File

@ -4,37 +4,39 @@ import { HorizontalPositionAlign, VerticalPositionAlign } from "@file/shared/ali
import { ITextWrapping } from "../text-wrap"; import { ITextWrapping } from "../text-wrap";
export enum HorizontalPositionRelativeFrom { /* eslint-disable @typescript-eslint/naming-convention */
CHARACTER = "character", export const HorizontalPositionRelativeFrom = {
COLUMN = "column", CHARACTER: "character",
INSIDE_MARGIN = "insideMargin", COLUMN: "column",
LEFT_MARGIN = "leftMargin", INSIDE_MARGIN: "insideMargin",
MARGIN = "margin", LEFT_MARGIN: "leftMargin",
OUTSIDE_MARGIN = "outsideMargin", MARGIN: "margin",
PAGE = "page", OUTSIDE_MARGIN: "outsideMargin",
RIGHT_MARGIN = "rightMargin", PAGE: "page",
} RIGHT_MARGIN: "rightMargin",
} as const;
export enum VerticalPositionRelativeFrom { export const VerticalPositionRelativeFrom = {
BOTTOM_MARGIN = "bottomMargin", BOTTOM_MARGIN: "bottomMargin",
INSIDE_MARGIN = "insideMargin", INSIDE_MARGIN: "insideMargin",
LINE = "line", LINE: "line",
MARGIN = "margin", MARGIN: "margin",
OUTSIDE_MARGIN = "outsideMargin", OUTSIDE_MARGIN: "outsideMargin",
PAGE = "page", PAGE: "page",
PARAGRAPH = "paragraph", PARAGRAPH: "paragraph",
TOP_MARGIN = "topMargin", TOP_MARGIN: "topMargin",
} } as const;
/* eslint-enable */
export interface IHorizontalPositionOptions { export interface IHorizontalPositionOptions {
readonly relative?: HorizontalPositionRelativeFrom; readonly relative?: (typeof HorizontalPositionRelativeFrom)[keyof typeof HorizontalPositionRelativeFrom];
readonly align?: HorizontalPositionAlign; readonly align?: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign];
readonly offset?: number; readonly offset?: number;
} }
export interface IVerticalPositionOptions { export interface IVerticalPositionOptions {
readonly relative?: VerticalPositionRelativeFrom; readonly relative?: (typeof VerticalPositionRelativeFrom)[keyof typeof VerticalPositionRelativeFrom];
readonly align?: VerticalPositionAlign; readonly align?: (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign];
readonly offset?: number; readonly offset?: number;
} }

View File

@ -5,7 +5,7 @@ import { HorizontalPositionRelativeFrom, IHorizontalPositionOptions } from "./fl
import { PositionOffset } from "./position-offset"; import { PositionOffset } from "./position-offset";
class HorizontalPositionAttributes extends XmlAttributeComponent<{ class HorizontalPositionAttributes extends XmlAttributeComponent<{
readonly relativeFrom: HorizontalPositionRelativeFrom; readonly relativeFrom: (typeof HorizontalPositionRelativeFrom)[keyof typeof HorizontalPositionRelativeFrom];
}> { }> {
protected readonly xmlKeys = { protected readonly xmlKeys = {
relativeFrom: "relativeFrom", relativeFrom: "relativeFrom",

View File

@ -5,7 +5,7 @@ import { IVerticalPositionOptions, VerticalPositionRelativeFrom } from "./floati
import { PositionOffset } from "./position-offset"; import { PositionOffset } from "./position-offset";
class VerticalPositionAttributes extends XmlAttributeComponent<{ class VerticalPositionAttributes extends XmlAttributeComponent<{
readonly relativeFrom: VerticalPositionRelativeFrom; readonly relativeFrom: (typeof VerticalPositionRelativeFrom)[keyof typeof VerticalPositionRelativeFrom];
}> { }> {
protected readonly xmlKeys = { protected readonly xmlKeys = {
relativeFrom: "relativeFrom", relativeFrom: "relativeFrom",

View File

@ -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);
} }

View File

@ -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 }));
} }
} }

View File

@ -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": {},
}); });

View File

@ -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");
}
}

View File

@ -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",
},
},
},
],
},
],
}); });
}); });
}); });

View File

@ -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,
}),
],
});

View File

@ -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,
},
},
});

View File

@ -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,
},
},
});

View File

@ -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",
},
},
},
],
});
});
});

View File

@ -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)],
});

View File

@ -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));
}
} }
} }

View File

@ -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);
} }

View File

@ -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",
};
}

View 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,
},
},
},
]),
});
});
});

View File

@ -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 }),
],
});

View File

@ -1,22 +1,25 @@
// http://officeopenxml.com/drwPicFloating-textWrap.php // http://officeopenxml.com/drwPicFloating-textWrap.php
import { IDistance } from "../drawing"; import { IDistance } from "../drawing";
export enum TextWrappingType { /* eslint-disable @typescript-eslint/naming-convention */
NONE, export const TextWrappingType = {
SQUARE, NONE: 0,
TIGHT, SQUARE: 1,
TOP_AND_BOTTOM, TIGHT: 2,
} TOP_AND_BOTTOM: 3,
} as const;
export enum TextWrappingSide { export const TextWrappingSide = {
BOTH_SIDES = "bothSides", BOTH_SIDES: "bothSides",
LEFT = "left", LEFT: "left",
RIGHT = "right", RIGHT: "right",
LARGEST = "largest", LARGEST: "largest",
} } as const;
/* eslint-enable */
export interface ITextWrapping { export interface ITextWrapping {
readonly type: TextWrappingType; readonly type: (typeof TextWrappingType)[keyof typeof TextWrappingType];
readonly side?: TextWrappingSide; readonly side?: (typeof TextWrappingSide)[keyof typeof TextWrappingSide];
readonly margins?: IDistance; readonly margins?: IDistance;
} }

View File

@ -6,7 +6,7 @@ import { IMargins } from "../floating";
import { ITextWrapping, TextWrappingSide } from "./text-wrapping"; import { ITextWrapping, TextWrappingSide } from "./text-wrapping";
interface IWrapSquareAttributes extends IDistance { interface IWrapSquareAttributes extends IDistance {
readonly wrapText?: TextWrappingSide; readonly wrapText?: (typeof TextWrappingSide)[keyof typeof TextWrappingSide];
} }
class WrapSquareAttributes extends XmlAttributeComponent<IWrapSquareAttributes> { class WrapSquareAttributes extends XmlAttributeComponent<IWrapSquareAttributes> {

View File

@ -17,6 +17,7 @@ import { Styles } from "./styles";
import { ExternalStylesFactory } from "./styles/external-styles-factory"; import { ExternalStylesFactory } from "./styles/external-styles-factory";
import { DefaultStylesFactory } from "./styles/factory"; import { DefaultStylesFactory } from "./styles/factory";
import { FileChild } from "./file-child"; import { FileChild } from "./file-child";
import { FontWrapper } from "./fonts/font-wrapper";
export interface ISectionOptions { export interface ISectionOptions {
readonly headers?: { readonly headers?: {
@ -53,6 +54,7 @@ export class File {
private readonly appProperties: AppProperties; private readonly appProperties: AppProperties;
private readonly styles: Styles; private readonly styles: Styles;
private readonly comments: Comments; private readonly comments: Comments;
private readonly fontWrapper: FontWrapper;
public constructor(options: IPropertiesOptions) { public constructor(options: IPropertiesOptions) {
this.coreProperties = new CoreProperties({ this.coreProperties = new CoreProperties({
@ -77,6 +79,7 @@ export class File {
evenAndOddHeaders: options.evenAndOddHeaderAndFooters ? true : false, evenAndOddHeaders: options.evenAndOddHeaderAndFooters ? true : false,
trackRevisions: options.features?.trackRevisions, trackRevisions: options.features?.trackRevisions,
updateFields: options.features?.updateFields, updateFields: options.features?.updateFields,
defaultTabStop: options.defaultTabStop,
}); });
this.media = new Media(); this.media = new Media();
@ -108,6 +111,8 @@ export class File {
this.footnotesWrapper.View.createFootNote(parseFloat(key), options.footnotes[key].children); this.footnotesWrapper.View.createFootNote(parseFloat(key), options.footnotes[key].children);
} }
} }
this.fontWrapper = new FontWrapper(options.fonts ?? []);
} }
private addSection({ headers = {}, footers = {}, children, properties }: ISectionOptions): void { private addSection({ headers = {}, footers = {}, children, properties }: ISectionOptions): void {
@ -154,7 +159,10 @@ export class File {
return wrapper; return wrapper;
} }
private addHeaderToDocument(header: HeaderWrapper, type: HeaderFooterReferenceType = HeaderFooterReferenceType.DEFAULT): void { private addHeaderToDocument(
header: HeaderWrapper,
type: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType] = HeaderFooterReferenceType.DEFAULT,
): void {
// eslint-disable-next-line functional/immutable-data // eslint-disable-next-line functional/immutable-data
this.headers.push({ header, type }); this.headers.push({ header, type });
this.documentWrapper.Relationships.createRelationship( this.documentWrapper.Relationships.createRelationship(
@ -165,7 +173,10 @@ export class File {
this.contentTypes.addHeader(this.headers.length); this.contentTypes.addHeader(this.headers.length);
} }
private addFooterToDocument(footer: FooterWrapper, type: HeaderFooterReferenceType = HeaderFooterReferenceType.DEFAULT): void { private addFooterToDocument(
footer: FooterWrapper,
type: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType] = HeaderFooterReferenceType.DEFAULT,
): void {
// eslint-disable-next-line functional/immutable-data // eslint-disable-next-line functional/immutable-data
this.footers.push({ footer, type }); this.footers.push({ footer, type });
this.documentWrapper.Relationships.createRelationship( this.documentWrapper.Relationships.createRelationship(
@ -285,4 +296,8 @@ export class File {
public get Comments(): Comments { public get Comments(): Comments {
return this.comments; return this.comments;
} }
public get FontTable(): FontWrapper {
return this.fontWrapper;
}
} }

View 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}`,
},
});

View 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,
}),
),
});

View 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
View 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
View 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
View File

@ -0,0 +1 @@
export { CharacterSet } from "./font";

View 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;
};

View 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();
});
});

View File

@ -10,14 +10,18 @@ import { Table } from "./table";
export interface IDocumentFooter { export interface IDocumentFooter {
readonly footer: FooterWrapper; readonly footer: FooterWrapper;
readonly type: HeaderFooterReferenceType; readonly type: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType];
} }
export class FooterWrapper implements IViewWrapper { export class FooterWrapper implements IViewWrapper {
private readonly footer: Footer; private readonly footer: Footer;
private readonly relationships: Relationships; private readonly relationships: Relationships;
public constructor(private readonly media: Media, referenceId: number, initContent?: XmlComponent) { public constructor(
private readonly media: Media,
referenceId: number,
initContent?: XmlComponent,
) {
this.footer = new Footer(referenceId, initContent); this.footer = new Footer(referenceId, initContent);
this.relationships = new Relationships(); this.relationships = new Relationships();
} }

View File

@ -4,14 +4,15 @@ import { XmlComponent } from "@file/xml-components";
import { FootnoteAttributes } from "./footnote-attributes"; import { FootnoteAttributes } from "./footnote-attributes";
import { FootnoteRefRun } from "./run/footnote-ref-run"; import { FootnoteRefRun } from "./run/footnote-ref-run";
export enum FootnoteType { export const FootnoteType = {
SEPERATOR = "separator", SEPERATOR: "separator",
CONTINUATION_SEPERATOR = "continuationSeparator", // eslint-disable-next-line @typescript-eslint/naming-convention
} CONTINUATION_SEPERATOR: "continuationSeparator",
} as const;
export interface IFootnoteOptions { export interface IFootnoteOptions {
readonly id: number; readonly id: number;
readonly type?: FootnoteType; readonly type?: (typeof FootnoteType)[keyof typeof FootnoteType];
readonly children: readonly Paragraph[]; readonly children: readonly Paragraph[];
} }

View File

@ -10,14 +10,18 @@ import { Table } from "./table";
export interface IDocumentHeader { export interface IDocumentHeader {
readonly header: HeaderWrapper; readonly header: HeaderWrapper;
readonly type: HeaderFooterReferenceType; readonly type: (typeof HeaderFooterReferenceType)[keyof typeof HeaderFooterReferenceType];
} }
export class HeaderWrapper implements IViewWrapper { export class HeaderWrapper implements IViewWrapper {
private readonly header: Header; private readonly header: Header;
private readonly relationships: Relationships; private readonly relationships: Relationships;
public constructor(private readonly media: Media, referenceId: number, initContent?: XmlComponent) { public constructor(
private readonly media: Media,
referenceId: number,
initContent?: XmlComponent,
) {
this.header = new Header(referenceId, initContent); this.header = new Header(referenceId, initContent);
this.relationships = new Relationships(); this.relationships = new Relationships();
} }

View File

@ -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";

View File

@ -75,71 +75,75 @@ import { IRunStylePropertiesOptions, RunProperties } from "../paragraph/run/prop
// <xsd:enumeration value="custom"/> // <xsd:enumeration value="custom"/>
// </xsd:restriction> // </xsd:restriction>
// </xsd:simpleType> // </xsd:simpleType>
export enum LevelFormat {
DECIMAL = "decimal", /* eslint-disable @typescript-eslint/naming-convention */
UPPER_ROMAN = "upperRoman", export const LevelFormat = {
LOWER_ROMAN = "lowerRoman", DECIMAL: "decimal",
UPPER_LETTER = "upperLetter", UPPER_ROMAN: "upperRoman",
LOWER_LETTER = "lowerLetter", LOWER_ROMAN: "lowerRoman",
ORDINAL = "ordinal", UPPER_LETTER: "upperLetter",
CARDINAL_TEXT = "cardinalText", LOWER_LETTER: "lowerLetter",
ORDINAL_TEXT = "ordinalText", ORDINAL: "ordinal",
HEX = "hex", CARDINAL_TEXT: "cardinalText",
CHICAGO = "chicago", ORDINAL_TEXT: "ordinalText",
IDEOGRAPH__DIGITAL = "ideographDigital", HEX: "hex",
JAPANESE_COUNTING = "japaneseCounting", CHICAGO: "chicago",
AIUEO = "aiueo", IDEOGRAPH__DIGITAL: "ideographDigital",
IROHA = "iroha", JAPANESE_COUNTING: "japaneseCounting",
DECIMAL_FULL_WIDTH = "decimalFullWidth", AIUEO: "aiueo",
DECIMAL_HALF_WIDTH = "decimalHalfWidth", IROHA: "iroha",
JAPANESE_LEGAL = "japaneseLegal", DECIMAL_FULL_WIDTH: "decimalFullWidth",
JAPANESE_DIGITAL_TEN_THOUSAND = "japaneseDigitalTenThousand", DECIMAL_HALF_WIDTH: "decimalHalfWidth",
DECIMAL_ENCLOSED_CIRCLE = "decimalEnclosedCircle", JAPANESE_LEGAL: "japaneseLegal",
DECIMAL_FULL_WIDTH2 = "decimalFullWidth2", JAPANESE_DIGITAL_TEN_THOUSAND: "japaneseDigitalTenThousand",
AIUEO_FULL_WIDTH = "aiueoFullWidth", DECIMAL_ENCLOSED_CIRCLE: "decimalEnclosedCircle",
IROHA_FULL_WIDTH = "irohaFullWidth", DECIMAL_FULL_WIDTH2: "decimalFullWidth2",
DECIMAL_ZERO = "decimalZero", AIUEO_FULL_WIDTH: "aiueoFullWidth",
BULLET = "bullet", IROHA_FULL_WIDTH: "irohaFullWidth",
GANADA = "ganada", DECIMAL_ZERO: "decimalZero",
CHOSUNG = "chosung", BULLET: "bullet",
DECIMAL_ENCLOSED_FULLSTOP = "decimalEnclosedFullstop", GANADA: "ganada",
DECIMAL_ENCLOSED_PARENTHESES = "decimalEnclosedParen", CHOSUNG: "chosung",
DECIMAL_ENCLOSED_CIRCLE_CHINESE = "decimalEnclosedCircleChinese", DECIMAL_ENCLOSED_FULLSTOP: "decimalEnclosedFullstop",
IDEOGRAPH_ENCLOSED_CIRCLE = "ideographEnclosedCircle", DECIMAL_ENCLOSED_PARENTHESES: "decimalEnclosedParen",
IDEOGRAPH_TRADITIONAL = "ideographTraditional", DECIMAL_ENCLOSED_CIRCLE_CHINESE: "decimalEnclosedCircleChinese",
IDEOGRAPH_ZODIAC = "ideographZodiac", IDEOGRAPH_ENCLOSED_CIRCLE: "ideographEnclosedCircle",
IDEOGRAPH_ZODIAC_TRADITIONAL = "ideographZodiacTraditional", IDEOGRAPH_TRADITIONAL: "ideographTraditional",
TAIWANESE_COUNTING = "taiwaneseCounting", IDEOGRAPH_ZODIAC: "ideographZodiac",
IDEOGRAPH_LEGAL_TRADITIONAL = "ideographLegalTraditional", IDEOGRAPH_ZODIAC_TRADITIONAL: "ideographZodiacTraditional",
TAIWANESE_COUNTING_THOUSAND = "taiwaneseCountingThousand", TAIWANESE_COUNTING: "taiwaneseCounting",
TAIWANESE_DIGITAL = "taiwaneseDigital", IDEOGRAPH_LEGAL_TRADITIONAL: "ideographLegalTraditional",
CHINESE_COUNTING = "chineseCounting", TAIWANESE_COUNTING_THOUSAND: "taiwaneseCountingThousand",
CHINESE_LEGAL_SIMPLIFIED = "chineseLegalSimplified", TAIWANESE_DIGITAL: "taiwaneseDigital",
CHINESE_COUNTING_THOUSAND = "chineseCountingThousand", CHINESE_COUNTING: "chineseCounting",
KOREAN_DIGITAL = "koreanDigital", CHINESE_LEGAL_SIMPLIFIED: "chineseLegalSimplified",
KOREAN_COUNTING = "koreanCounting", CHINESE_COUNTING_THOUSAND: "chineseCountingThousand",
KOREAN_LEGAL = "koreanLegal", KOREAN_DIGITAL: "koreanDigital",
KOREAN_DIGITAL2 = "koreanDigital2", KOREAN_COUNTING: "koreanCounting",
VIETNAMESE_COUNTING = "vietnameseCounting", KOREAN_LEGAL: "koreanLegal",
RUSSIAN_LOWER = "russianLower", KOREAN_DIGITAL2: "koreanDigital2",
RUSSIAN_UPPER = "russianUpper", VIETNAMESE_COUNTING: "vietnameseCounting",
NONE = "none", RUSSIAN_LOWER: "russianLower",
NUMBER_IN_DASH = "numberInDash", RUSSIAN_UPPER: "russianUpper",
HEBREW1 = "hebrew1", NONE: "none",
HEBREW2 = "hebrew2", NUMBER_IN_DASH: "numberInDash",
ARABIC_ALPHA = "arabicAlpha", HEBREW1: "hebrew1",
ARABIC_ABJAD = "arabicAbjad", HEBREW2: "hebrew2",
HINDI_VOWELS = "hindiVowels", ARABIC_ALPHA: "arabicAlpha",
HINDI_CONSONANTS = "hindiConsonants", ARABIC_ABJAD: "arabicAbjad",
HINDI_NUMBERS = "hindiNumbers", HINDI_VOWELS: "hindiVowels",
HINDI_COUNTING = "hindiCounting", HINDI_CONSONANTS: "hindiConsonants",
THAI_LETTERS = "thaiLetters", HINDI_NUMBERS: "hindiNumbers",
THAI_NUMBERS = "thaiNumbers", HINDI_COUNTING: "hindiCounting",
THAI_COUNTING = "thaiCounting", THAI_LETTERS: "thaiLetters",
BAHT_TEXT = "bahtText", THAI_NUMBERS: "thaiNumbers",
DOLLAR_TEXT = "dollarText", THAI_COUNTING: "thaiCounting",
CUSTOM = "custom", BAHT_TEXT: "bahtText",
} DOLLAR_TEXT: "dollarText",
CUSTOM: "custom",
} as const;
/* eslint-enable */
class LevelAttributes extends XmlAttributeComponent<{ class LevelAttributes extends XmlAttributeComponent<{
readonly ilvl?: number; readonly ilvl?: number;
@ -182,7 +186,7 @@ class LevelText extends XmlComponent {
} }
class LevelJc extends XmlComponent { class LevelJc extends XmlComponent {
public constructor(value: AlignmentType) { public constructor(value: (typeof AlignmentType)[keyof typeof AlignmentType]) {
super("w:lvlJc"); super("w:lvlJc");
this.root.push( this.root.push(
new Attributes({ new Attributes({
@ -192,19 +196,19 @@ class LevelJc extends XmlComponent {
} }
} }
export enum LevelSuffix { export const LevelSuffix = {
NOTHING = "nothing", NOTHING: "nothing",
SPACE = "space", SPACE: "space",
TAB = "tab", TAB: "tab",
} } as const;
export interface ILevelsOptions { export interface ILevelsOptions {
readonly level: number; readonly level: number;
readonly format?: LevelFormat; readonly format?: (typeof LevelFormat)[keyof typeof LevelFormat];
readonly text?: string; readonly text?: string;
readonly alignment?: AlignmentType; readonly alignment?: (typeof AlignmentType)[keyof typeof AlignmentType];
readonly start?: number; readonly start?: number;
readonly suffix?: LevelSuffix; readonly suffix?: (typeof LevelSuffix)[keyof typeof LevelSuffix];
readonly isLegalNumberingStyle?: boolean; readonly isLegalNumberingStyle?: boolean;
readonly style?: { readonly style?: {
readonly run?: IRunStylePropertiesOptions; readonly run?: IRunStylePropertiesOptions;
@ -223,7 +227,7 @@ export interface ILevelsOptions {
// </xsd:restriction> // </xsd:restriction>
// </xsd:simpleType> // </xsd:simpleType>
class Suffix extends XmlComponent { class Suffix extends XmlComponent {
public constructor(value: LevelSuffix) { public constructor(value: (typeof LevelSuffix)[keyof typeof LevelSuffix]) {
super("w:suff"); super("w:suff");
this.root.push( this.root.push(
new Attributes({ new Attributes({

View File

@ -216,7 +216,7 @@ export class Numbering extends XmlComponent {
abstractNumId: abstractNumbering.id, abstractNumId: abstractNumbering.id,
reference, reference,
instance, instance,
overrideLevel: overrideLevels: [
firstLevelStartNumber && Number.isInteger(firstLevelStartNumber) firstLevelStartNumber && Number.isInteger(firstLevelStartNumber)
? { ? {
num: 0, num: 0,
@ -226,6 +226,7 @@ export class Numbering extends XmlComponent {
num: 0, num: 0,
start: 1, start: 1,
}, },
],
}; };
this.concreteNumberingMap.set(fullReference, new ConcreteNumbering(concreteNumberingSettings)); this.concreteNumberingMap.set(fullReference, new ConcreteNumbering(concreteNumberingSettings));

View File

@ -19,41 +19,47 @@ import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
// <xsd:enumeration value="right"/> // <xsd:enumeration value="right"/>
// </xsd:restriction> // </xsd:restriction>
// </xsd:simpleType> // </xsd:simpleType>
export enum AlignmentType {
/** Align Start */
START = "start",
/** Align Center */
CENTER = "center",
/** End */
END = "end",
/** Justified */
BOTH = "both",
/** Medium Kashida Length */
MEDIUM_KASHIDA = "mediumKashida",
/** Distribute All Characters Equally */
DISTRIBUTE = "distribute",
/** Align to List Tab */
NUM_TAB = "numTab",
/** Widest Kashida Length */
HIGH_KASHIDA = "highKashida",
/** Low Kashida Length */
LOW_KASHIDA = "lowKashida",
/** Thai Language Justification */
THAI_DISTRIBUTE = "thaiDistribute",
/** Align Left */
LEFT = "left",
/** Align Right */
RIGHT = "right",
/** Justified */
JUSTIFIED = "both",
}
export class AlignmentAttributes extends XmlAttributeComponent<{ readonly val: AlignmentType }> { /* eslint-disable @typescript-eslint/naming-convention */
export const AlignmentType = {
/** Align Start */
START: "start",
/** Align Center */
CENTER: "center",
/** End */
END: "end",
/** Justified */
BOTH: "both",
/** Medium Kashida Length */
MEDIUM_KASHIDA: "mediumKashida",
/** Distribute All Characters Equally */
DISTRIBUTE: "distribute",
/** Align to List Tab */
NUM_TAB: "numTab",
/** Widest Kashida Length */
HIGH_KASHIDA: "highKashida",
/** Low Kashida Length */
LOW_KASHIDA: "lowKashida",
/** Thai Language Justification */
THAI_DISTRIBUTE: "thaiDistribute",
/** Align Left */
LEFT: "left",
/** Align Right */
RIGHT: "right",
/** Justified */
JUSTIFIED: "both",
} as const;
/* eslint-enable */
export class AlignmentAttributes extends XmlAttributeComponent<{
readonly val: (typeof AlignmentType)[keyof typeof AlignmentType];
}> {
protected readonly xmlKeys = { val: "w:val" }; protected readonly xmlKeys = { val: "w:val" };
} }
export class Alignment extends XmlComponent { export class Alignment extends XmlComponent {
public constructor(type: AlignmentType) { public constructor(type: (typeof AlignmentType)[keyof typeof AlignmentType]) {
super("w:jc"); super("w:jc");
this.root.push(new AlignmentAttributes({ val: type })); this.root.push(new AlignmentAttributes({ val: type }));
} }

View File

@ -2,14 +2,14 @@
import { Attributes, XmlComponent } from "@file/xml-components"; import { Attributes, XmlComponent } from "@file/xml-components";
import { Run } from "../run"; import { Run } from "../run";
enum BreakType { const BreakType = {
COLUMN = "column", COLUMN: "column",
PAGE = "page", PAGE: "page",
// textWrapping breaks are the default and already exposed via the "Run" class // textWrapping breaks are the default and already exposed via the "Run" class
} } as const;
class Break extends XmlComponent { class Break extends XmlComponent {
public constructor(type: BreakType) { public constructor(type: (typeof BreakType)[keyof typeof BreakType]) {
super("w:br"); super("w:br");
this.root.push( this.root.push(
new Attributes({ new Attributes({

View File

@ -1,17 +1,19 @@
// http://officeopenxml.com/WPspacing.php // http://officeopenxml.com/WPspacing.php
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
export enum LineRuleType { export const LineRuleType = {
AT_LEAST = "atLeast", // eslint-disable-next-line @typescript-eslint/naming-convention
EXACTLY = "exactly", AT_LEAST: "atLeast",
EXACT = "exact", EXACTLY: "exactly",
AUTO = "auto", EXACT: "exact",
} AUTO: "auto",
} as const;
export interface ISpacingProperties { export interface ISpacingProperties {
readonly after?: number; readonly after?: number;
readonly before?: number; readonly before?: number;
readonly line?: number; readonly line?: number;
readonly lineRule?: LineRuleType; readonly lineRule?: (typeof LineRuleType)[keyof typeof LineRuleType];
readonly beforeAutoSpacing?: boolean; readonly beforeAutoSpacing?: boolean;
readonly afterAutoSpacing?: boolean; readonly afterAutoSpacing?: boolean;
} }

View File

@ -1,14 +1,14 @@
import { Attributes, XmlComponent } from "@file/xml-components"; import { Attributes, XmlComponent } from "@file/xml-components";
export enum HeadingLevel { export const HeadingLevel = {
HEADING_1 = "Heading1", HEADING_1: "Heading1",
HEADING_2 = "Heading2", HEADING_2: "Heading2",
HEADING_3 = "Heading3", HEADING_3: "Heading3",
HEADING_4 = "Heading4", HEADING_4: "Heading4",
HEADING_5 = "Heading5", HEADING_5: "Heading5",
HEADING_6 = "Heading6", HEADING_6: "Heading6",
TITLE = "Title", TITLE: "Title",
} } as const;
export class Style extends XmlComponent { export class Style extends XmlComponent {
public constructor(styleId: string) { public constructor(styleId: string) {

View File

@ -2,9 +2,9 @@
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
export interface TabStopDefinition { export interface TabStopDefinition {
readonly type: TabStopType; readonly type: (typeof TabStopType)[keyof typeof TabStopType];
readonly position: number | TabStopPosition; readonly position: number | (typeof TabStopPosition)[keyof typeof TabStopPosition];
readonly leader?: LeaderType; readonly leader?: (typeof LeaderType)[keyof typeof LeaderType];
} }
export class TabStop extends XmlComponent { export class TabStop extends XmlComponent {
@ -17,34 +17,35 @@ export class TabStop extends XmlComponent {
} }
} }
export enum TabStopType { export const TabStopType = {
LEFT = "left", LEFT: "left",
RIGHT = "right", RIGHT: "right",
CENTER = "center", CENTER: "center",
BAR = "bar", BAR: "bar",
CLEAR = "clear", CLEAR: "clear",
DECIMAL = "decimal", DECIMAL: "decimal",
END = "end", END: "end",
NUM = "num", NUM: "num",
START = "start", START: "start",
} } as const;
export enum LeaderType { export const LeaderType = {
DOT = "dot", DOT: "dot",
HYPHEN = "hyphen", HYPHEN: "hyphen",
MIDDLE_DOT = "middleDot", // eslint-disable-next-line @typescript-eslint/naming-convention
NONE = "none", MIDDLE_DOT: "middleDot",
UNDERSCORE = "underscore", NONE: "none",
} UNDERSCORE: "underscore",
} as const;
export enum TabStopPosition { export const TabStopPosition = {
MAX = 9026, MAX: 9026,
} } as const;
export class TabAttributes extends XmlAttributeComponent<{ export class TabAttributes extends XmlAttributeComponent<{
readonly val: TabStopType; readonly val: (typeof TabStopType)[keyof typeof TabStopType];
readonly pos: string | number; readonly pos: string | number;
readonly leader?: LeaderType; readonly leader?: (typeof LeaderType)[keyof typeof LeaderType];
}> { }> {
protected readonly xmlKeys = { val: "w:val", pos: "w:pos", leader: "w:leader" }; protected readonly xmlKeys = { val: "w:val", pos: "w:pos", leader: "w:leader" };
} }

View File

@ -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,
}, },
}); },
}); });
}); });
}); });

View File

@ -1,48 +1,50 @@
// 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 enum DropCapType { export const DropCapType = {
NONE = "none", NONE: "none",
DROP = "drop", DROP: "drop",
MARGIN = "margin", MARGIN: "margin",
} } as const;
export enum FrameAnchorType { export const FrameAnchorType = {
MARGIN = "margin", MARGIN: "margin",
PAGE = "page", PAGE: "page",
TEXT = "text", TEXT: "text",
} } as const;
export enum FrameWrap { export const FrameWrap = {
AROUND = "around", AROUND: "around",
AUTO = "auto", AUTO: "auto",
NONE = "none", NONE: "none",
NOT_BESIDE = "notBeside", // eslint-disable-next-line @typescript-eslint/naming-convention
THROUGH = "through", NOT_BESIDE: "notBeside",
TIGHT = "tight", THROUGH: "through",
} TIGHT: "tight",
} as const;
interface IBaseFrameOptions { interface IBaseFrameOptions {
readonly anchorLock?: boolean; readonly anchorLock?: boolean;
readonly dropCap?: DropCapType; readonly dropCap?: (typeof DropCapType)[keyof typeof DropCapType];
readonly width: number; readonly width: number;
readonly height: number; readonly height: number;
readonly wrap?: FrameWrap; readonly wrap?: (typeof FrameWrap)[keyof typeof FrameWrap];
readonly lines?: number; readonly lines?: number;
readonly anchor: { readonly anchor: {
readonly horizontal: FrameAnchorType; readonly horizontal: (typeof FrameAnchorType)[keyof typeof FrameAnchorType];
readonly vertical: FrameAnchorType; readonly vertical: (typeof FrameAnchorType)[keyof typeof FrameAnchorType];
}; };
readonly space?: { readonly space?: {
readonly horizontal: number; readonly horizontal: number;
readonly vertical: number; readonly vertical: number;
}; };
readonly rule?: HeightRule; readonly rule?: (typeof HeightRule)[keyof typeof HeightRule];
} }
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;
@ -50,9 +52,10 @@ export interface IXYFrameOptions extends IBaseFrameOptions {
} }
export interface IAlignmentFrameOptions extends IBaseFrameOptions { export interface IAlignmentFrameOptions extends IBaseFrameOptions {
readonly type: "alignment";
readonly alignment: { readonly alignment: {
readonly x: HorizontalPositionAlign; readonly x: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign];
readonly y: VerticalPositionAlign; readonly y: (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign];
}; };
} }
@ -60,63 +63,104 @@ 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?: DropCapType; readonly dropCap?: (typeof DropCapType)[keyof typeof DropCapType];
readonly width: number; readonly width: number;
readonly height: number; readonly height: number;
readonly x?: number; readonly x?: number;
readonly y?: number; readonly y?: number;
readonly wrap?: FrameWrap; readonly wrap?: (typeof FrameWrap)[keyof typeof FrameWrap];
readonly lines?: number; readonly lines?: number;
readonly anchorHorizontal?: FrameAnchorType; readonly anchorHorizontal?: (typeof FrameAnchorType)[keyof typeof FrameAnchorType];
readonly anchorVertical?: FrameAnchorType; readonly anchorVertical?: (typeof FrameAnchorType)[keyof typeof FrameAnchorType];
readonly spaceHorizontal?: number; readonly spaceHorizontal?: number;
readonly spaceVertical?: number; readonly spaceVertical?: number;
readonly rule?: HeightRule; readonly rule?: (typeof HeightRule)[keyof typeof HeightRule];
readonly alignmentX?: HorizontalPositionAlign; readonly alignmentX?: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign];
readonly alignmentY?: 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,
},
},
});

View File

@ -5,10 +5,10 @@ import { uniqueId } from "@util/convenience-functions";
import { ParagraphChild } from "../paragraph"; import { ParagraphChild } from "../paragraph";
import { HyperlinkAttributes, IHyperlinkAttributesProperties } from "./hyperlink-attributes"; import { HyperlinkAttributes, IHyperlinkAttributesProperties } from "./hyperlink-attributes";
export enum HyperlinkType { export const HyperlinkType = {
INTERNAL = "INTERNAL", INTERNAL: "INTERNAL",
EXTERNAL = "EXTERNAL", EXTERNAL: "EXTERNAL",
} } as const;
export class ConcreteHyperlink extends XmlComponent { export class ConcreteHyperlink extends XmlComponent {
public readonly linkId: string; public readonly linkId: string;
@ -39,7 +39,12 @@ export class InternalHyperlink extends ConcreteHyperlink {
} }
export class ExternalHyperlink extends XmlComponent { export class ExternalHyperlink extends XmlComponent {
public constructor(public readonly options: { readonly children: readonly ParagraphChild[]; readonly link: string }) { public constructor(
public readonly options: {
readonly children: readonly ParagraphChild[];
readonly link: string;
},
) {
super("w:externalHyperlink"); super("w:externalHyperlink");
} }
} }

View File

@ -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 = {}) {

View File

@ -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;
}

View File

@ -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 = {}) {

View File

@ -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",
}, },
}, },

View File

@ -158,5 +158,52 @@ 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", () => {
const properties = new ParagraphProperties({
run: {
size: "10pt",
},
});
const tree = new Formatter().format(properties);
expect(tree).to.deep.equal({
"w:pPr": [
{
"w:rPr": [
{
"w:sz": {
_attr: {
"w:val": "10pt",
},
},
},
{
"w:szCs": {
_attr: {
"w:val": "10pt",
},
},
},
],
},
],
});
});
}); });
}); });

View File

@ -1,5 +1,6 @@
// http://officeopenxml.com/WPparagraphProperties.php // http://officeopenxml.com/WPparagraphProperties.php
// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_suppressLineNumbers_topic_ID0ECJAO.html // https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_suppressLineNumbers_topic_ID0ECJAO.html
/* eslint-disable functional/immutable-data */
import { IContext, IgnoreIfEmptyXmlComponent, IXmlableObject, OnOffElement, XmlComponent } from "@file/xml-components"; import { IContext, IgnoreIfEmptyXmlComponent, IXmlableObject, OnOffElement, XmlComponent } from "@file/xml-components";
import { DocumentWrapper } from "../document-wrapper"; import { DocumentWrapper } from "../document-wrapper";
import { IShadingAttributesProperties, Shading } from "../shading"; import { IShadingAttributesProperties, Shading } from "../shading";
@ -12,11 +13,12 @@ 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 ".";
export interface ILevelParagraphStylePropertiesOptions { export interface ILevelParagraphStylePropertiesOptions {
readonly alignment?: AlignmentType; readonly alignment?: (typeof AlignmentType)[keyof typeof AlignmentType];
readonly thematicBreak?: boolean; readonly thematicBreak?: boolean;
readonly contextualSpacing?: boolean; readonly contextualSpacing?: boolean;
readonly rightTabStop?: number; readonly rightTabStop?: number;
@ -45,7 +47,7 @@ export interface IParagraphStylePropertiesOptions extends ILevelParagraphStylePr
export interface IParagraphPropertiesOptions extends IParagraphStylePropertiesOptions { export interface IParagraphPropertiesOptions extends IParagraphStylePropertiesOptions {
readonly border?: IBordersOptions; readonly border?: IBordersOptions;
readonly heading?: HeadingLevel; readonly heading?: (typeof HeadingLevel)[keyof typeof HeadingLevel];
readonly bidirectional?: boolean; readonly bidirectional?: boolean;
readonly pageBreakBefore?: boolean; readonly pageBreakBefore?: boolean;
readonly tabStops?: readonly TabStopDefinition[]; readonly tabStops?: readonly TabStopDefinition[];
@ -58,12 +60,17 @@ 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.
* This only works in Microsoft Word. It is not part of the ECMA-376 OOXML standard. * This only works in Microsoft Word. It is not part of the ECMA-376 OOXML standard.
*/ */
readonly autoSpaceEastAsianText?: boolean; readonly autoSpaceEastAsianText?: boolean;
/**
* Reference: ECMA-376, 3rd Edition (June, 2011), Fundamentals and Markup Language Reference § 17.3.1.29.
*/
readonly run?: IRunOptions;
} }
export class ParagraphProperties extends IgnoreIfEmptyXmlComponent { export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
@ -110,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) {
@ -146,14 +153,18 @@ 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
*/ */
const tabDefinitions: readonly TabStopDefinition[] = [ const tabDefinitions: readonly TabStopDefinition[] = [
...(options.rightTabStop ? [{ type: TabStopType.RIGHT, position: options.rightTabStop }] : []), ...(options.rightTabStop !== undefined ? [{ type: TabStopType.RIGHT, position: options.rightTabStop }] : []),
...(options.tabStops ? options.tabStops : []), ...(options.tabStops ? options.tabStops : []),
...(options.leftTabStop ? [{ type: TabStopType.LEFT, position: options.leftTabStop }] : []), ...(options.leftTabStop !== undefined ? [{ type: TabStopType.LEFT, position: options.leftTabStop }] : []),
]; ];
if (tabDefinitions.length > 0) { if (tabDefinitions.length > 0) {
@ -194,6 +205,10 @@ export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
if (options.autoSpaceEastAsianText !== undefined) { if (options.autoSpaceEastAsianText !== undefined) {
this.push(new OnOffElement("w:autoSpaceDN", options.autoSpaceEastAsianText)); this.push(new OnOffElement("w:autoSpaceDN", options.autoSpaceEastAsianText));
} }
if (options.run) {
this.push(new RunProperties(options.run));
}
} }
public push(item: XmlComponent): void { public push(item: XmlComponent): void {

View File

@ -1,11 +1,11 @@
import { Attributes, XmlComponent } from "@file/xml-components"; import { Attributes, XmlComponent } from "@file/xml-components";
export enum EmphasisMarkType { export const EmphasisMarkType = {
DOT = "dot", DOT: "dot",
} } as const;
export abstract class BaseEmphasisMark extends XmlComponent { export abstract class BaseEmphasisMark extends XmlComponent {
protected constructor(emphasisMarkType: EmphasisMarkType) { protected constructor(emphasisMarkType: (typeof EmphasisMarkType)[keyof typeof EmphasisMarkType]) {
super("w:em"); super("w:em");
this.root.push( this.root.push(
new Attributes({ new Attributes({
@ -16,7 +16,7 @@ export abstract class BaseEmphasisMark extends XmlComponent {
} }
export class EmphasisMark extends BaseEmphasisMark { export class EmphasisMark extends BaseEmphasisMark {
public constructor(emphasisMarkType: EmphasisMarkType = EmphasisMarkType.DOT) { public constructor(emphasisMarkType: (typeof EmphasisMarkType)[keyof typeof EmphasisMarkType] = EmphasisMarkType.DOT) {
super(emphasisMarkType); super(emphasisMarkType);
} }
} }

View File

@ -1,12 +1,15 @@
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
enum FieldCharacterType { const FieldCharacterType = {
BEGIN = "begin", BEGIN: "begin",
END = "end", END: "end",
SEPARATE = "separate", SEPARATE: "separate",
} } as const;
class FidCharAttrs extends XmlAttributeComponent<{ readonly type: FieldCharacterType; readonly dirty?: boolean }> { class FidCharAttrs extends XmlAttributeComponent<{
readonly type: (typeof FieldCharacterType)[keyof typeof FieldCharacterType];
readonly dirty?: boolean;
}> {
protected readonly xmlKeys = { type: "w:fldCharType", dirty: "w:dirty" }; protected readonly xmlKeys = { type: "w:fldCharType", dirty: "w:dirty" };
} }

Some files were not shown because too many files have changed in this diff Show More