Compare commits

...

287 Commits
7.8.0 ... 8.0.0

Author SHA1 Message Date
78757753c8 Version bump 2023-03-19 03:27:29 +00:00
8343edcdf1 Update documentation 2023-03-19 03:26:02 +00:00
1ab9e08eb9 Bump coverage 2023-03-19 01:35:29 +00:00
e1bc7f34c9 Merge pull request #2015 from dolanmiu/feat/allow-for-children-in-comments
#1988 Allow for children in comments
2023-03-19 01:00:22 +00:00
d5b495df5b #1988 Allow for children in comments 2023-03-19 00:18:38 +00:00
d6256d2acb Merge pull request #2012 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-jsdoc-40.1.0
build(deps-dev): bump eslint-plugin-jsdoc from 40.0.3 to 40.1.0
2023-03-18 23:46:34 +00:00
f1c7e448ae Merge pull request #2014 from dolanmiu/feat/regex-match-for-types-fixer
Add fix to allow for different types of slash to be supported
2023-03-18 23:46:25 +00:00
b600fd9324 Add fix to allow for different types of slash to be supported
Maybe updating glob broke it for Windows
2023-03-18 23:16:41 +00:00
3bf40ecb33 Merge pull request #2013 from dolanmiu/feat/add-src-to-npmignore
#2002 Add src to .npmignore
2023-03-18 23:11:59 +00:00
ffb650daa9 #2002 Add src to .npmignore 2023-03-18 21:27:08 +00:00
d2122e7806 build(deps-dev): bump eslint-plugin-jsdoc from 40.0.3 to 40.1.0
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 40.0.3 to 40.1.0.
- [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/v40.0.3...v40.1.0)

---
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-03-18 21:21:06 +00:00
6b6eb1d7a2 Merge pull request #2008 from dolanmiu/dependabot/npm_and_yarn/typedoc-0.23.27
build(deps-dev): bump typedoc from 0.23.26 to 0.23.27
2023-03-18 21:20:52 +00:00
c80d881105 Merge pull request #2009 from dolanmiu/dependabot/npm_and_yarn/sinon-15.0.2
build(deps-dev): bump sinon from 15.0.1 to 15.0.2
2023-03-18 21:20:45 +00:00
3c223c69e9 Merge pull request #2010 from dolanmiu/dependabot/npm_and_yarn/typescript-5.0.2
build(deps-dev): bump typescript from 4.9.5 to 5.0.2
2023-03-18 21:20:38 +00:00
2420321008 Merge pull request #2011 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-jsdoc-40.0.3
build(deps-dev): bump eslint-plugin-jsdoc from 40.0.1 to 40.0.3
2023-03-18 21:20:30 +00:00
29d5421cea Merge pull request #2003 from dolanmiu/dependabot/npm_and_yarn/glob-9.3.0
build(deps-dev): bump glob from 8.1.0 to 9.3.0
2023-03-18 21:20:22 +00:00
325866d9c3 build(deps-dev): bump eslint-plugin-jsdoc from 40.0.1 to 40.0.3
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 40.0.1 to 40.0.3.
- [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/v40.0.1...v40.0.3)

---
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-03-17 11:57:54 +00:00
457e9c12e3 build(deps-dev): bump typescript from 4.9.5 to 5.0.2
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.9.5 to 5.0.2.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.9.5...v5.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-17 11:57:34 +00:00
ff4a66466a build(deps-dev): bump sinon from 15.0.1 to 15.0.2
Bumps [sinon](https://github.com/sinonjs/sinon) from 15.0.1 to 15.0.2.
- [Release notes](https://github.com/sinonjs/sinon/releases)
- [Changelog](https://github.com/sinonjs/sinon/blob/main/docs/changelog.md)
- [Commits](https://github.com/sinonjs/sinon/compare/v15.0.1...v15.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-17 11:57:12 +00:00
cc142cc052 build(deps-dev): bump typedoc from 0.23.26 to 0.23.27
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.23.26 to 0.23.27.
- [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.23.26...v0.23.27)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-17 11:56:43 +00:00
6e0dc69217 build(deps-dev): bump glob from 8.1.0 to 9.3.0
Bumps [glob](https://github.com/isaacs/node-glob) from 8.1.0 to 9.3.0.
- [Release notes](https://github.com/isaacs/node-glob/releases)
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v8.1.0...v9.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-17 02:55:01 +00:00
33332bcf66 Merge pull request #1993 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-functional-5.0.6
build(deps-dev): bump eslint-plugin-functional from 5.0.4 to 5.0.6
2023-03-17 02:54:26 +00:00
b94f9ac25b Merge pull request #1920 from dolanmiu/feat/float-options
Use next attribute component
2023-03-17 02:42:49 +00:00
0a7be48dcb build(deps-dev): bump eslint-plugin-functional from 5.0.4 to 5.0.6
Bumps [eslint-plugin-functional](https://github.com/eslint-functional/eslint-plugin-functional) from 5.0.4 to 5.0.6.
- [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.4...v5.0.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-17 02:41:12 +00:00
3f3397620e Merge pull request #2005 from dolanmiu/dependabot/npm_and_yarn/cspell-6.30.0
build(deps-dev): bump cspell from 6.28.0 to 6.30.0
2023-03-17 02:40:17 +00:00
154bc1df95 Merge pull request #2004 from dolanmiu/dependabot/npm_and_yarn/webpack-5.76.2
build(deps-dev): bump webpack from 5.75.0 to 5.76.2
2023-03-17 02:40:09 +00:00
715e436c4c Merge pull request #2000 from dolanmiu/dependabot/npm_and_yarn/types/node-18.15.3
build(deps): bump @types/node from 18.14.5 to 18.15.3
2023-03-17 02:39:59 +00:00
f5a9bcf839 Merge pull request #1999 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/parser-5.55.0
build(deps-dev): bump @typescript-eslint/parser from 5.54.0 to 5.55.0
2023-03-17 02:39:50 +00:00
31d2da86ff Merge pull request #1998 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.55.0
build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.54.0 to 5.55.0
2023-03-17 02:39:21 +00:00
9dad3ca356 Merge pull request #1994 from dolanmiu/dependabot/npm_and_yarn/eslint-8.36.0
build(deps-dev): bump eslint from 8.35.0 to 8.36.0
2023-03-17 02:39:08 +00:00
355e01edc6 Merge pull request #1979 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-unicorn-46.0.0
build(deps-dev): bump eslint-plugin-unicorn from 45.0.2 to 46.0.0
2023-03-17 02:38:58 +00:00
c19bf1c404 Merge pull request #2007 from dolanmiu/feat/autoSpaceDN
#1949 - Add auto space DN feature
2023-03-17 02:34:53 +00:00
970450074d #1949 - Add auto space DN feature 2023-03-17 02:20:51 +00:00
91e8295648 Merge pull request #2006 from dolanmiu/feat/deprecate-templates
Deprecate import dotx
2023-03-17 01:26:26 +00:00
3e40ae862b Remove demo 30 from CI 2023-03-17 01:15:45 +00:00
236cce604f Fix tests 2023-03-17 00:54:29 +00:00
0388a564b5 Deprecate import dotx 2023-03-17 00:20:55 +00:00
cd77ceba69 build(deps-dev): bump cspell from 6.28.0 to 6.30.0
Bumps [cspell](https://github.com/streetsidesoftware/cspell) from 6.28.0 to 6.30.0.
- [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.28.0...v6.30.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-16 23:38:36 +00:00
5ae8731abe build(deps-dev): bump @typescript-eslint/parser from 5.54.0 to 5.55.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.54.0 to 5.55.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.55.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-03-16 23:38:28 +00:00
7bb90c55d1 build(deps-dev): bump eslint from 8.35.0 to 8.36.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.35.0 to 8.36.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.35.0...v8.36.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-03-16 23:38:24 +00:00
a07d6378e8 Merge pull request #1960 from dolanmiu/feat/new-template
Document Patcher - Re-write / Re-vamp template feature
2023-03-16 23:37:31 +00:00
4fb8d277b4 Change demo import from src to build 2023-03-16 20:33:54 +00:00
73186ce920 build(deps-dev): bump webpack from 5.75.0 to 5.76.2
Bumps [webpack](https://github.com/webpack/webpack) from 5.75.0 to 5.76.2.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.75.0...v5.76.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-16 11:57:58 +00:00
d02f98956f Fix spelling errors 2023-03-16 03:24:51 +00:00
d186d42bb6 Merge branch 'master' into feat/new-template
# Conflicts:
#	package-lock.json
2023-03-16 03:18:50 +00:00
338f7be967 Add chai as promised and fix async test 2023-03-16 03:14:01 +00:00
b63a6e6e16 Update coverage stats 2023-03-16 02:02:02 +00:00
7e9884081e Add tests to patcher 2023-03-16 01:55:18 +00:00
262f6323d0 Write more tests and simplify code 2023-03-15 03:14:38 +00:00
811dd61562 Add tests 2023-03-15 02:46:39 +00:00
9801879063 build(deps): bump @types/node from 18.14.5 to 18.15.3
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.14.5 to 18.15.3.
- [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-03-14 11:58:04 +00:00
e30836c935 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.54.0 to 5.55.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/v5.55.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>
2023-03-14 11:56:58 +00:00
352511bb55 Add tests 2023-03-14 03:13:23 +00:00
8ce057e25c Context per view wrapper 2023-03-13 21:35:16 +00:00
0775ecb08b Merge pull request #1990 from dolanmiu/dependabot/npm_and_yarn/tsconfig-paths-webpack-plugin-4.0.1
build(deps-dev): bump tsconfig-paths-webpack-plugin from 4.0.0 to 4.0.1
2023-03-10 02:33:07 +00:00
e909ab9886 Merge pull request #1991 from dolanmiu/dependabot/npm_and_yarn/rimraf-4.4.0
build(deps-dev): bump rimraf from 4.2.0 to 4.4.0
2023-03-10 02:32:57 +00:00
e03bb155b9 build(deps-dev): bump rimraf from 4.2.0 to 4.4.0
Bumps [rimraf](https://github.com/isaacs/rimraf) from 4.2.0 to 4.4.0.
- [Release notes](https://github.com/isaacs/rimraf/releases)
- [Changelog](https://github.com/isaacs/rimraf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/rimraf/compare/v4.2.0...v4.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-09 11:57:17 +00:00
91620d61d8 build(deps-dev): bump tsconfig-paths-webpack-plugin from 4.0.0 to 4.0.1
Bumps [tsconfig-paths-webpack-plugin](https://github.com/dividab/tsconfig-paths-webpack-plugin) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/dividab/tsconfig-paths-webpack-plugin/releases)
- [Changelog](https://github.com/dividab/tsconfig-paths-webpack-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/dividab/tsconfig-paths-webpack-plugin/compare/v4.0.0...v4.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-09 11:56:45 +00:00
0fba450c9a Allow patching of ExternalHyperlinks 2023-03-08 23:30:51 +00:00
ca604fb004 Merge pull request #1982 from dolanmiu/dependabot/npm_and_yarn/cspell-6.28.0
build(deps-dev): bump cspell from 6.27.0 to 6.28.0
2023-03-06 16:13:02 +00:00
9e998d233c build(deps-dev): bump cspell from 6.27.0 to 6.28.0
Bumps [cspell](https://github.com/streetsidesoftware/cspell) from 6.27.0 to 6.28.0.
- [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.27.0...v6.28.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-06 11:57:29 +00:00
6c0fd3adec build(deps-dev): bump eslint-plugin-unicorn from 45.0.2 to 46.0.0
Bumps [eslint-plugin-unicorn](https://github.com/sindresorhus/eslint-plugin-unicorn) from 45.0.2 to 46.0.0.
- [Release notes](https://github.com/sindresorhus/eslint-plugin-unicorn/releases)
- [Commits](https://github.com/sindresorhus/eslint-plugin-unicorn/compare/v45.0.2...v46.0.0)

---
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-03-06 11:56:43 +00:00
6ad18420e5 Add hyperlink to demo 2023-03-05 18:46:02 +00:00
ef95a16f39 Merge pull request #1975 from dolanmiu/dependabot/npm_and_yarn/rimraf-4.2.0
build(deps-dev): bump rimraf from 4.1.2 to 4.2.0
2023-03-05 04:44:07 +00:00
53861ec18d Merge pull request #1976 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-jsdoc-40.0.1
build(deps-dev): bump eslint-plugin-jsdoc from 40.0.0 to 40.0.1
2023-03-05 04:44:00 +00:00
81b1569ad2 Merge pull request #1977 from dolanmiu/dependabot/npm_and_yarn/types/node-18.14.5
build(deps): bump @types/node from 18.14.2 to 18.14.5
2023-03-05 04:43:52 +00:00
66a1992da0 Add ImageRun feature 2023-03-03 23:47:50 +00:00
100356c344 build(deps): bump @types/node from 18.14.2 to 18.14.5
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.14.2 to 18.14.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-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-03 11:57:17 +00:00
31905a27b1 build(deps-dev): bump eslint-plugin-jsdoc from 40.0.0 to 40.0.1
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 40.0.0 to 40.0.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/v40.0.0...v40.0.1)

---
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-03-03 11:57:05 +00:00
08916176a2 build(deps-dev): bump rimraf from 4.1.2 to 4.2.0
Bumps [rimraf](https://github.com/isaacs/rimraf) from 4.1.2 to 4.2.0.
- [Release notes](https://github.com/isaacs/rimraf/releases)
- [Changelog](https://github.com/isaacs/rimraf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/rimraf/compare/v4.1.2...v4.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-03 11:56:40 +00:00
ffb3d63c92 Merge pull request #1968 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/parser-5.54.0
build(deps-dev): bump @typescript-eslint/parser from 5.53.0 to 5.54.0
2023-03-01 03:32:54 +00:00
22005428ba Merge pull request #1967 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.54.0
build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.52.0 to 5.54.0
2023-02-28 19:35:29 +00:00
a70acd6d63 build(deps-dev): bump @typescript-eslint/parser from 5.53.0 to 5.54.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.53.0 to 5.54.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.54.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-02-28 11:56:53 +00:00
af9e0b0d3f 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.52.0 to 5.54.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/v5.54.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>
2023-02-28 10:59:29 +00:00
a0c2be8af2 Merge pull request #1955 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/parser-5.53.0
build(deps-dev): bump @typescript-eslint/parser from 5.52.0 to 5.53.0
2023-02-28 10:58:30 +00:00
df9d4b4219 Merge pull request #1961 from dolanmiu/dependabot/npm_and_yarn/cspell-6.27.0
build(deps-dev): bump cspell from 6.26.3 to 6.27.0
2023-02-28 02:55:00 +00:00
cdf5015920 Merge pull request #1962 from dolanmiu/dependabot/npm_and_yarn/eslint-8.35.0
build(deps-dev): bump eslint from 8.34.0 to 8.35.0
2023-02-28 02:52:54 +00:00
fe9b438a51 Update documentation 2023-02-27 21:06:54 +00:00
59cbf8c9cb build(deps-dev): bump cspell from 6.26.3 to 6.27.0
Bumps [cspell](https://github.com/streetsidesoftware/cspell) from 6.26.3 to 6.27.0.
- [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.26.3...v6.27.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-27 16:54:32 +00:00
7af8175034 build(deps-dev): bump eslint from 8.34.0 to 8.35.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.34.0 to 8.35.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.34.0...v8.35.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-02-27 16:53:42 +00:00
bf0393b485 build(deps-dev): bump @typescript-eslint/parser from 5.52.0 to 5.53.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.52.0 to 5.53.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.53.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-02-27 16:53:31 +00:00
83a8822cf7 Merge pull request #1957 from dolanmiu/dependabot/npm_and_yarn/types/glob-8.1.0
build(deps-dev): bump @types/glob from 8.0.1 to 8.1.0
2023-02-27 16:53:03 +00:00
eada41b8a1 Merge pull request #1964 from dolanmiu/dependabot/npm_and_yarn/typedoc-0.23.26
build(deps-dev): bump typedoc from 0.23.25 to 0.23.26
2023-02-27 16:52:55 +00:00
2c03377c47 Merge pull request #1963 from dolanmiu/dependabot/npm_and_yarn/types/node-18.14.2
build(deps): bump @types/node from 18.13.0 to 18.14.2
2023-02-27 16:52:45 +00:00
484fc4aa2d build(deps-dev): bump typedoc from 0.23.25 to 0.23.26
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.23.25 to 0.23.26.
- [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.23.25...v0.23.26)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-27 11:58:30 +00:00
2846014db0 build(deps): bump @types/node from 18.13.0 to 18.14.2
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.13.0 to 18.14.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-02-27 11:58:10 +00:00
c9d86619de Clean up 2023-02-25 22:18:56 +00:00
ce485dbc29 Simplify patcher
Use map notation
2023-02-25 22:18:31 +00:00
4e875b4744 Re-name templater to patcher 2023-02-25 20:18:00 +00:00
3f6c006716 Allow for it to work with all xml files under word/ 2023-02-25 19:34:04 +00:00
f8f5d43b0c Allow for Paragraph and array patching 2023-02-25 19:33:12 +00:00
8c0fe00c6f Add launch json 2023-02-24 02:55:53 +00:00
c37d9ca5b3 Add ts-node to tsconfig 2023-02-24 01:44:53 +00:00
f3dc1f0712 Work on replacer logic 2023-02-24 01:05:43 +00:00
a4d96bbf6e Add paragraph token replacer 2023-02-23 19:43:19 +00:00
90c40178aa build(deps-dev): bump @types/glob from 8.0.1 to 8.1.0
Bumps [@types/glob](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/glob) from 8.0.1 to 8.1.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/glob)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-23 11:11:19 +00:00
2ee96b419a Merge branch 'master' into feat/new-template 2023-02-22 20:39:59 +00:00
773900b620 Merge branch 'master' of github.com:dolanmiu/docx 2023-02-22 20:17:58 +00:00
ece440340f Add footnotes documentation 2023-02-22 20:16:23 +00:00
5233b4b5e6 Simple patcher working 2023-02-18 20:36:24 +00:00
86de252a52 Extract runs and text 2023-02-17 10:38:03 +00:00
c206d23480 work on docx patcher 2023-02-16 20:17:48 +00:00
5a53a138d9 Merge pull request #1946 from dolanmiu/dependabot/npm_and_yarn/cspell-6.26.3
build(deps-dev): bump cspell from 6.22.0 to 6.26.3
2023-02-16 16:36:43 +00:00
5b5deb198e Merge pull request #1941 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.52.0
build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.51.0 to 5.52.0
2023-02-16 16:36:30 +00:00
88a30e5af7 Merge pull request #1940 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/parser-5.52.0
build(deps-dev): bump @typescript-eslint/parser from 5.51.0 to 5.52.0
2023-02-16 16:36:18 +00:00
0b9ffa9a7b Merge pull request #1938 from dolanmiu/dependabot/npm_and_yarn/typedoc-0.23.25
build(deps-dev): bump typedoc from 0.23.24 to 0.23.25
2023-02-16 16:36:07 +00:00
5052bcde4f Merge pull request #1937 from dolanmiu/dependabot/npm_and_yarn/eslint-8.34.0
build(deps-dev): bump eslint from 8.33.0 to 8.34.0
2023-02-16 16:35:54 +00:00
d5409678ee Merge pull request #1945 from cledoux95/readme/docx-used-by-novelpad
Add NovelPad to Companies
2023-02-16 16:35:24 +00:00
72c39a9eb2 build(deps-dev): bump cspell from 6.22.0 to 6.26.3
Bumps [cspell](https://github.com/streetsidesoftware/cspell) from 6.22.0 to 6.26.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/v6.22.0...v6.26.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-16 11:57:22 +00:00
2ed7a28d1e Fixed Whitespace 2023-02-15 18:36:28 -05:00
7b2ff00c83 Add NovelPad to Companies 2023-02-15 18:34:40 -05:00
d5b0083d77 build(deps-dev): bump eslint from 8.33.0 to 8.34.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.33.0 to 8.34.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.33.0...v8.34.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-02-15 20:26:23 +00:00
406183d104 Merge pull request #1935 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-jsdoc-40.0.0
build(deps-dev): bump eslint-plugin-jsdoc from 39.8.0 to 40.0.0
2023-02-15 20:25:17 +00:00
c6d3e60314 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.51.0 to 5.52.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/v5.52.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>
2023-02-14 11:57:37 +00:00
be71037a13 build(deps-dev): bump @typescript-eslint/parser from 5.51.0 to 5.52.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.51.0 to 5.52.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.52.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-02-14 11:56:54 +00:00
c8c64b320b build(deps-dev): bump typedoc from 0.23.24 to 0.23.25
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.23.24 to 0.23.25.
- [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.23.24...v0.23.25)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 11:59:09 +00:00
8514e8ad31 build(deps-dev): bump eslint-plugin-jsdoc from 39.8.0 to 40.0.0
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 39.8.0 to 40.0.0.
- [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/v39.8.0...v40.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 11:57:05 +00:00
d505281a7e Merge pull request #1928 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.51.0
build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.50.0 to 5.51.0
2023-02-08 15:01:28 +00:00
58575342e0 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.50.0 to 5.51.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/v5.51.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>
2023-02-08 11:21:24 +00:00
60ad6d6ab5 Merge pull request #1930 from dolanmiu/dependabot/npm_and_yarn/prettier-2.8.4
build(deps-dev): bump prettier from 2.8.3 to 2.8.4
2023-02-08 11:19:43 +00:00
f9dec1cb3c build(deps-dev): bump prettier from 2.8.3 to 2.8.4
Bumps [prettier](https://github.com/prettier/prettier) from 2.8.3 to 2.8.4.
- [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/2.8.3...2.8.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-08 11:01:31 +00:00
ffd998cbf5 Simple import and export of document 2023-02-08 03:18:11 +00:00
c713e6f371 Merge pull request #1927 from dolanmiu/dependabot/npm_and_yarn/types/node-18.13.0
build(deps): bump @types/node from 18.11.18 to 18.13.0
2023-02-07 15:39:18 +00:00
3c55f9fc1f Merge pull request #1925 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-jsdoc-39.8.0
build(deps-dev): bump eslint-plugin-jsdoc from 39.7.5 to 39.8.0
2023-02-07 15:39:11 +00:00
c9a8a99278 Merge pull request #1923 from dolanmiu/dependabot/npm_and_yarn/cspell-6.22.0
build(deps-dev): bump cspell from 6.21.0 to 6.22.0
2023-02-07 15:39:02 +00:00
b309d327f0 Merge pull request #1922 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-functional-5.0.4
build(deps-dev): bump eslint-plugin-functional from 5.0.1 to 5.0.4
2023-02-07 15:38:53 +00:00
58bad10bfe Merge pull request #1929 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/parser-5.51.0
build(deps-dev): bump @typescript-eslint/parser from 5.50.0 to 5.51.0
2023-02-07 15:38:46 +00:00
26ea6c518f build(deps-dev): bump @typescript-eslint/parser from 5.50.0 to 5.51.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.50.0 to 5.51.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.51.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-02-07 11:02:29 +00:00
d4594a97a2 build(deps): bump @types/node from 18.11.18 to 18.13.0
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.11.18 to 18.13.0.
- [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-02-07 11:01:04 +00:00
68f951ef79 build(deps-dev): bump eslint-plugin-jsdoc from 39.7.5 to 39.8.0
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 39.7.5 to 39.8.0.
- [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/v39.7.5...v39.8.0)

---
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-02-06 11:02:34 +00:00
12e29c6a75 build(deps-dev): bump cspell from 6.21.0 to 6.22.0
Bumps [cspell](https://github.com/streetsidesoftware/cspell) from 6.21.0 to 6.22.0.
- [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.21.0...v6.22.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 11:01:46 +00:00
05eedb2ac1 build(deps-dev): bump eslint-plugin-functional from 5.0.1 to 5.0.4
Bumps [eslint-plugin-functional](https://github.com/eslint-functional/eslint-plugin-functional) from 5.0.1 to 5.0.4.
- [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.1...v5.0.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 11:01:24 +00:00
8cbc6c15fe Fix linting 2023-02-04 23:53:37 +00:00
2c21f64b9f Remove only 2023-02-04 23:50:59 +00:00
7ec9cff433 Add tests for BuilderElement 2023-02-04 23:50:37 +00:00
3f979b9981 Remove unused code 2023-02-04 22:48:33 +00:00
3077ca96a7 Use next attribute component 2023-02-04 22:11:47 +00:00
46ded68369 Merge pull request #1919 from dolanmiu/dependabot/npm_and_yarn/cspell-6.21.0
build(deps-dev): bump cspell from 6.20.1 to 6.21.0
2023-02-03 22:06:17 +00:00
b3a53d341d build(deps-dev): bump cspell from 6.20.1 to 6.21.0
Bumps [cspell](https://github.com/streetsidesoftware/cspell) from 6.20.1 to 6.21.0.
- [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.20.1...v6.21.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-03 11:01:04 +00:00
afcd5e70a1 Upgrade eslint plugin functional 2023-02-02 17:44:12 +00:00
ae48999e38 Merge pull request #1917 from dolanmiu/dependabot/npm_and_yarn/http-cache-semantics-4.1.1
build(deps): bump http-cache-semantics from 4.1.0 to 4.1.1
2023-02-02 17:37:26 +00:00
4c38e45455 Merge pull request #1918 from dolanmiu/feature/upgrade-code-cov
Fix eslint issues
2023-02-02 17:37:17 +00:00
ec847dccf9 Fix prettier issue 2023-02-02 17:22:49 +00:00
ca47a1dc3f Merge pull request #1914 from dolanmiu/dependabot/npm_and_yarn/cspell-6.20.1
build(deps-dev): bump cspell from 6.19.2 to 6.20.1
2023-02-02 17:00:33 +00:00
cc53ff417b build(deps): bump http-cache-semantics from 4.1.0 to 4.1.1
Bumps [http-cache-semantics](https://github.com/kornelski/http-cache-semantics) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/kornelski/http-cache-semantics/releases)
- [Commits](https://github.com/kornelski/http-cache-semantics/commits)

---
updated-dependencies:
- dependency-name: http-cache-semantics
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-02 16:59:58 +00:00
fcba817a4a Fix eslint issues 2023-02-02 16:59:37 +00:00
bcd8249d17 Merge pull request #1916 from dolanmiu/feature/upgrade-code-cov
Upgrade codecov
2023-02-02 16:59:22 +00:00
bc0a197ba1 Upgrade codecov 2023-02-02 16:31:12 +00:00
2e16279d7b build(deps-dev): bump cspell from 6.19.2 to 6.20.1
Bumps [cspell](https://github.com/streetsidesoftware/cspell) from 6.19.2 to 6.20.1.
- [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.19.2...v6.20.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-02 11:01:04 +00:00
87590aedbd Merge pull request #1913 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-jsdoc-39.7.5
build(deps-dev): bump eslint-plugin-jsdoc from 39.7.4 to 39.7.5
2023-02-01 20:35:24 +00:00
0fef7763d5 build(deps-dev): bump eslint-plugin-jsdoc from 39.7.4 to 39.7.5
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 39.7.4 to 39.7.5.
- [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/v39.7.4...v39.7.5)

---
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-02-01 11:01:06 +00:00
e55698d221 Merge pull request #1910 from dolanmiu/dependabot/npm_and_yarn/typescript-4.9.5
build(deps-dev): bump typescript from 4.9.4 to 4.9.5
2023-01-31 21:22:49 +00:00
d410b5e96f Merge pull request #1907 from dolanmiu/dependabot/npm_and_yarn/eslint-8.33.0
build(deps-dev): bump eslint from 8.32.0 to 8.33.0
2023-01-31 21:22:37 +00:00
8587601411 Merge pull request #1906 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-jsdoc-39.7.4
build(deps-dev): bump eslint-plugin-jsdoc from 39.6.9 to 39.7.4
2023-01-31 21:22:28 +00:00
5b67cb21c6 Merge pull request #1909 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.50.0
build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.49.0 to 5.50.0
2023-01-31 21:22:20 +00:00
42fd9d06de Merge pull request #1911 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/parser-5.50.0
build(deps-dev): bump @typescript-eslint/parser from 5.49.0 to 5.50.0
2023-01-31 21:22:14 +00:00
1e0b74fd27 build(deps-dev): bump @typescript-eslint/parser from 5.49.0 to 5.50.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.49.0 to 5.50.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.50.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-01-31 11:02:29 +00:00
21934ec85b build(deps-dev): bump typescript from 4.9.4 to 4.9.5
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.9.4 to 4.9.5.
- [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-01-31 11:01:53 +00:00
b4f01fb6ec 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.49.0 to 5.50.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/v5.50.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>
2023-01-31 11:01:28 +00:00
fbf6329500 build(deps-dev): bump eslint from 8.32.0 to 8.33.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.32.0 to 8.33.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.32.0...v8.33.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-01-30 11:01:14 +00:00
41549443c3 build(deps-dev): bump eslint-plugin-jsdoc from 39.6.9 to 39.7.4
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 39.6.9 to 39.7.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/v39.6.9...v39.7.4)

---
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-01-30 11:00:52 +00:00
92630af4e1 Merge pull request #1905 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-jsdoc-39.6.9
build(deps-dev): bump eslint-plugin-jsdoc from 39.6.8 to 39.6.9
2023-01-27 11:12:56 +00:00
4db633da16 build(deps-dev): bump eslint-plugin-jsdoc from 39.6.8 to 39.6.9
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 39.6.8 to 39.6.9.
- [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/v39.6.8...v39.6.9)

---
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-01-27 11:01:09 +00:00
dac02f13ae Merge pull request #1901 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/parser-5.49.0
build(deps-dev): bump @typescript-eslint/parser from 5.48.2 to 5.49.0
2023-01-27 10:46:54 +00:00
1a52dec1c2 build(deps-dev): bump @typescript-eslint/parser from 5.48.2 to 5.49.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.48.2 to 5.49.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.49.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-01-27 10:27:04 +00:00
be1ca51162 Merge pull request #1900 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-jsdoc-39.6.8
build(deps-dev): bump eslint-plugin-jsdoc from 39.6.7 to 39.6.8
2023-01-27 10:26:08 +00:00
768e20bb79 Merge pull request #1902 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.49.0
build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.48.2 to 5.49.0
2023-01-27 10:25:37 +00:00
26b9b15de8 Merge pull request #1903 from dolanmiu/dependabot/npm_and_yarn/rimraf-4.1.2
build(deps-dev): bump rimraf from 4.1.1 to 4.1.2
2023-01-27 10:25:23 +00:00
42713095b6 Merge pull request #1904 from dolanmiu/dependabot/npm_and_yarn/types/prompt-1.1.5
build(deps-dev): bump @types/prompt from 1.1.4 to 1.1.5
2023-01-27 10:25:08 +00:00
3acafeca38 build(deps-dev): bump @types/prompt from 1.1.4 to 1.1.5
Bumps [@types/prompt](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/prompt) from 1.1.4 to 1.1.5.
- [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>
2023-01-26 11:00:45 +00:00
7ca75c8c5a build(deps-dev): bump rimraf from 4.1.1 to 4.1.2
Bumps [rimraf](https://github.com/isaacs/rimraf) from 4.1.1 to 4.1.2.
- [Release notes](https://github.com/isaacs/rimraf/releases)
- [Changelog](https://github.com/isaacs/rimraf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/rimraf/compare/v4.1.1...v4.1.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-24 11:02:11 +00:00
c00ad454a9 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.48.2 to 5.49.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/v5.49.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>
2023-01-24 11:01:54 +00:00
16d04eb4d3 build(deps-dev): bump eslint-plugin-jsdoc from 39.6.7 to 39.6.8
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 39.6.7 to 39.6.8.
- [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/v39.6.7...v39.6.8)

---
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-01-24 11:00:46 +00:00
816845f271 Merge pull request #1893 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-jsdoc-39.6.7
build(deps-dev): bump eslint-plugin-jsdoc from 39.6.4 to 39.6.7
2023-01-23 15:02:42 +00:00
12eeda8d33 Merge pull request #1894 from dolanmiu/dependabot/npm_and_yarn/types/glob-8.0.1
build(deps-dev): bump @types/glob from 8.0.0 to 8.0.1
2023-01-23 15:01:37 +00:00
3d622c2ef1 Merge pull request #1898 from dolanmiu/feat/strict-types-for-File-Child
Add strict types for file child
2023-01-23 15:01:03 +00:00
21a6767c6f Add strict types for file child 2023-01-23 14:14:05 +00:00
7a7326ec09 build(deps-dev): bump @types/glob from 8.0.0 to 8.0.1
Bumps [@types/glob](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/glob) from 8.0.0 to 8.0.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/glob)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-20 11:01:17 +00:00
9b3af4e217 build(deps-dev): bump eslint-plugin-jsdoc from 39.6.4 to 39.6.7
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 39.6.4 to 39.6.7.
- [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/v39.6.4...v39.6.7)

---
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-01-20 11:00:55 +00:00
cee0114f81 Merge pull request #1890 from dolanmiu/dependabot/npm_and_yarn/cspell-6.19.2
build(deps-dev): bump cspell from 6.18.1 to 6.19.2
2023-01-18 17:03:52 +00:00
03399aedf0 Merge pull request #1891 from dolanmiu/dependabot/npm_and_yarn/rimraf-4.1.1
build(deps-dev): bump rimraf from 4.1.0 to 4.1.1
2023-01-18 17:03:45 +00:00
2739b94bd8 build(deps-dev): bump rimraf from 4.1.0 to 4.1.1
Bumps [rimraf](https://github.com/isaacs/rimraf) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/isaacs/rimraf/releases)
- [Changelog](https://github.com/isaacs/rimraf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/rimraf/compare/v4.1.0...v4.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-18 11:01:15 +00:00
c720441d62 build(deps-dev): bump cspell from 6.18.1 to 6.19.2
Bumps [cspell](https://github.com/streetsidesoftware/cspell) from 6.18.1 to 6.19.2.
- [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.18.1...v6.19.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-18 11:00:58 +00:00
00b5898fe0 Merge pull request #1889 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/parser-5.48.2
build(deps-dev): bump @typescript-eslint/parser from 5.48.1 to 5.48.2
2023-01-18 04:23:15 +00:00
0d0940b7a5 Merge pull request #1888 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.48.2
build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.48.1 to 5.48.2
2023-01-18 04:23:06 +00:00
f28c949ac6 Merge pull request #1887 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-import-2.27.5
build(deps-dev): bump eslint-plugin-import from 2.27.4 to 2.27.5
2023-01-18 04:22:59 +00:00
63317d6ac8 Merge pull request #1886 from dolanmiu/dependabot/npm_and_yarn/rimraf-4.1.0
build(deps-dev): bump rimraf from 4.0.4 to 4.1.0
2023-01-18 04:22:52 +00:00
6406ba831f Merge pull request #1884 from dolanmiu/dependabot/npm_and_yarn/prettier-2.8.3
build(deps-dev): bump prettier from 2.8.2 to 2.8.3
2023-01-18 04:22:45 +00:00
7a7575964a Merge pull request #1883 from dolanmiu/dependabot/npm_and_yarn/eslint-8.32.0
build(deps-dev): bump eslint from 8.31.0 to 8.32.0
2023-01-18 04:22:37 +00:00
d75c833717 Merge pull request #1882 from dolanmiu/dependabot/npm_and_yarn/glob-8.1.0
build(deps-dev): bump glob from 8.0.3 to 8.1.0
2023-01-18 04:22:27 +00:00
40344b57d9 build(deps-dev): bump @typescript-eslint/parser from 5.48.1 to 5.48.2
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.48.1 to 5.48.2.
- [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.48.2/packages/parser)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-17 11:02:10 +00:00
6fc26d1da3 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.48.1 to 5.48.2.
- [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/v5.48.2/packages/eslint-plugin)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-17 11:01:49 +00:00
a012a0e418 build(deps-dev): bump eslint-plugin-import from 2.27.4 to 2.27.5
Bumps [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import) from 2.27.4 to 2.27.5.
- [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.4...v2.27.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-17 11:01:16 +00:00
bf1a2f3059 build(deps-dev): bump rimraf from 4.0.4 to 4.1.0
Bumps [rimraf](https://github.com/isaacs/rimraf) from 4.0.4 to 4.1.0.
- [Release notes](https://github.com/isaacs/rimraf/releases)
- [Changelog](https://github.com/isaacs/rimraf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/rimraf/compare/v4.0.4...v4.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-17 11:00:58 +00:00
ca316b4e6d build(deps-dev): bump prettier from 2.8.2 to 2.8.3
Bumps [prettier](https://github.com/prettier/prettier) from 2.8.2 to 2.8.3.
- [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/2.8.2...2.8.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 11:02:22 +00:00
1fb5c581c9 build(deps-dev): bump eslint from 8.31.0 to 8.32.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.31.0 to 8.32.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.31.0...v8.32.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-01-16 11:01:59 +00:00
efa64b451a build(deps-dev): bump glob from 8.0.3 to 8.1.0
Bumps [glob](https://github.com/isaacs/node-glob) from 8.0.3 to 8.1.0.
- [Release notes](https://github.com/isaacs/node-glob/releases)
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v8.0.3...v8.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 11:01:33 +00:00
38059ea6b9 Merge pull request #1879 from dolanmiu/dependabot/npm_and_yarn/rimraf-4.0.4
build(deps-dev): bump rimraf from 3.0.2 to 4.0.4
2023-01-15 20:23:37 +00:00
c2110622ca Merge pull request #1875 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-import-2.27.4
build(deps-dev): bump eslint-plugin-import from 2.26.0 to 2.27.4
2023-01-15 20:23:31 +00:00
0452959b85 build(deps-dev): bump rimraf from 3.0.2 to 4.0.4
Bumps [rimraf](https://github.com/isaacs/rimraf) from 3.0.2 to 4.0.4.
- [Release notes](https://github.com/isaacs/rimraf/releases)
- [Changelog](https://github.com/isaacs/rimraf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/rimraf/compare/v3.0.2...v4.0.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-13 11:00:53 +00:00
0eca8389b6 build(deps-dev): bump eslint-plugin-import from 2.26.0 to 2.27.4
Bumps [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import) from 2.26.0 to 2.27.4.
- [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.26.0...v2.27.4)

---
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>
2023-01-12 11:01:10 +00:00
66e043137b Merge pull request #1871 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.48.1
build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.48.0 to 5.48.1
2023-01-10 18:03:32 +00:00
d684654625 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.48.0 to 5.48.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/v5.48.1/packages/eslint-plugin)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-10 17:44:35 +00:00
7749f6b20f Merge pull request #1872 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/parser-5.48.1
build(deps-dev): bump @typescript-eslint/parser from 5.48.0 to 5.48.1
2023-01-10 17:43:48 +00:00
15c9c0ae3e build(deps-dev): bump @typescript-eslint/parser from 5.48.0 to 5.48.1
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.48.0 to 5.48.1.
- [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.48.1/packages/parser)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-10 11:02:06 +00:00
74fddc2ada Merge pull request #1869 from dolanmiu/dependabot/npm_and_yarn/prettier-2.8.2
build(deps-dev): bump prettier from 2.8.1 to 2.8.2
2023-01-09 18:17:01 +00:00
cff866ecdc Merge pull request #1870 from dolanmiu/dependabot/npm_and_yarn/typedoc-0.23.24
build(deps-dev): bump typedoc from 0.23.23 to 0.23.24
2023-01-09 18:16:54 +00:00
e952c02c83 build(deps-dev): bump typedoc from 0.23.23 to 0.23.24
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.23.23 to 0.23.24.
- [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.23.23...v0.23.24)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 11:01:20 +00:00
546983c6ba build(deps-dev): bump prettier from 2.8.1 to 2.8.2
Bumps [prettier](https://github.com/prettier/prettier) from 2.8.1 to 2.8.2.
- [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/2.8.1...2.8.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 11:00:50 +00:00
c7134564a3 Merge pull request #1867 from dolanmiu/dependabot/npm_and_yarn/json5-1.0.2
build(deps): bump json5 from 1.0.1 to 1.0.2
2023-01-06 16:47:05 +00:00
984a3573eb build(deps): bump json5 from 1.0.1 to 1.0.2
Bumps [json5](https://github.com/json5/json5) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v1.0.1...v1.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-05 22:29:30 +00:00
defe94a2b2 Merge pull request #1865 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.48.0
build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.46.1 to 5.48.0
2023-01-05 22:29:13 +00:00
e23c8c4b46 Merge pull request #1864 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/parser-5.48.0
build(deps-dev): bump @typescript-eslint/parser from 5.46.1 to 5.48.0
2023-01-05 22:29:06 +00:00
7941ff487a Merge pull request #1863 from dolanmiu/dependabot/npm_and_yarn/tsconfig-paths-4.1.2
build(deps-dev): bump tsconfig-paths from 4.1.1 to 4.1.2
2023-01-05 22:28:54 +00:00
7b7df33a0f Merge pull request #1862 from dolanmiu/dependabot/npm_and_yarn/eslint-8.31.0
build(deps-dev): bump eslint from 8.30.0 to 8.31.0
2023-01-05 22:28:47 +00:00
68b04f2511 Merge pull request #1860 from dolanmiu/dependabot/npm_and_yarn/cspell-6.18.1
build(deps-dev): bump cspell from 6.17.0 to 6.18.1
2023-01-05 22:28:37 +00:00
db3e017a7d Merge pull request #1854 from dolanmiu/dependabot/npm_and_yarn/types/node-18.11.18
build(deps): bump @types/node from 18.11.17 to 18.11.18
2023-01-05 22:28:30 +00:00
c21d45a79e Merge pull request #1859 from dolanmiu/feat/more-run-props
Add more run properties and Universal measure
2023-01-05 22:28:18 +00:00
6defb686bb Remove unessesary checks for values 2023-01-05 21:39:46 +00:00
f68796dae1 build(deps): bump @types/node from 18.11.17 to 18.11.18
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.11.17 to 18.11.18.
- [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-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-05 14:19:14 +00:00
b1872bcb95 Merge pull request #1866 from dolanmiu/hot-fix/return-constructor-value
Fix more empty return values
2023-01-05 14:18:11 +00:00
3006f4d2c1 Version bump 2023-01-05 00:25:31 +00:00
7f88a38219 Fix more empty return values 2023-01-04 22:45:27 +00:00
aeb2487c70 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.46.1 to 5.48.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/v5.48.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>
2023-01-03 11:01:20 +00:00
e42e50dd39 build(deps-dev): bump @typescript-eslint/parser from 5.46.1 to 5.48.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.46.1 to 5.48.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.48.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-01-03 11:00:40 +00:00
f4572b9720 build(deps-dev): bump tsconfig-paths from 4.1.1 to 4.1.2
Bumps [tsconfig-paths](https://github.com/dividab/tsconfig-paths) from 4.1.1 to 4.1.2.
- [Release notes](https://github.com/dividab/tsconfig-paths/releases)
- [Changelog](https://github.com/dividab/tsconfig-paths/blob/master/CHANGELOG.md)
- [Commits](https://github.com/dividab/tsconfig-paths/compare/v4.1.1...v4.1.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-02 11:01:07 +00:00
7646f3a845 build(deps-dev): bump eslint from 8.30.0 to 8.31.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.30.0 to 8.31.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.30.0...v8.31.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-01-02 11:00:57 +00:00
e4e5b1e4f6 Merge pull request #1861 from dolanmiu/hot-fix/return-constructor-value
Hot fix/return constructor value
2022-12-30 16:40:35 +00:00
a481518470 Version bump 2022-12-30 16:21:00 +00:00
2435ebf16e Correctly return value from constructor 2022-12-30 16:16:59 +00:00
414fa70e5d build(deps-dev): bump cspell from 6.17.0 to 6.18.1
Bumps [cspell](https://github.com/streetsidesoftware/cspell) from 6.17.0 to 6.18.1.
- [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.17.0...v6.18.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-30 11:00:49 +00:00
f255d4c141 Fix tests 2022-12-29 12:12:53 +00:00
4513bb529b Add more run properties and Universal measure 2022-12-29 09:57:15 +00:00
5907132062 Merge pull request #1853 from dolanmiu/feat/hyperlink-images
#1699 Allow images to work with Hyperlink
2022-12-26 15:42:02 +00:00
69bf313f18 Remove module tsconfig 2022-12-26 15:16:01 +00:00
fe8b0a6b2b #1699 Allow images to work with Hyperlink
Add stack to IContext for prepForXml
2022-12-26 15:12:44 +00:00
abcfd79f2f Merge pull request #1845 from dolanmiu/dependabot/npm_and_yarn/typedoc-0.23.23
build(deps-dev): bump typedoc from 0.23.22 to 0.23.23
2022-12-24 21:03:07 +00:00
41e3b078ec Merge pull request #1844 from dolanmiu/dependabot/npm_and_yarn/types/node-18.11.17
build(deps): bump @types/node from 18.11.15 to 18.11.17
2022-12-24 21:03:00 +00:00
4eb2f92c1f Merge pull request #1843 from dolanmiu/dependabot/npm_and_yarn/eslint-8.30.0
build(deps-dev): bump eslint from 8.29.0 to 8.30.0
2022-12-24 21:02:53 +00:00
9bfb5bf681 Merge pull request #1852 from dolanmiu/feat/positional-tab
#940 - Add positional tab feature
2022-12-24 21:02:44 +00:00
473ad2947c Remove demo 2022-12-24 20:30:35 +00:00
ee28f6ad84 Revert demo 75 2022-12-24 19:49:13 +00:00
11bebd42ac #940 - Add positional tab feature
Also add extra run elements as per spec
2022-12-24 19:32:44 +00:00
49b4ca67e0 Merge pull request #1848 from dolanmiu/feat/refactoring
Different Language support
2022-12-21 04:38:38 +00:00
3282f762df Add language support 2022-12-20 21:42:26 +00:00
d335106b46 build(deps-dev): bump typedoc from 0.23.22 to 0.23.23
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.23.22 to 0.23.23.
- [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.23.22...v0.23.23)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-19 11:01:42 +00:00
cefa01f7ec build(deps): bump @types/node from 18.11.15 to 18.11.17
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.11.15 to 18.11.17.
- [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-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-19 11:01:19 +00:00
b7ba2b3306 build(deps-dev): bump eslint from 8.29.0 to 8.30.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.29.0 to 8.30.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.29.0...v8.30.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-19 11:00:46 +00:00
03d5152e7c Add BuilderElement and lang 2022-12-18 00:52:29 +00:00
af3b7f2613 Remove unused method 2022-12-17 19:39:27 +00:00
1405841565 Merge pull request #1839 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.46.1
build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.46.0 to 5.46.1
2022-12-16 23:39:45 +00:00
211d2dc0d6 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.46.0 to 5.46.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/v5.46.1/packages/eslint-plugin)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-16 16:21:09 +00:00
82f431465f Merge pull request #1841 from dolanmiu/dependabot/npm_and_yarn/types/node-18.11.15
build(deps): bump @types/node from 18.11.13 to 18.11.15
2022-12-16 16:20:12 +00:00
247afe56ce Merge pull request #1838 from dolanmiu/dependabot/npm_and_yarn/typescript-eslint/parser-5.46.1
build(deps-dev): bump @typescript-eslint/parser from 5.46.0 to 5.46.1
2022-12-16 16:19:53 +00:00
91e874eee5 Merge pull request #1837 from dolanmiu/dependabot/npm_and_yarn/eslint-plugin-unicorn-45.0.2
build(deps-dev): bump eslint-plugin-unicorn from 45.0.1 to 45.0.2
2022-12-16 16:19:46 +00:00
ff67c3660b Merge pull request #1842 from dolanmiu/dependabot/npm_and_yarn/sinon-15.0.1
build(deps-dev): bump sinon from 15.0.0 to 15.0.1
2022-12-16 16:19:35 +00:00
58c580b9ca build(deps-dev): bump sinon from 15.0.0 to 15.0.1
Bumps [sinon](https://github.com/sinonjs/sinon) from 15.0.0 to 15.0.1.
- [Release notes](https://github.com/sinonjs/sinon/releases)
- [Changelog](https://github.com/sinonjs/sinon/blob/main/docs/changelog.md)
- [Commits](https://github.com/sinonjs/sinon/compare/v15.0.0...v15.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-16 11:01:13 +00:00
a9da151026 Add examples for continuous headers
Add different headers for different sections
2022-12-16 00:27:04 +00:00
83c72d0dbb build(deps): bump @types/node from 18.11.13 to 18.11.15
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.11.13 to 18.11.15.
- [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-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-14 11:01:06 +00:00
2c31367851 build(deps-dev): bump @typescript-eslint/parser from 5.46.0 to 5.46.1
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.46.0 to 5.46.1.
- [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.46.1/packages/parser)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-13 11:01:16 +00:00
3b618f3a2c build(deps-dev): bump eslint-plugin-unicorn from 45.0.1 to 45.0.2
Bumps [eslint-plugin-unicorn](https://github.com/sindresorhus/eslint-plugin-unicorn) from 45.0.1 to 45.0.2.
- [Release notes](https://github.com/sindresorhus/eslint-plugin-unicorn/releases)
- [Commits](https://github.com/sindresorhus/eslint-plugin-unicorn/compare/v45.0.1...v45.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-13 11:00:47 +00:00
4c5bc6232d Merge pull request #1834 from dolanmiu/dependabot/npm_and_yarn/typedoc-0.23.22
build(deps-dev): bump typedoc from 0.23.21 to 0.23.22
2022-12-12 11:14:53 +00:00
694835bdac Merge pull request #1835 from dolanmiu/dependabot/npm_and_yarn/mocha-10.2.0
build(deps-dev): bump mocha from 10.1.0 to 10.2.0
2022-12-12 11:14:46 +00:00
c8b75c19da Merge pull request #1836 from dolanmiu/dependabot/npm_and_yarn/types/node-18.11.13
build(deps): bump @types/node from 18.11.12 to 18.11.13
2022-12-12 11:12:18 +00:00
c0181aa83a build(deps): bump @types/node from 18.11.12 to 18.11.13
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.11.12 to 18.11.13.
- [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-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 11:01:25 +00:00
c5b615ae2a build(deps-dev): bump mocha from 10.1.0 to 10.2.0
Bumps [mocha](https://github.com/mochajs/mocha) from 10.1.0 to 10.2.0.
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v10.1.0...v10.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 11:01:04 +00:00
54cbd56f42 build(deps-dev): bump typedoc from 0.23.21 to 0.23.22
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.23.21 to 0.23.22.
- [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.23.21...v0.23.22)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 11:00:46 +00:00
c8914a109e Merge pull request #1823 from anti-the-social/overrideLevels-impl
Override levels impl
2022-12-10 23:15:39 +00:00
8509bccc4f Fix comment tests to support testing in different time zones 2022-12-10 13:06:22 +02:00
4ce53a3d76 Fix failing test 2022-12-10 12:47:48 +02:00
ec69f9ac07 Downgrade nanoid 2022-12-09 21:56:50 +00:00
5a4fe5d5da Formatting applied 2022-12-07 23:03:42 +02:00
e6af9b4b73 fix for tests && new tests for multi-level cases 2022-12-07 22:55:15 +02:00
361f9231d8 default numbering with overrideLevels 2022-12-07 22:54:51 +02:00
4215932550 overrideLevels as array impl instead of overrideLevel 2022-12-07 22:54:26 +02:00
29da523579 Interface (overrideLevel -> overrideLevels)
Breaking change
2022-12-07 22:11:34 +02:00
fbb4d7cfde Merge pull request #9 from dolanmiu/master
Upd to latest version of docx js
2022-12-07 21:58:14 +02:00
323895f0ab Merge remote-tracking branch 'upstream/master' 2022-11-21 21:25:36 +02:00
32a5cca878 Upd version, include security fix into package 2022-10-14 11:45:53 +03:00
911c705b59 Security fix via npm audit 2022-10-14 11:42:59 +03:00
594c8d72b8 Upd nanoid to v4 2022-10-14 11:09:51 +03:00
7ea5232b22 Changing name&version 2022-10-14 11:05:46 +03:00
be12d61795 Merge remote-tracking branch 'upstream/master' 2022-10-13 13:00:55 +03:00
925340eb3d Adjusting name and version for publishing (old one) 2022-10-13 11:45:21 +03:00
601a4038f4 Merge pull request #6 from dolanmiu/master
Update from Dolan's master
2022-09-16 15:24:38 +03:00
e0576c889b Merge pull request #5 from dolanmiu/master
Upd to latest Dolan master
2022-06-29 16:37:28 +03:00
4ff7f0a7bd Merge pull request #4 from dolanmiu/master
Merge latest changes from Dolans master (V7)
2022-05-16 11:42:13 +03:00
119 changed files with 7656 additions and 2609 deletions

View File

@ -47,7 +47,9 @@
"/xmlKeys = {[^}]+}/g", "/xmlKeys = {[^}]+}/g",
"/\\.to\\.deep\\.equal\\({[^)]+}\\)/g", "/\\.to\\.deep\\.equal\\({[^)]+}\\)/g",
"\\.to\\.include\\.members\\(\\[[^\\]]+]\\)", "\\.to\\.include\\.members\\(\\[[^\\]]+]\\)",
"/new [a-zA-Z]+\\({[^£]+}\\)/g" "/new [a-zA-Z]+\\({[^£]+}\\)/g",
"/<element name=\"[a-z]+\"/gi",
"/<attribute name=\"[a-z]+\"/gi"
], ],
"ignorePaths": ["package.json", "docs/api"], "ignorePaths": ["package.json", "docs/api"],
"allowCompoundWords": true, "allowCompoundWords": true,

View File

@ -96,8 +96,8 @@ module.exports = {
"@typescript-eslint/explicit-function-return-type": [ "@typescript-eslint/explicit-function-return-type": [
"error", "error",
{ {
allowExpressions: false, allowExpressions: true,
allowTypedFunctionExpressions: false, allowTypedFunctionExpressions: true,
allowHigherOrderFunctions: false, allowHigherOrderFunctions: false,
allowDirectConstAssertionInArrowFunctions: true, allowDirectConstAssertionInArrowFunctions: true,
allowConciseArrowFunctionExpressionsStartingWithVoid: true, allowConciseArrowFunctionExpressionsStartingWithVoid: true,
@ -214,7 +214,6 @@ module.exports = {
"no-sequences": "error", "no-sequences": "error",
"no-shadow": "off", "no-shadow": "off",
"no-sparse-arrays": "error", "no-sparse-arrays": "error",
"no-template-curly-in-string": "error",
"no-throw-literal": "error", "no-throw-literal": "error",
"no-trailing-spaces": "error", "no-trailing-spaces": "error",
"no-undef-init": "error", "no-undef-init": "error",
@ -243,7 +242,6 @@ module.exports = {
"unicorn/prefer-ternary": "error", "unicorn/prefer-ternary": "error",
"use-isnan": "error", "use-isnan": "error",
"valid-typeof": "off", "valid-typeof": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"functional/immutable-data": [ "functional/immutable-data": [
"error", "error",
{ {
@ -252,9 +250,12 @@ module.exports = {
ignoreAccessorPattern: ["**.root*", "**.numberingReferences*", "**.sections*", "**.properties*"], ignoreAccessorPattern: ["**.root*", "**.numberingReferences*", "**.sections*", "**.properties*"],
}, },
], ],
"functional/no-method-signature": "error", "functional/prefer-property-signatures": "error",
"functional/no-mixed-type": "error", "functional/no-mixed-types": "error",
// TODO: Deprecated. Use prefer-immutable-types and type-declaration-immutability instead
"functional/prefer-readonly-type": "error", "functional/prefer-readonly-type": "error",
// "functional/prefer-immutable-types": "error",
// "functional/type-declaration-immutability": "error",
"no-unused-vars": ["error", { argsIgnorePattern: "^[_]+$" }], "no-unused-vars": ["error", { argsIgnorePattern: "^[_]+$" }],
}, },
overrides: [ overrides: [
@ -264,6 +265,7 @@ module.exports = {
"@typescript-eslint/no-unused-expressions": "off", "@typescript-eslint/no-unused-expressions": "off",
"@typescript-eslint/dot-notation": "off", "@typescript-eslint/dot-notation": "off",
"prefer-destructuring": "off", "prefer-destructuring": "off",
"@typescript-eslint/explicit-function-return-type": "off",
}, },
}, },
], ],

View File

@ -34,7 +34,7 @@ jobs:
- name: Test - name: Test
run: npm run test.coverage run: npm run test.coverage
- name: Codecov - name: Codecov
uses: codecov/codecov-action@v1 uses: codecov/codecov-action@v3
with: with:
fail_ci_if_error: true fail_ci_if_error: true
verbose: true verbose: true

View File

@ -301,15 +301,6 @@ jobs:
with: with:
xml-file: build/extracted-doc/word/document.xml xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
- name: Run Demo
run: npm run ts-node -- ./demo/30-template-document.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 - name: Run Demo
run: npm run ts-node -- ./demo/31-tables.ts run: npm run ts-node -- ./demo/31-tables.ts
- name: Extract Word Document - name: Extract Word Document
@ -716,3 +707,93 @@ jobs:
with: with:
xml-file: build/extracted-doc/word/document.xml xml-file: build/extracted-doc/word/document.xml
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd 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

View File

@ -41,3 +41,6 @@ build-tests
# docs # docs
docs docs
# src
src

6
.nycrc
View File

@ -1,9 +1,9 @@
{ {
"check-coverage": true, "check-coverage": true,
"statements": 99.79, "statements": 99.87,
"branches": 98.41, "branches": 98.29,
"functions": 100, "functions": 100,
"lines": 99.73, "lines": 99.86,
"include": [ "include": [
"src/**/*.ts" "src/**/*.ts"
], ],

18
.vscode/launch.json vendored Normal file
View File

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

View File

@ -3,7 +3,7 @@
</p> </p>
<p align="center"> <p align="center">
Easily generate .docx files with JS/TS. Works for Node and on the Browser. Easily generate and modify .docx files with JS/TS. Works for Node and on the Browser.
</p> </p>
--- ---
@ -88,6 +88,7 @@ Read the contribution guidelines [here](https://docx.js.org/#/contribution-guide
[<img src="https://i.imgur.com/cmykN7c.png" alt="drawing"/>](https://www.arity.co/) [<img src="https://i.imgur.com/cmykN7c.png" alt="drawing"/>](https://www.arity.co/)
[<img src="https://i.imgur.com/PXo25um.png" alt="drawing" height="50"/>](https://www.circadianrisk.com/) [<img src="https://i.imgur.com/PXo25um.png" alt="drawing" height="50"/>](https://www.circadianrisk.com/)
[<img src="https://i.imgur.com/AKGhtlh.png" alt="drawing"/>](https://lexense.com/) [<img src="https://i.imgur.com/AKGhtlh.png" alt="drawing"/>](https://lexense.com/)
[<img src="https://i.imgur.com/9tqJaHw.png" alt="drawing" height="50"/>](https://novelpad.co/)
...and many more! ...and many more!

View File

@ -1,35 +0,0 @@
// Example on how to use a template document
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, ImportDotx, Packer, Paragraph } from "../build";
const importDotx = new ImportDotx();
const filePath = "./demo/dotx/template.dotx";
fs.readFile(filePath, (err, data) => {
if (err) {
throw new Error(`Failed to read file ${filePath}.`);
}
importDotx.extract(data).then((templateDocument) => {
const doc = new Document(
{
sections: [
{
properties: {
titlePage: templateDocument.titlePageIsDefined,
},
children: [new Paragraph("Hello World")],
},
],
},
{
template: templateDocument,
},
);
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});
});
});

View File

@ -5,7 +5,34 @@ import { Document, Packer, Paragraph, TextRun, CommentRangeStart, CommentRangeEn
const doc = new Document({ const doc = new Document({
comments: { comments: {
children: [{ id: 0, author: "Ray Chen", date: new Date(), text: "comment text content" }], children: [
{
id: 0,
author: "Ray Chen",
date: new Date(),
children: [
new Paragraph({
children: [
new TextRun({
text: "some initial text content",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "comment text content",
}),
new TextRun({ text: "", break: 1 }),
new TextRun({
text: "More text here",
bold: true,
}),
],
}),
],
},
],
}, },
sections: [ sections: [
{ {

View File

@ -1,4 +1,4 @@
// Exporting the document as a stream // Example of using tab stops
// Import from 'docx' rather than '../build' if you install from npm // Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs"; import * as fs from "fs";
import { Document, HeadingLevel, Packer, Paragraph, TabStopPosition, TabStopType, TextRun } from "../build"; import { Document, HeadingLevel, Packer, Paragraph, TabStopPosition, TabStopType, TextRun } from "../build";

View File

@ -0,0 +1,148 @@
// Example of a continuous header
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Footer, Header, Packer, Paragraph, SectionType, Tab, TextRun } from "../build";
const doc = new Document({
creator: "Creator",
title: "Title",
sections: [
{
properties: { titlePage: true },
headers: {
first: new Header({
children: [
new Paragraph({
children: [
new TextRun({
text: "HEADER PAGE ONE",
}),
],
}),
],
}),
default: new Header({
children: [
new Paragraph({
children: [
new TextRun({
text: "HEADER PAGE TWO AND FOLLOWING PAGES",
}),
],
}),
],
}),
},
footers: {
first: new Footer({
children: [
new Paragraph({
children: [
new TextRun({
text: "FOOTER PAGE ONE",
}),
],
}),
],
}),
default: new Footer({
children: [
new Paragraph({
children: [
new TextRun({
text: "FOOTER PAGE TWO AND FOLLOWING PAGES",
}),
],
}),
],
}),
},
children: [
new Paragraph({
children: [
new TextRun({
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer ac suscipit orci, in lobortis risus. Nulla vehicula rutrum finibus. Nullam consequat, magna in vehicula commodo, enim massa consectetur nisl, sit amet rutrum nunc ante vel lorem. Sed sit amet scelerisque velit. Proin non quam eget mauris aliquet posuere a sed orci. Proin posuere ante suscipit neque dignissim hendrerit. Pellentesque eget dapibus metus. Donec at mollis mauris. Vestibulum sit amet scelerisque nulla. Vivamus ipsum erat, tempor sed volutpat non, molestie at odio. Vivamus lectus ligula, finibus at mattis vitae, euismod sed tellus. Etiam neque massa, faucibus a fringilla nec, mollis at ex. Aliquam eget nibh tortor. Sed ut viverra libero. Nulla facilisis bibendum quam eget porttitor.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "Sed eget nunc ac turpis facilisis volutpat. Duis eget arcu vitae neque porta hendrerit. Proin vel ante nulla. Duis congue efficitur dui. Suspendisse potenti. Aliquam aliquam nibh eu ipsum sagittis efficitur. Quisque sagittis metus dui, vitae suscipit tortor sollicitudin at. Suspendisse convallis, sem ac ornare condimentum, odio ipsum dapibus justo, a aliquam risus massa ut enim. Mauris vel placerat nibh. Ut iaculis vitae nibh at elementum. Quisque hendrerit et magna vitae mollis. Duis dictum euismod leo, at cursus risus sodales sed.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "Sed gravida commodo felis, at aliquet risus volutpat ut. Nam nec ex eleifend tellus sodales volutpat nec ac nibh. Vestibulum pretium, leo vitae lobortis accumsan, urna libero euismod ante, consequat aliquam enim risus id nisl. Donec sagittis, justo eu luctus posuere, leo purus pellentesque turpis, eget volutpat mi leo vitae lacus. Etiam ante ante, posuere at augue non, lacinia ornare purus. Praesent vitae velit in enim congue maximus. Vivamus tincidunt fringilla neque. Curabitur fermentum justo nec sapien porttitor, ac ullamcorper nisi imperdiet. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed non orci vel eros egestas eleifend sit amet a diam. Duis mattis at ligula quis faucibus. Donec elementum lacus velit, a vehicula nunc gravida a. Phasellus eget nunc vehicula, varius velit a, maximus velit. Sed a suscipit nisi, non hendrerit felis. Proin mattis facilisis massa, quis elementum neque fringilla non.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "Sed gravida commodo felis, at aliquet risus volutpat ut. Nam nec ex eleifend tellus sodales volutpat nec ac nibh. Vestibulum pretium, leo vitae lobortis accumsan, urna libero euismod ante, consequat aliquam enim risus id nisl. Donec sagittis, justo eu luctus posuere, leo purus pellentesque turpis, eget volutpat mi leo vitae lacus. Etiam ante ante, posuere at augue non, lacinia ornare purus. Praesent vitae velit in enim congue maximus. Vivamus tincidunt fringilla neque. Curabitur fermentum justo nec sapien porttitor, ac ullamcorper nisi imperdiet. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed non orci vel eros egestas eleifend sit amet a diam. Duis mattis at ligula quis faucibus. Donec elementum lacus velit, a vehicula nunc gravida a. Phasellus eget nunc vehicula, varius velit a, maximus velit. Sed a suscipit nisi, non hendrerit felis. Proin mattis facilisis massa, quis elementum neque fringilla non.",
}),
],
}),
new Paragraph({
spacing: {
after: 500,
},
children: [
new TextRun({
text: "The first section ends after this paragraph.",
}),
],
}),
],
},
{
properties: {
type: SectionType.CONTINUOUS,
},
children: [
new Paragraph({
children: [
new TextRun({
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer ac suscipit orci, in lobortis risus. Nulla vehicula rutrum finibus. Nullam consequat, magna in vehicula commodo, enim massa consectetur nisl, sit amet rutrum nunc ante vel lorem. Sed sit amet scelerisque velit. Proin non quam eget mauris aliquet posuere a sed orci. Proin posuere ante suscipit neque dignissim hendrerit. Pellentesque eget dapibus metus. Donec at mollis mauris. Vestibulum sit amet scelerisque nulla. Vivamus ipsum erat, tempor sed volutpat non, molestie at odio. Vivamus lectus ligula, finibus at mattis vitae, euismod sed tellus. Etiam neque massa, faucibus a fringilla nec, mollis at ex. Aliquam eget nibh tortor. Sed ut viverra libero. Nulla facilisis bibendum quam eget porttitor.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "Sed eget nunc ac turpis facilisis volutpat. Duis eget arcu vitae neque porta hendrerit. Proin vel ante nulla. Duis congue efficitur dui. Suspendisse potenti. Aliquam aliquam nibh eu ipsum sagittis efficitur. Quisque sagittis metus dui, vitae suscipit tortor sollicitudin at. Suspendisse convallis, sem ac ornare condimentum, odio ipsum dapibus justo, a aliquam risus massa ut enim. Mauris vel placerat nibh. Ut iaculis vitae nibh at elementum. Quisque hendrerit et magna vitae mollis. Duis dictum euismod leo, at cursus risus sodales sed.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "Sed gravida commodo felis, at aliquet risus volutpat ut. Nam nec ex eleifend tellus sodales volutpat nec ac nibh. Vestibulum pretium, leo vitae lobortis accumsan, urna libero euismod ante, consequat aliquam enim risus id nisl. Donec sagittis, justo eu luctus posuere, leo purus pellentesque turpis, eget volutpat mi leo vitae lacus. Etiam ante ante, posuere at augue non, lacinia ornare purus. Praesent vitae velit in enim congue maximus. Vivamus tincidunt fringilla neque. Curabitur fermentum justo nec sapien porttitor, ac ullamcorper nisi imperdiet. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed non orci vel eros egestas eleifend sit amet a diam. Duis mattis at ligula quis faucibus. Donec elementum lacus velit, a vehicula nunc gravida a. Phasellus eget nunc vehicula, varius velit a, maximus velit. Sed a suscipit nisi, non hendrerit felis. Proin mattis facilisis massa, quis elementum neque fringilla non.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "Sed gravida commodo felis, at aliquet risus volutpat ut. Nam nec ex eleifend tellus sodales volutpat nec ac nibh. Vestibulum pretium, leo vitae lobortis accumsan, urna libero euismod ante, consequat aliquam enim risus id nisl. Donec sagittis, justo eu luctus posuere, leo purus pellentesque turpis, eget volutpat mi leo vitae lacus. Etiam ante ante, posuere at augue non, lacinia ornare purus. Praesent vitae velit in enim congue maximus. Vivamus tincidunt fringilla neque. Curabitur fermentum justo nec sapien porttitor, ac ullamcorper nisi imperdiet. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed non orci vel eros egestas eleifend sit amet a diam. Duis mattis at ligula quis faucibus. Donec elementum lacus velit, a vehicula nunc gravida a. Phasellus eget nunc vehicula, varius velit a, maximus velit. Sed a suscipit nisi, non hendrerit felis. Proin mattis facilisis massa, quis elementum neque fringilla non.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "The second section starts with the headline above. Move cursor to the end of this text and press enter until next page is generated in continuous section break mode.",
}),
],
}),
],
},
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,148 @@
// Example of using headers and footers in a new section
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Footer, Header, Packer, Paragraph, SectionType, Tab, TextRun } from "../build";
const doc = new Document({
creator: "Creator",
title: "Title",
sections: [
{
headers: {
default: new Header({
children: [
new Paragraph({
children: [
new TextRun({
text: "HEADER PAGE ONE",
}),
],
}),
],
}),
},
footers: {
default: new Footer({
children: [
new Paragraph({
children: [
new TextRun({
text: "FOOTER PAGE ONE",
}),
],
}),
],
}),
},
children: [
new Paragraph({
children: [
new TextRun({
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer ac suscipit orci, in lobortis risus. Nulla vehicula rutrum finibus. Nullam consequat, magna in vehicula commodo, enim massa consectetur nisl, sit amet rutrum nunc ante vel lorem. Sed sit amet scelerisque velit. Proin non quam eget mauris aliquet posuere a sed orci. Proin posuere ante suscipit neque dignissim hendrerit. Pellentesque eget dapibus metus. Donec at mollis mauris. Vestibulum sit amet scelerisque nulla. Vivamus ipsum erat, tempor sed volutpat non, molestie at odio. Vivamus lectus ligula, finibus at mattis vitae, euismod sed tellus. Etiam neque massa, faucibus a fringilla nec, mollis at ex. Aliquam eget nibh tortor. Sed ut viverra libero. Nulla facilisis bibendum quam eget porttitor.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "Sed eget nunc ac turpis facilisis volutpat. Duis eget arcu vitae neque porta hendrerit. Proin vel ante nulla. Duis congue efficitur dui. Suspendisse potenti. Aliquam aliquam nibh eu ipsum sagittis efficitur. Quisque sagittis metus dui, vitae suscipit tortor sollicitudin at. Suspendisse convallis, sem ac ornare condimentum, odio ipsum dapibus justo, a aliquam risus massa ut enim. Mauris vel placerat nibh. Ut iaculis vitae nibh at elementum. Quisque hendrerit et magna vitae mollis. Duis dictum euismod leo, at cursus risus sodales sed.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "Sed gravida commodo felis, at aliquet risus volutpat ut. Nam nec ex eleifend tellus sodales volutpat nec ac nibh. Vestibulum pretium, leo vitae lobortis accumsan, urna libero euismod ante, consequat aliquam enim risus id nisl. Donec sagittis, justo eu luctus posuere, leo purus pellentesque turpis, eget volutpat mi leo vitae lacus. Etiam ante ante, posuere at augue non, lacinia ornare purus. Praesent vitae velit in enim congue maximus. Vivamus tincidunt fringilla neque. Curabitur fermentum justo nec sapien porttitor, ac ullamcorper nisi imperdiet. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed non orci vel eros egestas eleifend sit amet a diam. Duis mattis at ligula quis faucibus. Donec elementum lacus velit, a vehicula nunc gravida a. Phasellus eget nunc vehicula, varius velit a, maximus velit. Sed a suscipit nisi, non hendrerit felis. Proin mattis facilisis massa, quis elementum neque fringilla non.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "Sed gravida commodo felis, at aliquet risus volutpat ut. Nam nec ex eleifend tellus sodales volutpat nec ac nibh. Vestibulum pretium, leo vitae lobortis accumsan, urna libero euismod ante, consequat aliquam enim risus id nisl. Donec sagittis, justo eu luctus posuere, leo purus pellentesque turpis, eget volutpat mi leo vitae lacus. Etiam ante ante, posuere at augue non, lacinia ornare purus. Praesent vitae velit in enim congue maximus. Vivamus tincidunt fringilla neque. Curabitur fermentum justo nec sapien porttitor, ac ullamcorper nisi imperdiet. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed non orci vel eros egestas eleifend sit amet a diam. Duis mattis at ligula quis faucibus. Donec elementum lacus velit, a vehicula nunc gravida a. Phasellus eget nunc vehicula, varius velit a, maximus velit. Sed a suscipit nisi, non hendrerit felis. Proin mattis facilisis massa, quis elementum neque fringilla non.",
}),
],
}),
new Paragraph({
spacing: {
after: 500,
},
children: [
new TextRun({
text: "The first section ends after this paragraph.",
}),
],
}),
],
},
{
headers: {
default: new Header({
children: [
new Paragraph({
children: [
new TextRun({
text: "HEADER PAGE TWO AND FOLLOWING PAGES",
}),
],
}),
],
}),
},
footers: {
default: new Footer({
children: [
new Paragraph({
children: [
new TextRun({
text: "FOOTER PAGE TWO AND FOLLOWING PAGES",
}),
],
}),
],
}),
},
children: [
new Paragraph({
children: [
new TextRun({
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer ac suscipit orci, in lobortis risus. Nulla vehicula rutrum finibus. Nullam consequat, magna in vehicula commodo, enim massa consectetur nisl, sit amet rutrum nunc ante vel lorem. Sed sit amet scelerisque velit. Proin non quam eget mauris aliquet posuere a sed orci. Proin posuere ante suscipit neque dignissim hendrerit. Pellentesque eget dapibus metus. Donec at mollis mauris. Vestibulum sit amet scelerisque nulla. Vivamus ipsum erat, tempor sed volutpat non, molestie at odio. Vivamus lectus ligula, finibus at mattis vitae, euismod sed tellus. Etiam neque massa, faucibus a fringilla nec, mollis at ex. Aliquam eget nibh tortor. Sed ut viverra libero. Nulla facilisis bibendum quam eget porttitor.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "Sed eget nunc ac turpis facilisis volutpat. Duis eget arcu vitae neque porta hendrerit. Proin vel ante nulla. Duis congue efficitur dui. Suspendisse potenti. Aliquam aliquam nibh eu ipsum sagittis efficitur. Quisque sagittis metus dui, vitae suscipit tortor sollicitudin at. Suspendisse convallis, sem ac ornare condimentum, odio ipsum dapibus justo, a aliquam risus massa ut enim. Mauris vel placerat nibh. Ut iaculis vitae nibh at elementum. Quisque hendrerit et magna vitae mollis. Duis dictum euismod leo, at cursus risus sodales sed.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "Sed gravida commodo felis, at aliquet risus volutpat ut. Nam nec ex eleifend tellus sodales volutpat nec ac nibh. Vestibulum pretium, leo vitae lobortis accumsan, urna libero euismod ante, consequat aliquam enim risus id nisl. Donec sagittis, justo eu luctus posuere, leo purus pellentesque turpis, eget volutpat mi leo vitae lacus. Etiam ante ante, posuere at augue non, lacinia ornare purus. Praesent vitae velit in enim congue maximus. Vivamus tincidunt fringilla neque. Curabitur fermentum justo nec sapien porttitor, ac ullamcorper nisi imperdiet. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed non orci vel eros egestas eleifend sit amet a diam. Duis mattis at ligula quis faucibus. Donec elementum lacus velit, a vehicula nunc gravida a. Phasellus eget nunc vehicula, varius velit a, maximus velit. Sed a suscipit nisi, non hendrerit felis. Proin mattis facilisis massa, quis elementum neque fringilla non.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "Sed gravida commodo felis, at aliquet risus volutpat ut. Nam nec ex eleifend tellus sodales volutpat nec ac nibh. Vestibulum pretium, leo vitae lobortis accumsan, urna libero euismod ante, consequat aliquam enim risus id nisl. Donec sagittis, justo eu luctus posuere, leo purus pellentesque turpis, eget volutpat mi leo vitae lacus. Etiam ante ante, posuere at augue non, lacinia ornare purus. Praesent vitae velit in enim congue maximus. Vivamus tincidunt fringilla neque. Curabitur fermentum justo nec sapien porttitor, ac ullamcorper nisi imperdiet. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed non orci vel eros egestas eleifend sit amet a diam. Duis mattis at ligula quis faucibus. Donec elementum lacus velit, a vehicula nunc gravida a. Phasellus eget nunc vehicula, varius velit a, maximus velit. Sed a suscipit nisi, non hendrerit felis. Proin mattis facilisis massa, quis elementum neque fringilla non.",
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: "The second section starts with the headline above. Move cursor to the end of this text and press enter until next page is generated in continuous section break mode.",
}),
],
}),
],
},
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,69 @@
// Simple example to add text to a document
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer, Paragraph } from "../build";
const doc = new Document({
styles: {
default: {
document: {
run: {
color: "ff0000",
language: {
value: "es-ES",
},
},
},
},
paragraphStyles: [
{
id: "frenchNormal",
name: "French Normal",
basedOn: "Normal",
next: "Normal",
run: {
color: "999999",
italics: true,
language: {
value: "fr-FR",
},
},
},
{
id: "koreanNormal",
name: "Korean Normal",
basedOn: "Normal",
next: "Normal",
run: {
color: "0000ff",
bold: true,
language: {
value: "ko-KR",
},
},
},
],
},
sections: [
{
properties: {},
children: [
new Paragraph({
text: "Yo vivo en Granada, una ciudad pequeña que tiene monumentos muy importantes como la Alhambra. Aquí la comida es deliciosa y son famosos el gazpacho, el rebujito y el salmorejo.",
}),
new Paragraph({
text: "Toute personne a droit à l'éducation. L'éducation doit être gratuite, au moins en ce qui concerne l'enseignement élémentaire et fondamental. L'enseignement élémentaire est obligatoire. L'enseignement technique et professionnel doit être généralisé; l'accès aux études supérieures doit être ouvert en pleine égalité à tous en fonction de leur mérite.",
style: "frenchNormal",
}),
new Paragraph({
text: "대법관은 대법원장의 제청으로 국회의 동의를 얻어 대통령이 임명한다. 강화조약. 국가는 국민 모두의 생산 및 생활의 기반이 되는 국토의 효율적이고 균형있는 이용·개발과 보전을 위하여 법률이 정하는 바에 의하여 그에 관한 필요한 제한과 의무를 과할 수 있다, 국가는 청원에 대하여 심사할 의무를 진다.",
style: "koreanNormal",
}),
],
},
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,60 @@
// Simple example apply positional tabs to a document
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import {
Document,
Packer,
Paragraph,
PositionalTab,
Tab,
TextRun,
PositionalTabAlignment,
PositionalTabRelativeTo,
PositionalTabLeader,
} from "../build";
const doc = new Document({
sections: [
{
properties: {},
children: [
new Paragraph({
children: [
new TextRun("Full name"),
new TextRun({
children: [
new PositionalTab({
alignment: PositionalTabAlignment.RIGHT,
relativeTo: PositionalTabRelativeTo.MARGIN,
leader: PositionalTabLeader.DOT,
}),
"John Doe",
],
bold: true,
}),
],
}),
new Paragraph({
children: [
new TextRun("Hello World"),
new TextRun({
children: [
new PositionalTab({
alignment: PositionalTabAlignment.CENTER,
relativeTo: PositionalTabRelativeTo.INDENT,
leader: PositionalTabLeader.HYPHEN,
}),
"Foo bar",
],
bold: true,
}),
],
}),
],
},
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,155 @@
// Patch a document with patches
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import {
ExternalHyperlink,
HeadingLevel,
ImageRun,
Paragraph,
patchDocument,
PatchType,
Table,
TableCell,
TableRow,
TextDirection,
TextRun,
VerticalAlign,
} from "../build";
patchDocument(fs.readFileSync("demo/assets/simple-template.docx"), {
patches: {
name: {
type: PatchType.PARAGRAPH,
children: [new TextRun("Sir. "), new TextRun("John Doe"), new TextRun("(The Conqueror)")],
},
table_heading_1: {
type: PatchType.PARAGRAPH,
children: [new TextRun("Heading wow!")],
},
item_1: {
type: PatchType.PARAGRAPH,
children: [
new TextRun("#657"),
new ExternalHyperlink({
children: [
new TextRun({
text: "BBC News Link",
}),
],
link: "https://www.bbc.co.uk/news",
}),
],
},
paragraph_replace: {
type: PatchType.DOCUMENT,
children: [
new Paragraph("Lorem ipsum paragraph"),
new Paragraph("Another paragraph"),
new Paragraph({
children: [
new TextRun("This is a "),
new ExternalHyperlink({
children: [
new TextRun({
text: "Google Link",
}),
],
link: "https://www.google.co.uk",
}),
new ImageRun({ data: fs.readFileSync("./demo/images/dog.png"), transformation: { width: 100, height: 100 } }),
],
}),
],
},
header_adjective: {
type: PatchType.PARAGRAPH,
children: [new TextRun("Delightful Header")],
},
footer_text: {
type: PatchType.PARAGRAPH,
children: [
new TextRun("replaced just as"),
new TextRun(" well"),
new ExternalHyperlink({
children: [
new TextRun({
text: "BBC News Link",
}),
],
link: "https://www.bbc.co.uk/news",
}),
],
},
image_test: {
type: PatchType.PARAGRAPH,
children: [new ImageRun({ data: fs.readFileSync("./demo/images/image1.jpeg"), transformation: { width: 100, height: 100 } })],
},
table: {
type: PatchType.DOCUMENT,
children: [
new Table({
rows: [
new TableRow({
children: [
new TableCell({
children: [new Paragraph({}), new Paragraph({})],
verticalAlign: VerticalAlign.CENTER,
}),
new TableCell({
children: [new Paragraph({}), new Paragraph({})],
verticalAlign: VerticalAlign.CENTER,
}),
new TableCell({
children: [new Paragraph({ text: "bottom to top" }), new Paragraph({})],
textDirection: TextDirection.BOTTOM_TO_TOP_LEFT_TO_RIGHT,
}),
new TableCell({
children: [new Paragraph({ text: "top to bottom" }), new Paragraph({})],
textDirection: TextDirection.TOP_TO_BOTTOM_RIGHT_TO_LEFT,
}),
],
}),
new TableRow({
children: [
new TableCell({
children: [
new Paragraph({
text: "Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah",
heading: HeadingLevel.HEADING_1,
}),
],
}),
new TableCell({
children: [
new Paragraph({
text: "This text should be in the middle of the cell",
}),
],
verticalAlign: VerticalAlign.CENTER,
}),
new TableCell({
children: [
new Paragraph({
text: "Text above should be vertical from bottom to top",
}),
],
verticalAlign: VerticalAlign.CENTER,
}),
new TableCell({
children: [
new Paragraph({
text: "Text above should be vertical from top to bottom",
}),
],
verticalAlign: VerticalAlign.CENTER,
}),
],
}),
],
}),
],
},
},
}).then((doc) => {
fs.writeFileSync("My Document.docx", doc);
});

View File

@ -0,0 +1,20 @@
// Generate a template document
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer, Paragraph, TextRun } from "../build";
const doc = new Document({
sections: [
{
children: [
new Paragraph({
children: [new TextRun("{{template}}")],
}),
],
},
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

Binary file not shown.

Binary file not shown.

View File

@ -1,10 +1,10 @@
<img src="https://i.imgur.com/37uBGhO.gif" alt="drawing" style="width:200px;"/> <img src="https://i.imgur.com/37uBGhO.gif" alt="drawing" style="width:200px;"/>
> Easily generate .docx files with JS/TS. Works for Node and on the Browser. :100: > Easily generate and modify .docx files with JS/TS. Works for Node and on the Browser. :100:
- Simple, declarative API - Simple, declarative API
- 60+ usage examples - 80+ usage examples
- Battle tested, mature, 99%+ coverage - Battle tested, mature, 99.9%+ coverage
[GitHub](https://github.com/dolanmiu/docx) [GitHub](https://github.com/dolanmiu/docx)
[Get Started](#Welcome) [Get Started](#Welcome)

View File

@ -1,6 +1,8 @@
- [Getting Started](/) - [Getting Started](/)
- [Examples](https://github.com/dolanmiu/docx/tree/master/demo) - Examples
- [Demos](https://github.com/dolanmiu/docx/tree/master/demo)
- API - API
@ -20,7 +22,7 @@
- [Hyperlinks](usage/hyperlinks.md) - [Hyperlinks](usage/hyperlinks.md)
- [Numbering](usage/numbering.md) - [Numbering](usage/numbering.md)
- [Tables](usage/tables.md) - [Tables](usage/tables.md)
- [Tab Stops](usage/tab-stops.md) - [Tabs](usage/tabs.md)
- [Table of Contents](usage/table-of-contents.md) - [Table of Contents](usage/table-of-contents.md)
- [Page Numbers](usage/page-numbers.md) - [Page Numbers](usage/page-numbers.md)
- [Change Tracking](usage/change-tracking.md) - [Change Tracking](usage/change-tracking.md)
@ -36,6 +38,10 @@
- [Packers](usage/packers.md) - [Packers](usage/packers.md)
- Modifying Existing Documents
- [Patcher](usage/patcher.md)
- Utility - Utility
- [Convenience functions](usage/convenience-functions.md) - [Convenience functions](usage/convenience-functions.md)

View File

@ -1,11 +1,21 @@
# Contribution Guidelines # Contribution Guidelines
- Include documentation reference(s) at the top of each file: - Include documentation reference(s) at the top of each file as a comment. For example:
```ts ```ts
// http://officeopenxml.com/WPdocument.php // http://officeopenxml.com/WPdocument.php
``` ```
<!-- cSpell:ignore datypic -->
It can be a link to `officeopenxml.com` or `datypic.com` etc.
It could also be a reference to the official ECMA-376 standard: https://www.ecma-international.org/publications-and-standards/standards/ecma-376/
- Include a portion of the schema as a comment for cross reference. For example:
```ts
// <xsd:element name="tbl" type="CT_Tbl" minOccurs="0" maxOccurs="1"/>
```
- Follow Prettier standards, and consider using the [Prettier VSCode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) plugin. - Follow Prettier standards, and consider using the [Prettier VSCode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) plugin.
- Follow the `ESLint` rules - Follow the `ESLint` rules

42
docs/usage/footnotes.md Normal file
View File

@ -0,0 +1,42 @@
# Footnotes
!> Footnotes requires an understanding of [Sections](usage/sections.md).
Use footnotes and endnotes to explain, comment on, or provide references to something in a document. Usually, footnotes appear at the bottom of the page.
## Example
```ts
const doc = new Document({
footnotes: {
1: { children: [new Paragraph("Foo"), new Paragraph("Bar")] },
2: { children: [new Paragraph("Test")] },
},
sections: [
{
children: [
new Paragraph({
children: [
new TextRun({
children: ["Hello"],
}),
new FootnoteReferenceRun(1),
new TextRun({
children: [" World!"],
}),
new FootnoteReferenceRun(2),
],
}),
],
},
],
});
```
## Usage
Footnotes requires an entry into the `footnotes` array in the `Document` constructor, and a `FootnoteReferenceRun` in the `Paragraph` constructor.
`footnotes` is an object of number to `Footnote` objects. The number is the reference number, and the `Footnote` object is the content of the footnote. The `Footnote` object has a `children` property, which is an array of `Paragraph` objects.
`FootnoteReferenceRun` is a `Run` object, which are added to `Paragraph`s. It takes a number as a parameter, which is the reference number of the footnote.

94
docs/usage/patcher.md Normal file
View File

@ -0,0 +1,94 @@
# Patcher
The patcher allows you to modify existing documents, and add new content to them.
!> The Patcher requires an understanding of [Paragraphs](usage/paragraph.md).
---
## Usage
```ts
import * as fs from "fs";
import { patchDocument } from "docx";
patchDocument(fs.readFileSync("My Document.docx"), {
patches: {
// Patches here
},
});
```
## Patches
The patcher takes in a `patches` object, which is a map of `string` to `Patch`:
```ts
interface Patch {
type: PatchType;
children: FileChild[] | ParagraphChild[];
}
```
| Property | Type | Notes | Possible Values |
| -------- | --------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| type | `PatchType` | Required | `DOCUMENT`, `PARAGRAPH` |
| children | `FileChild[] or ParagraphChild[]` | Required | The contents to replace with. A `FileChild` is a `Paragraph` or `Table`, whereas a `ParagraphChild` is typical `Paragraph` children. |
### How to patch existing document
1. Open your existing word document in your favorite Word Processor
2. Write tags in the document where you want to patch in a mustache style notation. For example, `{{my_patch}}` and `{{my_second_patch}}`.
3. Run the patcher with the patches as a key value pair.
## Example
### Word Document
![Word Document screenshot](https://i.imgur.com/ybkvw6Z.png)
### Patcher
?> Notice how there is no handlebar notation in the key.
The patch can be as simple as a string, or as complex as a table. Images, hyperlinks, and other complex elements within the `docx` library are also supported.
```ts
patchDocument(fs.readFileSync("My Document.docx"), {
patches: {
my_patch: {
type: PatchType.PARAGRAPH,
children: [new TextRun("Sir. "), new TextRun("John Doe"), new TextRun("(The Conqueror)")],
},
my_second_patch: {
type: PatchType.DOCUMENT,
children: [
new Paragraph("Lorem ipsum paragraph"),
new Paragraph("Another paragraph"),
new Paragraph({
children: [
new TextRun("This is a "),
new ExternalHyperlink({
children: [
new TextRun({
text: "Google Link",
}),
],
link: "https://www.google.co.uk",
}),
new ImageRun({ data: fs.readFileSync("./demo/images/dog.png"), transformation: { width: 100, height: 100 } }),
],
}),
],
},
},
});
```
---
## Demo
_Source: https://github.com/dolanmiu/docx/blob/master/demo/85-template-document.ts_
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/85-template-document.ts ":include :type=code typescript")

View File

@ -1,121 +0,0 @@
# Tab Stops
> Tab stops are useful, if you are unclear of what they are, [here is a link explaining](https://en.wikipedia.org/wiki/Tab_stop). It enables side by side text which is nicely laid out without the need for tables, or constantly pressing space bar.
!> **Note**: The unit of measurement for a tab stop is in [DXA](https://stackoverflow.com/questions/14360183/default-wordml-unit-measurement-pixel-or-point-or-inches)
![Word 2013 Tabs](https://support.content.office.net/en-us/media/d75ca75d-9fe9-4d46-9a8b-4534c13acbc5.png "Word 2013 Tab Stops")
Simply declare the tab stops on the paragraph, as shown below. Use the tab character `\t` to indicate the tab position within the `text` property of a `TextRun`. Adding multiple `tabStops` will mean you can add additional `\t` characters until the desired `tabStop` is selected. Example is shown below.
## Example
```ts
const paragraph = new Paragraph({
children: [new TextRun({ text: "Hey everyone", bold: true}), new TextRun("\t11th November 1999")],
tabStops: [
{
type: TabStopType.RIGHT,
position: TabStopPosition.MAX,
},
],
});
```
The example above will create a left aligned text, and a right aligned text on the same line. The laymans approach to this problem would be to either use text boxes or tables. Not ideal!
```ts
const paragraph = new Paragraph({
children: [new TextRun("\t\tSecond tab stop here I come!")],
tabStops: [
{
type: TabStopType.RIGHT,
position: TabStopPosition.MAX,
},
{
type: TabStopType.LEFT,
position: 1000,
},
],
});
```
The above shows the use of two tab stops, and how to select/use it.
You can add multiple tab stops of the same `type` too.
```ts
const paragraph = new Paragraph({
children: [new TextRun("Multiple \ttab \tstops!")],
tabStops: [
{
type: TabStopType.RIGHT,
position: TabStopPosition.MAX,
},
{
type: TabStopType.RIGHT,
position: 1000,
},
],
});
```
## Left Tab Stop
```ts
const paragraph = new Paragraph({
tabStops: [
{
type: TabStopType.LEFT,
position: 2268,
},
],
});
```
2268 is the distance from the left side.
## Center Tab Stop
```ts
const paragraph = new Paragraph({
tabStops: [
{
type: TabStopType.CENTER,
position: 2268,
},
],
});
```
2268 is the distance from the center.
## Right Tab Stop
```ts
const paragraph = new Paragraph({
tabStops: [
{
type: TabStopType.RIGHT,
position: 2268,
},
],
});
```
2268 is the distance from the left side.
## Max Right Tab Stop
```ts
const paragraph = new Paragraph({
tabStops: [
{
type: TabStopType.RIGHT,
position: TabStopPosition.MAX,
},
],
});
```
This will create a tab stop on the very edge of the right hand side. Handy for right aligning and left aligning text on the same line.

184
docs/usage/tabs.md Normal file
View File

@ -0,0 +1,184 @@
# Tabs and Tab Stops
## Tab Stops
> Tab stops are useful, if you are unclear of what they are, [here is a link explaining](https://en.wikipedia.org/wiki/Tab_stop). It enables side by side text which is nicely laid out without the need for tables, or constantly pressing space bar.
!> **Note**: The unit of measurement for a tab stop is in [DXA](https://stackoverflow.com/questions/14360183/default-wordml-unit-measurement-pixel-or-point-or-inches)
![Word 2013 Tabs](https://support.content.office.net/en-us/media/d75ca75d-9fe9-4d46-9a8b-4534c13acbc5.png "Word 2013 Tab Stops")
Simply declare the tab stops on the paragraph, as shown below. Use the tab character `\t` or add the `new Tab()` child to indicate the tab position within the `text` property of a `TextRun`. Adding multiple `tabStops` will mean you can add additional `\t` characters until the desired `tabStop` is selected. Example is shown below.
### Example
```ts
const paragraph = new Paragraph({
children: [
new TextRun({ text: "Hey everyone", bold: true }),
new TextRun("\t11th November 1999"),
new TextRun({
children: [new Tab(), "11th November 1999"],
}),
],
tabStops: [
{
type: TabStopType.RIGHT,
position: TabStopPosition.MAX,
},
],
});
```
The example above will create a left aligned text, and a right aligned text on the same line. The laymans approach to this problem would be to either use text boxes or tables. Not ideal!
```ts
const paragraph = new Paragraph({
children: [new TextRun("\t\tSecond tab stop here I come!")],
tabStops: [
{
type: TabStopType.RIGHT,
position: TabStopPosition.MAX,
},
{
type: TabStopType.LEFT,
position: 1000,
},
],
});
```
The above shows the use of two tab stops, and how to select/use it.
You can add multiple tab stops of the same `type` too.
```ts
const paragraph = new Paragraph({
children: [new TextRun("Multiple \ttab \tstops!")],
tabStops: [
{
type: TabStopType.RIGHT,
position: TabStopPosition.MAX,
},
{
type: TabStopType.RIGHT,
position: 1000,
},
],
});
const paragraph = new Paragraph({
children: [
new TextRun({
children: ["Multiple ", new Tab(), "tab ", new Tab(), "stops!"],
}),
],
tabStops: [
{
type: TabStopType.RIGHT,
position: TabStopPosition.MAX,
},
{
type: TabStopType.RIGHT,
position: 1000,
},
],
});
```
### Left Tab Stop
```ts
const paragraph = new Paragraph({
tabStops: [
{
type: TabStopType.LEFT,
position: 2268,
},
],
});
```
2268 is the distance from the left side.
### Center Tab Stop
```ts
const paragraph = new Paragraph({
tabStops: [
{
type: TabStopType.CENTER,
position: 2268,
},
],
});
```
2268 is the distance from the center.
### Right Tab Stop
```ts
const paragraph = new Paragraph({
tabStops: [
{
type: TabStopType.RIGHT,
position: 2268,
},
],
});
```
2268 is the distance from the left side.
### Max Right Tab Stop
```ts
const paragraph = new Paragraph({
tabStops: [
{
type: TabStopType.RIGHT,
position: TabStopPosition.MAX,
},
],
});
```
This will create a tab stop on the very edge of the right hand side. Handy for right aligning and left aligning text on the same line.
## Positional Tabs
> Positional tab allow you to create a tab stop that is relative to the margin, or the page. This is useful if you want to create a table of contents, or a table of figures.
They are easier to use than the normal tab stops, as you can use the `PositionalTab` class to create a tab stop, and then add the text to the `TextRun` children. Useful for most cases.
![Word Positional Tabs](https://user-images.githubusercontent.com/26860966/209019464-d4b50236-c324-4cdb-8139-b9d172b1b993.png "Word Positional Tabs")
### Example
```ts
new Paragraph({
children: [
new TextRun("Full name"),
new TextRun({
children: [
new PositionalTab({
alignment: PositionalTabAlignment.RIGHT,
relativeTo: PositionalTabRelativeTo.MARGIN,
leader: PositionalTabLeader.DOT,
}),
"John Doe",
],
bold: true,
}),
],
}),
```
### Options
| Option | Type | Description | Possible Values |
| ---------- | ------------------------- | ------------------------------------- | ------------------------------------------------------------- |
| alignment | `PositionalTabAlignment` | The alignment of the tab stop | `LEFT`, `RIGHT`, `CENTER` |
| relativeTo | `PositionalTabRelativeTo` | The relative position of the tab stop | `MARGIN`, `INDENT` |
| leader | `PositionalTabLeader` | The leader of the tab stop | `NONE`, `DOT`, `HYPHEN`, `UNDERSCORE`, `MIDDLE_DOT`, `EQUALS` |

3614
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "docx", "name": "docx",
"version": "7.8.0", "version": "8.0.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.",
"main": "build/index.js", "main": "build/index.js",
"scripts": { "scripts": {
@ -52,7 +52,7 @@
"dependencies": { "dependencies": {
"@types/node": "^18.0.0", "@types/node": "^18.0.0",
"jszip": "^3.1.5", "jszip": "^3.1.5",
"nanoid": "^3.1.20", "nanoid": "^3.3.4",
"xml": "^1.0.1", "xml": "^1.0.1",
"xml-js": "^1.6.8" "xml-js": "^1.6.8"
}, },
@ -64,6 +64,7 @@
"homepage": "https://github.com/dolanmiu/docx#readme", "homepage": "https://github.com/dolanmiu/docx#readme",
"devDependencies": { "devDependencies": {
"@types/chai": "^4.2.15", "@types/chai": "^4.2.15",
"@types/chai-as-promised": "^7.1.5",
"@types/glob": "^8.0.0", "@types/glob": "^8.0.0",
"@types/mocha": "^10.0.0", "@types/mocha": "^10.0.0",
"@types/prompt": "^1.1.1", "@types/prompt": "^1.1.1",
@ -76,16 +77,17 @@
"@typescript-eslint/parser": "^5.36.1", "@typescript-eslint/parser": "^5.36.1",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"chai": "^4.3.6", "chai": "^4.3.6",
"chai-as-promised": "^7.1.1",
"cspell": "^6.2.2", "cspell": "^6.2.2",
"docsify-cli": "^4.3.0", "docsify-cli": "^4.3.0",
"eslint": "^8.23.0", "eslint": "^8.23.0",
"eslint-plugin-functional": "^4.3.1", "eslint-plugin-functional": "^5.0.1",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsdoc": "^39.3.6", "eslint-plugin-jsdoc": "^40.0.0",
"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": "^45.0.0", "eslint-plugin-unicorn": "^46.0.0",
"glob": "^8.0.1", "glob": "^9.3.0",
"jszip": "^3.1.5", "jszip": "^3.1.5",
"mocha": "^10.0.0", "mocha": "^10.0.0",
"nyc": "^15.1.0", "nyc": "^15.1.0",
@ -96,7 +98,7 @@
"replace-in-file": "^6.2.0", "replace-in-file": "^6.2.0",
"request": "^2.88.0", "request": "^2.88.0",
"request-promise": "^4.2.2", "request-promise": "^4.2.2",
"rimraf": "^3.0.2", "rimraf": "^4.0.4",
"shelljs": "^0.8.4", "shelljs": "^0.8.4",
"sinon": "^15.0.0", "sinon": "^15.0.0",
"stream-browserify": "^3.0.0", "stream-browserify": "^3.0.0",
@ -105,7 +107,7 @@
"tsconfig-paths": "^4.0.0", "tsconfig-paths": "^4.0.0",
"tsconfig-paths-webpack-plugin": "^4.0.0", "tsconfig-paths-webpack-plugin": "^4.0.0",
"typedoc": "^0.23.2", "typedoc": "^0.23.2",
"typescript": "4.9.4", "typescript": "5.0.2",
"unzipper": "^0.10.11", "unzipper": "^0.10.11",
"webpack": "^5.28.0", "webpack": "^5.28.0",
"webpack-cli": "^5.0.0" "webpack-cli": "^5.0.0"

View File

@ -9,7 +9,7 @@ for (const file of files) {
from: /"@[a-z/-]*"/gi, from: /"@[a-z/-]*"/gi,
to: (match) => { to: (match) => {
const matchSlug = match.replace(/['"]+/g, "").replace(/[@]+/g, "").trim(); const matchSlug = match.replace(/['"]+/g, "").replace(/[@]+/g, "").trim();
const levelCount = file.split("/").length - 2; const levelCount = file.split(/[\/\\]/).length - 2;
const backLevels = Array(levelCount).fill("../").join(""); const backLevels = Array(levelCount).fill("../").join("");
return `"${backLevels}${matchSlug}"`; return `"${backLevels}${matchSlug}"`;

View File

@ -2,7 +2,7 @@ import { BaseXmlComponent, IContext, IXmlableObject } from "@file/xml-components
export class Formatter { export class Formatter {
// tslint:disable-next-line: no-object-literal-type-assertion // tslint:disable-next-line: no-object-literal-type-assertion
public format(input: BaseXmlComponent, context: IContext = {} as IContext): IXmlableObject { public format(input: BaseXmlComponent, context: IContext = { stack: [] } as unknown as IContext): IXmlableObject {
const output = input.prepForXml(context); const output = input.prepForXml(context);
if (output) { if (output) {

View File

@ -59,9 +59,8 @@ export class Compiler {
} }
} }
for (const data of file.Media.Array) { for (const { stream, fileName } of file.Media.Array) {
const mediaData = data.stream; zip.file(`word/media/${fileName}`, stream);
zip.file(`word/media/${data.fileName}`, mediaData);
} }
return zip; return zip;
@ -74,6 +73,7 @@ export class Compiler {
this.formatter.format(file.Document.View, { this.formatter.format(file.Document.View, {
viewWrapper: file.Document, viewWrapper: file.Document,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -100,6 +100,7 @@ export class Compiler {
this.formatter.format(file.Document.Relationships, { this.formatter.format(file.Document.Relationships, {
viewWrapper: file.Document, viewWrapper: file.Document,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -125,6 +126,7 @@ export class Compiler {
this.formatter.format(file.Styles, { this.formatter.format(file.Styles, {
viewWrapper: file.Document, viewWrapper: file.Document,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -144,6 +146,7 @@ export class Compiler {
this.formatter.format(file.CoreProperties, { this.formatter.format(file.CoreProperties, {
viewWrapper: file.Document, viewWrapper: file.Document,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -160,6 +163,7 @@ export class Compiler {
this.formatter.format(file.Numbering, { this.formatter.format(file.Numbering, {
viewWrapper: file.Document, viewWrapper: file.Document,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -176,6 +180,7 @@ export class Compiler {
this.formatter.format(file.FileRelationships, { this.formatter.format(file.FileRelationships, {
viewWrapper: file.Document, viewWrapper: file.Document,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -191,6 +196,7 @@ export class Compiler {
this.formatter.format(headerWrapper.View, { this.formatter.format(headerWrapper.View, {
viewWrapper: headerWrapper, viewWrapper: headerWrapper,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -214,6 +220,7 @@ export class Compiler {
this.formatter.format(headerWrapper.Relationships, { this.formatter.format(headerWrapper.Relationships, {
viewWrapper: headerWrapper, viewWrapper: headerWrapper,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -230,6 +237,7 @@ export class Compiler {
this.formatter.format(footerWrapper.View, { this.formatter.format(footerWrapper.View, {
viewWrapper: footerWrapper, viewWrapper: footerWrapper,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -253,6 +261,7 @@ export class Compiler {
this.formatter.format(footerWrapper.Relationships, { this.formatter.format(footerWrapper.Relationships, {
viewWrapper: footerWrapper, viewWrapper: footerWrapper,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -269,6 +278,7 @@ export class Compiler {
this.formatter.format(headerWrapper.View, { this.formatter.format(headerWrapper.View, {
viewWrapper: headerWrapper, viewWrapper: headerWrapper,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -293,6 +303,7 @@ export class Compiler {
this.formatter.format(footerWrapper.View, { this.formatter.format(footerWrapper.View, {
viewWrapper: footerWrapper, viewWrapper: footerWrapper,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -317,6 +328,7 @@ export class Compiler {
this.formatter.format(file.ContentTypes, { this.formatter.format(file.ContentTypes, {
viewWrapper: file.Document, viewWrapper: file.Document,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -332,6 +344,7 @@ export class Compiler {
this.formatter.format(file.CustomProperties, { this.formatter.format(file.CustomProperties, {
viewWrapper: file.Document, viewWrapper: file.Document,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -348,6 +361,7 @@ export class Compiler {
this.formatter.format(file.AppProperties, { this.formatter.format(file.AppProperties, {
viewWrapper: file.Document, viewWrapper: file.Document,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -363,7 +377,8 @@ export class Compiler {
data: xml( data: xml(
this.formatter.format(file.FootNotes.View, { this.formatter.format(file.FootNotes.View, {
viewWrapper: file.FootNotes, viewWrapper: file.FootNotes,
file: file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -378,7 +393,8 @@ export class Compiler {
data: xml( data: xml(
this.formatter.format(file.FootNotes.Relationships, { this.formatter.format(file.FootNotes.Relationships, {
viewWrapper: file.FootNotes, viewWrapper: file.FootNotes,
file: file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -394,6 +410,7 @@ export class Compiler {
this.formatter.format(file.Settings, { this.formatter.format(file.Settings, {
viewWrapper: file.Document, viewWrapper: file.Document,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,
@ -410,6 +427,7 @@ export class Compiler {
this.formatter.format(file.Comments, { this.formatter.format(file.Comments, {
viewWrapper: file.Document, viewWrapper: file.Document,
file, file,
stack: [],
}), }),
{ {
indent: prettify, indent: prettify,

View File

@ -1,25 +1,23 @@
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { NextAttributeComponent, XmlComponent } from "@file/xml-components";
import { twipsMeasureValue } from "@util/values"; import { PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
export interface IColumnAttributes { // <xsd:complexType name="CT_Column">
readonly width: number | string; // <xsd:attribute name="w" type="s:ST_TwipsMeasure" use="optional" />
readonly space?: number | string; // <xsd:attribute name="space" type="s:ST_TwipsMeasure" use="optional" default="0" />
} // </xsd:complexType>
export class ColumnAttributes extends XmlAttributeComponent<IColumnAttributes> { type IColumnAttributes = {
protected readonly xmlKeys = { readonly width: number | PositiveUniversalMeasure;
width: "w:w", readonly space?: number | PositiveUniversalMeasure;
space: "w:space",
}; };
}
export class Column extends XmlComponent { export class Column extends XmlComponent {
public constructor({ width, space }: IColumnAttributes) { public constructor({ width, space }: IColumnAttributes) {
super("w:col"); super("w:col");
this.root.push( this.root.push(
new ColumnAttributes({ new NextAttributeComponent<IColumnAttributes>({
width: twipsMeasureValue(width), width: { key: "w:w", value: twipsMeasureValue(width) },
space: space === undefined ? undefined : twipsMeasureValue(space), space: { key: "w:space", value: space === undefined ? undefined : twipsMeasureValue(space) },
}), }),
); );
} }

View File

@ -1,5 +1,5 @@
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { NextAttributeComponent, XmlComponent } from "@file/xml-components";
import { decimalNumber, twipsMeasureValue } from "@util/values"; import { decimalNumber, PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
import { Column } from "./column"; import { Column } from "./column";
@ -12,32 +12,23 @@ import { Column } from "./column";
// <xsd:attribute name="num" type="ST_DecimalNumber" use="optional" default="1"/> // <xsd:attribute name="num" type="ST_DecimalNumber" use="optional" default="1"/>
// <xsd:attribute name="sep" type="s:ST_OnOff" use="optional"/> // <xsd:attribute name="sep" type="s:ST_OnOff" use="optional"/>
// </xsd:complexType> // </xsd:complexType>
export interface IColumnsAttributes { export type IColumnsAttributes = {
readonly space?: number | string; readonly space?: number | PositiveUniversalMeasure;
readonly count?: number; readonly count?: number;
readonly separate?: boolean; readonly separate?: boolean;
readonly equalWidth?: boolean; readonly equalWidth?: boolean;
readonly children?: readonly Column[]; readonly children?: readonly Column[];
}
export class ColumnsAttributes extends XmlAttributeComponent<IColumnsAttributes> {
protected readonly xmlKeys = {
space: "w:space",
count: "w:num",
separate: "w:sep",
equalWidth: "w:equalWidth",
}; };
}
export class Columns extends XmlComponent { export class Columns extends XmlComponent {
public constructor({ space, count, separate, equalWidth, children }: IColumnsAttributes) { public constructor({ space, count, separate, equalWidth, children }: IColumnsAttributes) {
super("w:cols"); super("w:cols");
this.root.push( this.root.push(
new ColumnsAttributes({ new NextAttributeComponent<Omit<IColumnsAttributes, "children">>({
space: space === undefined ? undefined : twipsMeasureValue(space), space: { key: "w:space", value: space === undefined ? undefined : twipsMeasureValue(space) },
count: count === undefined ? undefined : decimalNumber(count), count: { key: "w:num", value: count === undefined ? undefined : decimalNumber(count) },
separate, separate: { key: "w:sep", value: separate },
equalWidth, equalWidth: { key: "w:equalWidth", value: equalWidth },
}), }),
); );

View File

@ -1,6 +1,6 @@
// http://officeopenxml.com/WPsectionLineNumbering.php // http://officeopenxml.com/WPsectionLineNumbering.php
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { NextAttributeComponent, XmlComponent } from "@file/xml-components";
import { decimalNumber, twipsMeasureValue } from "@util/values"; import { decimalNumber, PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
// <xsd:simpleType name="ST_LineNumberRestart"> // <xsd:simpleType name="ST_LineNumberRestart">
// <xsd:restriction base="xsd:string"> // <xsd:restriction base="xsd:string">
@ -26,27 +26,23 @@ export interface ILineNumberAttributes {
readonly countBy?: number; readonly countBy?: number;
readonly start?: number; readonly start?: number;
readonly restart?: LineNumberRestartFormat; readonly restart?: LineNumberRestartFormat;
readonly distance?: number | string; readonly distance?: number | PositiveUniversalMeasure;
}
export class LineNumberAttributes extends XmlAttributeComponent<ILineNumberAttributes> {
protected readonly xmlKeys = {
countBy: "w:countBy",
start: "w:start",
restart: "w:restart",
distance: "w:distance",
};
} }
export class LineNumberType extends XmlComponent { export class LineNumberType extends XmlComponent {
public constructor({ countBy, start, restart, distance }: ILineNumberAttributes) { public constructor({ countBy, start, restart, distance }: ILineNumberAttributes) {
super("w:lnNumType"); super("w:lnNumType");
this.root.push( this.root.push(
new LineNumberAttributes({ new NextAttributeComponent<{
countBy: countBy === undefined ? undefined : decimalNumber(countBy), readonly countBy?: number;
start: start === undefined ? undefined : decimalNumber(start), readonly start?: number;
restart, readonly restart?: LineNumberRestartFormat;
distance: distance === undefined ? undefined : twipsMeasureValue(distance), readonly distance?: number | PositiveUniversalMeasure;
}>({
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

@ -75,7 +75,7 @@ export class PageBorders extends IgnoreIfEmptyXmlComponent {
super("w:pgBorders"); super("w:pgBorders");
if (!options) { if (!options) {
return; return this;
} }
if (options.pageBorders) { if (options.pageBorders) {

View File

@ -1,5 +1,5 @@
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { NextAttributeComponent, XmlComponent } from "@file/xml-components";
import { signedTwipsMeasureValue, twipsMeasureValue } from "@util/values"; import { PositiveUniversalMeasure, signedTwipsMeasureValue, twipsMeasureValue, UniversalMeasure } from "@util/values";
// <xsd:complexType name="CT_PageMar"> // <xsd:complexType name="CT_PageMar">
// <xsd:attribute name="top" type="ST_SignedTwipsMeasure" use="required"/> // <xsd:attribute name="top" type="ST_SignedTwipsMeasure" use="required"/>
@ -10,48 +10,36 @@ import { signedTwipsMeasureValue, twipsMeasureValue } from "@util/values";
// <xsd:attribute name="footer" type="s:ST_TwipsMeasure" use="required"/> // <xsd:attribute name="footer" type="s:ST_TwipsMeasure" use="required"/>
// <xsd:attribute name="gutter" type="s:ST_TwipsMeasure" use="required"/> // <xsd:attribute name="gutter" type="s:ST_TwipsMeasure" use="required"/>
// </xsd:complexType> // </xsd:complexType>
export interface IPageMarginAttributes { export type IPageMarginAttributes = {
readonly top?: number | string; readonly top?: number | UniversalMeasure;
readonly right?: number | string; readonly right?: number | PositiveUniversalMeasure;
readonly bottom?: number | string; readonly bottom?: number | UniversalMeasure;
readonly left?: number | string; readonly left?: number | PositiveUniversalMeasure;
readonly header?: number | string; readonly header?: number | PositiveUniversalMeasure;
readonly footer?: number | string; readonly footer?: number | PositiveUniversalMeasure;
readonly gutter?: number | string; readonly gutter?: number | PositiveUniversalMeasure;
}
export class PageMarginAttributes extends XmlAttributeComponent<IPageMarginAttributes> {
protected readonly xmlKeys = {
top: "w:top",
right: "w:right",
bottom: "w:bottom",
left: "w:left",
header: "w:header",
footer: "w:footer",
gutter: "w:gutter",
}; };
}
export class PageMargin extends XmlComponent { export class PageMargin extends XmlComponent {
public constructor( public constructor(
top: number | string, top: number | UniversalMeasure,
right: number | string, right: number | PositiveUniversalMeasure,
bottom: number | string, bottom: number | UniversalMeasure,
left: number | string, left: number | PositiveUniversalMeasure,
header: number | string, header: number | PositiveUniversalMeasure,
footer: number | string, footer: number | PositiveUniversalMeasure,
gutter: number | string, gutter: number | PositiveUniversalMeasure,
) { ) {
super("w:pgMar"); super("w:pgMar");
this.root.push( this.root.push(
new PageMarginAttributes({ new NextAttributeComponent<IPageMarginAttributes>({
top: signedTwipsMeasureValue(top), top: { key: "w:top", value: signedTwipsMeasureValue(top) },
right: twipsMeasureValue(right), right: { key: "w:right", value: twipsMeasureValue(right) },
bottom: signedTwipsMeasureValue(bottom), bottom: { key: "w:bottom", value: signedTwipsMeasureValue(bottom) },
left: twipsMeasureValue(left), left: { key: "w:left", value: twipsMeasureValue(left) },
header: twipsMeasureValue(header), header: { key: "w:header", value: twipsMeasureValue(header) },
footer: twipsMeasureValue(footer), footer: { key: "w:footer", value: twipsMeasureValue(footer) },
gutter: twipsMeasureValue(gutter), gutter: { key: "w:gutter", value: twipsMeasureValue(gutter) },
}), }),
); );
} }

View File

@ -1,5 +1,5 @@
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { NextAttributeComponent, XmlComponent } from "@file/xml-components";
import { twipsMeasureValue } from "@util/values"; import { PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
// <xsd:simpleType name="ST_PageOrientation"> // <xsd:simpleType name="ST_PageOrientation">
// <xsd:restriction base="xsd:string"> // <xsd:restriction base="xsd:string">
@ -18,22 +18,14 @@ export enum PageOrientation {
// <xsd:attribute name="orient" type="ST_PageOrientation" use="optional"/> // <xsd:attribute name="orient" type="ST_PageOrientation" use="optional"/>
// <xsd:attribute name="code" type="ST_DecimalNumber" use="optional"/> // <xsd:attribute name="code" type="ST_DecimalNumber" use="optional"/>
// </xsd:complexType> // </xsd:complexType>
export interface IPageSizeAttributes { export type IPageSizeAttributes = {
readonly width?: number | string; readonly width?: number | PositiveUniversalMeasure;
readonly height?: number | string; readonly height?: number | PositiveUniversalMeasure;
readonly orientation?: PageOrientation; readonly orientation?: PageOrientation;
}
export class PageSizeAttributes extends XmlAttributeComponent<IPageSizeAttributes> {
protected readonly xmlKeys = {
width: "w:w",
height: "w:h",
orientation: "w:orient",
}; };
}
export class PageSize extends XmlComponent { export class PageSize extends XmlComponent {
public constructor(width: number | string, height: number | string, orientation: PageOrientation) { public constructor(width: number | PositiveUniversalMeasure, height: number | PositiveUniversalMeasure, orientation: PageOrientation) {
super("w:pgSz"); super("w:pgSz");
const flip = orientation === PageOrientation.LANDSCAPE; const flip = orientation === PageOrientation.LANDSCAPE;
@ -42,10 +34,10 @@ export class PageSize extends XmlComponent {
const heightTwips = twipsMeasureValue(height); const heightTwips = twipsMeasureValue(height);
this.root.push( this.root.push(
new PageSizeAttributes({ new NextAttributeComponent<IPageSizeAttributes>({
width: flip ? heightTwips : widthTwips, width: { key: "w:w", value: flip ? heightTwips : widthTwips },
height: flip ? widthTwips : heightTwips, height: { key: "w:h", value: flip ? widthTwips : heightTwips },
orientation: orientation, orientation: { key: "w:orient", value: orientation },
}), }),
); );
} }

View File

@ -5,9 +5,9 @@ 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, LineNumberType } from "./properties/line-number";
@ -76,10 +76,10 @@ export interface ISectionPropertiesOptions {
// </xsd:group> // </xsd:group>
export const sectionMarginDefaults = { export const sectionMarginDefaults = {
TOP: "1in", TOP: "1in" as UniversalMeasure,
RIGHT: "1in", RIGHT: "1in" as PositiveUniversalMeasure,
BOTTOM: "1in", BOTTOM: "1in" as UniversalMeasure,
LEFT: "1in", LEFT: "1in" as PositiveUniversalMeasure,
HEADER: 708, HEADER: 708,
FOOTER: 708, FOOTER: 708,
GUTTER: 0, GUTTER: 0,

View File

@ -0,0 +1,61 @@
import { expect } from "chai";
import { Formatter } from "@export/formatter";
import { createHyperlinkClick, createHyperlinkHover } from "./doc-properties-children";
describe("Document Properties Children", () => {
describe("#createHyperlinkClick", () => {
it("should create a Hyperlink Click component", () => {
const tree = new Formatter().format(createHyperlinkClick("1", false));
expect(tree).to.deep.equal({
"a:hlinkClick": {
_attr: {
"r:id": "rId1",
},
},
});
});
it("should create a Hyperlink Click component with xmlns:a", () => {
const tree = new Formatter().format(createHyperlinkClick("1", true));
expect(tree).to.deep.equal({
"a:hlinkClick": {
_attr: {
"r:id": "rId1",
"xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
},
},
});
});
});
describe("#createHyperlinkHover", () => {
it("should create a Hyperlink Hover component", () => {
const tree = new Formatter().format(createHyperlinkHover("1", false));
expect(tree).to.deep.equal({
"a:hlinkHover": {
_attr: {
"r:id": "rId1",
},
},
});
});
it("should create a Hyperlink Hover component with xmlns:a", () => {
const tree = new Formatter().format(createHyperlinkHover("1", true));
expect(tree).to.deep.equal({
"a:hlinkHover": {
_attr: {
"r:id": "rId1",
"xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
},
},
});
});
});
});

View File

@ -0,0 +1,57 @@
// <sequence>
// <element name="hlinkClick" type="CT_Hyperlink" minOccurs="0" maxOccurs="1" />
// <element name="hlinkHover" type="CT_Hyperlink" minOccurs="0" maxOccurs="1" />
// <element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1" />
// </sequence>
import { BuilderElement, XmlComponent } from "@file/xml-components";
// <xsd:complexType name="CT_Hyperlink">
// <xsd:group ref="EG_PContent" minOccurs="0" maxOccurs="unbounded" />
// <xsd:attribute name="tgtFrame" type="s:ST_String" use="optional" />
// <xsd:attribute name="tooltip" type="s:ST_String" use="optional" />
// <xsd:attribute name="docLocation" type="s:ST_String" use="optional" />
// <xsd:attribute name="history" type="s:ST_OnOff" use="optional" />
// <xsd:attribute name="anchor" type="s:ST_String" use="optional" />
// <xsd:attribute ref="r:id" />
// </xsd:complexType>
// TODO: Implement the rest of the attributes
export const createHyperlinkClick = (linkId: string, hasXmlNs: boolean): XmlComponent =>
new BuilderElement({
name: "a:hlinkClick",
attributes: {
...(hasXmlNs
? {
xmlns: {
key: "xmlns:a",
value: "http://schemas.openxmlformats.org/drawingml/2006/main",
},
}
: {}),
id: {
key: "r:id",
value: `rId${linkId}`,
},
},
});
export const createHyperlinkHover = (linkId: string, hasXmlNs: boolean): XmlComponent =>
new BuilderElement({
name: "a:hlinkHover",
attributes: {
...(hasXmlNs
? {
xmlns: {
key: "xmlns:a",
value: "http://schemas.openxmlformats.org/drawingml/2006/main",
},
}
: {}),
id: {
key: "r:id",
value: `rId${linkId}`,
},
},
});

View File

@ -1,19 +1,22 @@
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; // https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_docPr_topic_ID0ES32OB.html
import { IContext, IXmlableObject, NextAttributeComponent, XmlComponent } from "@file/xml-components";
import { ConcreteHyperlink } from "@file/paragraph";
import { uniqueNumericId } from "@util/convenience-functions"; import { uniqueNumericId } from "@util/convenience-functions";
class DocPropertiesAttributes extends XmlAttributeComponent<{ import { createHyperlinkClick } from "./doc-properties-children";
readonly id?: number;
readonly name?: string; // <complexType name="CT_NonVisualDrawingProps">
readonly description?: string; // <sequence>
readonly title?: string; // <element name="hlinkClick" type="CT_Hyperlink" minOccurs="0" maxOccurs="1" />
}> { // <element name="hlinkHover" type="CT_Hyperlink" minOccurs="0" maxOccurs="1" />
protected readonly xmlKeys = { // <element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1" />
id: "id", // </sequence>
name: "name", // <attribute name="id" type="ST_DrawingElementId" use="required" />
description: "descr", // <attribute name="name" type="xsd:string" use="required" />
title: "title", // <attribute name="descr" type="xsd:string" use="optional" default="" />
}; // <attribute name="hidden" type="xsd:boolean" use="optional" default="false" />
} // </complexType>
export interface DocPropertiesOptions { export interface DocPropertiesOptions {
readonly name: string; readonly name: string;
@ -26,12 +29,39 @@ export class DocProperties extends XmlComponent {
super("wp:docPr"); super("wp:docPr");
this.root.push( this.root.push(
new DocPropertiesAttributes({ new NextAttributeComponent({
id: uniqueNumericId(), id: {
name, key: "id",
description, value: uniqueNumericId(),
title, },
name: {
key: "name",
value: name,
},
description: {
key: "descr",
value: description,
},
title: {
key: "title",
value: title,
},
}), }),
); );
} }
public prepForXml(context: IContext): IXmlableObject | undefined {
for (let i = context.stack.length - 1; i >= 0; i--) {
const element = context.stack[i];
if (!(element instanceof ConcreteHyperlink)) {
continue;
}
this.root.push(createHyperlinkClick(element.linkId, true));
break;
}
return super.prepForXml(context);
}
} }

View File

@ -1,9 +1,11 @@
import { expect } from "chai"; import { expect } from "chai";
import { SinonStub, stub } from "sinon"; import { SinonStub, stub } from "sinon";
import { IContext } from "@file/xml-components";
import { Formatter } from "@export/formatter"; import { Formatter } from "@export/formatter";
import * as convenienceFunctions from "@util/convenience-functions"; import * as convenienceFunctions from "@util/convenience-functions";
import { ConcreteHyperlink, TextRun } from "../";
import { Drawing, IDrawingOptions } from "./drawing"; import { Drawing, IDrawingOptions } from "./drawing";
const imageBase64Data = `iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAACzVBMVEUAAAAAAAAAAAAAAAA/AD8zMzMqKiokJCQfHx8cHBwZGRkuFxcqFSonJyckJCQiIiIfHx8eHh4cHBwoGhomGSYkJCQhISEfHx8eHh4nHR0lHBwkGyQjIyMiIiIgICAfHx8mHh4lHh4kHR0jHCMiGyIhISEgICAfHx8lHx8kHh4jHR0hHCEhISEgICAlHx8kHx8jHh4jHh4iHSIhHCEhISElICAkHx8jHx8jHh4iHh4iHSIhHSElICAkICAjHx8jHx8iHh4iHh4hHiEhHSEkICAjHx8iHx8iHx8hHh4hHiEkHSEjHSAjHx8iHx8iHx8hHh4kHiEkHiEjHSAiHx8hHx8hHh4kHiEjHiAjHSAiHx8iHx8hHx8kHh4jHiEjHiAjHiAiICAiHx8kHx8jHh4jHiEjHiAiHiAiHSAiHx8jHx8jHx8jHiAiHiAiHiAiHSAiHx8jHx8jHx8iHiAiHiAiHiAjHx8jHx8jHx8jHx8iHiAiHiAiHiAjHx8jHx8jHx8iHx8iHSAiHiAjHiAjHx8jHx8hHx8iHx8iHyAiHiAjHiAjHiAjHh4hHx8iHx8iHx8iHyAjHSAjHiAjHiAjHh4hHx8iHx8iHx8jHyAjHiAhHh4iHx8iHx8jHyAjHSAjHSAhHiAhHh4iHx8iHx8jHx8jHyAjHSAjHSAiHh4iHh4jHx8jHx8jHyAjHyAhHSAhHSAiHh4iHh4jHx8jHx8jHyAhHyAhHSAiHSAiHh4jHh4jHx8jHx8jHyAhHyAhHSAiHSAjHR4jHh4jHx8jHx8hHyAhHyAiHSAjHSAjHR4jHh4jHx8hHx8hHyAhHyAiHyAjHSAjHR4jHR4hHh4hHx8hHyAiHyAjHyAjHSAjHR4jHR4hHh4hHx8hHyAjHyAjHyAjHSAjHR4hHR4hHR4hHx8iHyAjHyAjHyAjHSAhHR4hHR4hHR4hHx8jHyAjHyAjHyAjHyC9S2xeAAAA7nRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFxgZGhscHR4fICEiIyQlJicoKSorLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZISUpLTE1OUFFSU1RVVllaW1xdXmBhYmNkZWZnaGprbG1ub3Byc3R1dnd4eXp8fn+AgYKDhIWGiImKi4yNj5CRkpOUlZaXmJmam5ydnp+goaKjpKaoqqusra6vsLGys7S1tri5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+fkZpVQAABcBJREFUGBntwftjlQMcBvDnnLNL22qzJjWlKLHFVogyty3SiFq6EZliqZGyhnSxsLlMRahYoZKRFcul5dKFCatYqWZaNKvWtrPz/A2+7/b27qRzec/lPfvl/XxgMplMJpPJZDKZAtA9HJ3ppnIez0KnSdtC0RCNznHdJrbrh85wdSlVVRaEXuoGamYi5K5430HNiTiEWHKJg05eRWgNfKeV7RxbqUhGKPV/207VupQ8is0IoX5vtFC18SqEHaK4GyHTZ2kzVR8PBTCO4oANIZL4ShNVZcOhKKeYg9DoWdhI1ec3os2VFI0JCIUez5+i6st0qJZRrEAIJCw+QdW223BG/EmKwTBc/IJ/qfp2FDrkUnwFo8U9dZyqnaPhxLqfYjyM1S3vb6p+GGOBszsojoTDSDFz6qj66R4LzvYJxVMwUNRjf1H1ywQr/megg2RzLximy8waqvbda8M5iijegVEiHjlM1W/3h+FcXesphsMY4dMOUnUgOxyuPEzxPQwRNvV3qg5Nj4BreyimwADWe/dRVTMjEm6MoGLzGwtystL6RyOY3qSqdlYU3FpLZw1VW0sK5943MvUCKwJ1noNtjs6Ohge76Zq9ZkfpigU5WWkDYuCfbs1U5HWFR8/Qq4a9W0uK5k4ZmdrTCl8spGIePLPlbqqsc1Afe83O0hULc8alDYiBd7ZyitYMeBfR55rR2fOKP6ioPk2dGvZ+UVI0d8rtqT2tcCexlqK2F3wRn5Q+YVbBqrLKOupkr9lZujAOrmS0UpTb4JeIPkNHZ+cXr6uoPk2vyuBSPhWLEKj45PQJuQWryyqP0Z14uGLdROHIRNBEXDR09EP5r62rOHCazhrD4VKPwxTH+sIA3ZPTJ+YuWV22n+IruHFDC8X2CBjnPoolcGc2FYUwzmsUWXDHsoGKLBhmN0VvuBVfTVE/AAbpaid5CB4MbaLY1QXGuIViLTyZQcVyGGMuxWPwaA0Vk2GI9RRp8Ci2iuLkIBjhT5LNUfAspZFiTwyC72KK7+DNg1SsRvCNp3gZXq2k4iEEXSHFJHgVXUlxejCCbTvFAHiXdIJiXxyCK7KJ5FHoMZGK9xBcwyg2QpdlVMxEUM2iyIMuXXZQNF+HswxMsSAAJRQjoE//eoqDCXBSTO6f1xd+O0iyNRY6jaWi1ALNYCocZROj4JdEikroVkjFk9DcStXxpdfCD2MoXodu4RUU9ptxxmXssOfxnvDVcxRTod9FxyhqLoAqis5aPhwTDp9spRgEH2Q6KLbYoKqlaKTm6Isp0C/sJMnjFvhiERXPQvUNRe9p29lhR04CdBpC8Sl8YiuncIxEuzUUg4Dkgj+paVozygY9plPMh28SaymO9kabAopREGF3vt9MzeFFl8G7lRSZ8FFGK8XX4VA8QjEd7XrM3M0OXz8YCy+qKBLgq3wqnofiTorF0Ax56Rg1J1elW+BBAsVe+My6iYq7IK6keBdOIseV2qn5Pb8f3MqkWAXf9ThM8c8lAOIotuFsF875lRrH5klRcG0+xcPwQ1oLxfeRAP4heQTnGL78X2rqlw2DK59SXAV/zKaiGMAuko5InCt68mcOan5+ohf+z1pP8lQY/GHZQMV4YD3FpXDp4qerqbF/lBWBswyi+AL+ia+maLgcRRQj4IYlY/UpauqKBsPJAxQF8NM1TRQ/RudSPAD34rK3scOuR8/HGcspxsJfOVS8NZbiGXiUtPgINU3v3WFDmx8pEuG3EiqKKVbCC1vm2iZqap5LAtCtleQf8F9sFYWDohzeJczYyQ4V2bEZFGsQgJRGqqqhS2phHTWn9lDkIhBTqWqxQZ+IsRvtdHY9AvI2VX2hW68nfqGmuQsCEl3JdjfCF8OW1bPdtwhQ0gm2mQzfRE3a7KCYj0BNZJs8+Kxf/r6WtTEI2FIqlsMfFgRB5A6KUnSe/vUkX0AnuvUIt8SjM1m6wWQymUwmk8lkMgXRf5vi8rLQxtUhAAAAAElFTkSuQmCC`; const imageBase64Data = `iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAACzVBMVEUAAAAAAAAAAAAAAAA/AD8zMzMqKiokJCQfHx8cHBwZGRkuFxcqFSonJyckJCQiIiIfHx8eHh4cHBwoGhomGSYkJCQhISEfHx8eHh4nHR0lHBwkGyQjIyMiIiIgICAfHx8mHh4lHh4kHR0jHCMiGyIhISEgICAfHx8lHx8kHh4jHR0hHCEhISEgICAlHx8kHx8jHh4jHh4iHSIhHCEhISElICAkHx8jHx8jHh4iHh4iHSIhHSElICAkICAjHx8jHx8iHh4iHh4hHiEhHSEkICAjHx8iHx8iHx8hHh4hHiEkHSEjHSAjHx8iHx8iHx8hHh4kHiEkHiEjHSAiHx8hHx8hHh4kHiEjHiAjHSAiHx8iHx8hHx8kHh4jHiEjHiAjHiAiICAiHx8kHx8jHh4jHiEjHiAiHiAiHSAiHx8jHx8jHx8jHiAiHiAiHiAiHSAiHx8jHx8jHx8iHiAiHiAiHiAjHx8jHx8jHx8jHx8iHiAiHiAiHiAjHx8jHx8jHx8iHx8iHSAiHiAjHiAjHx8jHx8hHx8iHx8iHyAiHiAjHiAjHiAjHh4hHx8iHx8iHx8iHyAjHSAjHiAjHiAjHh4hHx8iHx8iHx8jHyAjHiAhHh4iHx8iHx8jHyAjHSAjHSAhHiAhHh4iHx8iHx8jHx8jHyAjHSAjHSAiHh4iHh4jHx8jHx8jHyAjHyAhHSAhHSAiHh4iHh4jHx8jHx8jHyAhHyAhHSAiHSAiHh4jHh4jHx8jHx8jHyAhHyAhHSAiHSAjHR4jHh4jHx8jHx8hHyAhHyAiHSAjHSAjHR4jHh4jHx8hHx8hHyAhHyAiHyAjHSAjHR4jHR4hHh4hHx8hHyAiHyAjHyAjHSAjHR4jHR4hHh4hHx8hHyAjHyAjHyAjHSAjHR4hHR4hHR4hHx8iHyAjHyAjHyAjHSAhHR4hHR4hHR4hHx8jHyAjHyAjHyAjHyC9S2xeAAAA7nRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFxgZGhscHR4fICEiIyQlJicoKSorLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZISUpLTE1OUFFSU1RVVllaW1xdXmBhYmNkZWZnaGprbG1ub3Byc3R1dnd4eXp8fn+AgYKDhIWGiImKi4yNj5CRkpOUlZaXmJmam5ydnp+goaKjpKaoqqusra6vsLGys7S1tri5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+fkZpVQAABcBJREFUGBntwftjlQMcBvDnnLNL22qzJjWlKLHFVogyty3SiFq6EZliqZGyhnSxsLlMRahYoZKRFcul5dKFCatYqWZaNKvWtrPz/A2+7/b27qRzec/lPfvl/XxgMplMJpPJZDKZAtA9HJ3ppnIez0KnSdtC0RCNznHdJrbrh85wdSlVVRaEXuoGamYi5K5430HNiTiEWHKJg05eRWgNfKeV7RxbqUhGKPV/207VupQ8is0IoX5vtFC18SqEHaK4GyHTZ2kzVR8PBTCO4oANIZL4ShNVZcOhKKeYg9DoWdhI1ec3os2VFI0JCIUez5+i6st0qJZRrEAIJCw+QdW223BG/EmKwTBc/IJ/qfp2FDrkUnwFo8U9dZyqnaPhxLqfYjyM1S3vb6p+GGOBszsojoTDSDFz6qj66R4LzvYJxVMwUNRjf1H1ywQr/megg2RzLximy8waqvbda8M5iijegVEiHjlM1W/3h+FcXesphsMY4dMOUnUgOxyuPEzxPQwRNvV3qg5Nj4BreyimwADWe/dRVTMjEm6MoGLzGwtystL6RyOY3qSqdlYU3FpLZw1VW0sK5943MvUCKwJ1noNtjs6Ohge76Zq9ZkfpigU5WWkDYuCfbs1U5HWFR8/Qq4a9W0uK5k4ZmdrTCl8spGIePLPlbqqsc1Afe83O0hULc8alDYiBd7ZyitYMeBfR55rR2fOKP6ioPk2dGvZ+UVI0d8rtqT2tcCexlqK2F3wRn5Q+YVbBqrLKOupkr9lZujAOrmS0UpTb4JeIPkNHZ+cXr6uoPk2vyuBSPhWLEKj45PQJuQWryyqP0Z14uGLdROHIRNBEXDR09EP5r62rOHCazhrD4VKPwxTH+sIA3ZPTJ+YuWV22n+IruHFDC8X2CBjnPoolcGc2FYUwzmsUWXDHsoGKLBhmN0VvuBVfTVE/AAbpaid5CB4MbaLY1QXGuIViLTyZQcVyGGMuxWPwaA0Vk2GI9RRp8Ci2iuLkIBjhT5LNUfAspZFiTwyC72KK7+DNg1SsRvCNp3gZXq2k4iEEXSHFJHgVXUlxejCCbTvFAHiXdIJiXxyCK7KJ5FHoMZGK9xBcwyg2QpdlVMxEUM2iyIMuXXZQNF+HswxMsSAAJRQjoE//eoqDCXBSTO6f1xd+O0iyNRY6jaWi1ALNYCocZROj4JdEikroVkjFk9DcStXxpdfCD2MoXodu4RUU9ptxxmXssOfxnvDVcxRTod9FxyhqLoAqis5aPhwTDp9spRgEH2Q6KLbYoKqlaKTm6Isp0C/sJMnjFvhiERXPQvUNRe9p29lhR04CdBpC8Sl8YiuncIxEuzUUg4Dkgj+paVozygY9plPMh28SaymO9kabAopREGF3vt9MzeFFl8G7lRSZ8FFGK8XX4VA8QjEd7XrM3M0OXz8YCy+qKBLgq3wqnofiTorF0Ax56Rg1J1elW+BBAsVe+My6iYq7IK6keBdOIseV2qn5Pb8f3MqkWAXf9ThM8c8lAOIotuFsF875lRrH5klRcG0+xcPwQ1oLxfeRAP4heQTnGL78X2rqlw2DK59SXAV/zKaiGMAuko5InCt68mcOan5+ohf+z1pP8lQY/GHZQMV4YD3FpXDp4qerqbF/lBWBswyi+AL+ia+maLgcRRQj4IYlY/UpauqKBsPJAxQF8NM1TRQ/RudSPAD34rK3scOuR8/HGcspxsJfOVS8NZbiGXiUtPgINU3v3WFDmx8pEuG3EiqKKVbCC1vm2iZqap5LAtCtleQf8F9sFYWDohzeJczYyQ4V2bEZFGsQgJRGqqqhS2phHTWn9lDkIhBTqWqxQZ+IsRvtdHY9AvI2VX2hW68nfqGmuQsCEl3JdjfCF8OW1bPdtwhQ0gm2mQzfRE3a7KCYj0BNZJs8+Kxf/r6WtTEI2FIqlsMfFgRB5A6KUnSe/vUkX0AnuvUIt8SjM1m6wWQymUwmk8lkMgXRf5vi8rLQxtUhAAAAAElFTkSuQmCC`;
@ -450,5 +452,257 @@ describe("Drawing", () => {
], ],
}); });
}); });
it("should create a drawing with a hyperlink", () => {
currentBreak = createDrawing({
floating: {
horizontalPosition: {
offset: 0,
},
verticalPosition: {
offset: 0,
},
},
});
const tree = new Formatter().format(currentBreak, {
stack: [new ConcreteHyperlink([new TextRun("Test")], "1")],
} as unknown as IContext);
expect(tree).to.deep.equal({
"w:drawing": [
{
"wp:anchor": [
{
_attr: {
allowOverlap: "1",
behindDoc: "0",
distB: 0,
distL: 0,
distR: 0,
distT: 0,
layoutInCell: "1",
locked: "0",
relativeHeight: 952500,
simplePos: "0",
},
},
{
"wp:simplePos": {
_attr: {
x: 0,
y: 0,
},
},
},
{
"wp:positionH": [
{
_attr: {
relativeFrom: "page",
},
},
{
"wp:posOffset": ["0"],
},
],
},
{
"wp:positionV": [
{
_attr: {
relativeFrom: "page",
},
},
{
"wp:posOffset": ["0"],
},
],
},
{
"wp:extent": {
_attr: {
cx: 952500,
cy: 952500,
},
},
},
{
"wp:effectExtent": {
_attr: {
b: 0,
l: 0,
r: 0,
t: 0,
},
},
},
{
"wp:wrapNone": {},
},
{
"wp:docPr": [
{
_attr: {
descr: "",
id: 0,
name: "",
title: "",
},
},
{
"a:hlinkClick": {
_attr: {
"r:id": "rId1",
"xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
},
},
},
],
},
{
"wp:cNvGraphicFramePr": [
{
"a:graphicFrameLocks": {
_attr: {
// tslint:disable-next-line:object-literal-key-quotes
noChangeAspect: 1,
"xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
},
},
},
],
},
{
"a:graphic": [
{
_attr: {
"xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
},
},
{
"a:graphicData": [
{
_attr: {
uri: "http://schemas.openxmlformats.org/drawingml/2006/picture",
},
},
{
"pic:pic": [
{
_attr: {
"xmlns:pic": "http://schemas.openxmlformats.org/drawingml/2006/picture",
},
},
{
"pic:nvPicPr": [
{
"pic:cNvPr": [
{
_attr: {
descr: "",
id: 0,
name: "",
},
},
{
"a:hlinkClick": {
_attr: {
"r:id": "rId1",
},
},
},
],
},
{
"pic:cNvPicPr": [
{
"a:picLocks": {
_attr: {
noChangeArrowheads: 1,
noChangeAspect: 1,
},
},
},
],
},
],
},
{
"pic:blipFill": [
{
"a:blip": {
_attr: {
// tslint:disable-next-line:object-literal-key-quotes
cstate: "none",
"r:embed": "rId{test.jpg}",
},
},
},
{
"a:srcRect": {},
},
{
"a:stretch": [
{
"a:fillRect": {},
},
],
},
],
},
{
"pic:spPr": [
{
_attr: {
bwMode: "auto",
},
},
{
"a:xfrm": [
{
_attr: {},
},
{
"a:off": {
_attr: {
x: 0,
y: 0,
},
},
},
{
"a:ext": {
_attr: {
cx: 952500,
cy: 952500,
},
},
},
],
},
{
"a:prstGeom": [
{
_attr: {
prst: "rect",
},
},
{
"a:avLst": {},
},
],
},
],
},
],
},
],
},
],
},
],
},
],
});
});
}); });
}); });

View File

@ -1,6 +1,21 @@
import { XmlComponent } from "@file/xml-components"; import { IContext, IXmlableObject, XmlComponent } from "@file/xml-components";
import { createHyperlinkClick } from "@file/drawing/doc-properties/doc-properties-children";
import { ConcreteHyperlink } from "@file/paragraph";
import { NonVisualPropertiesAttributes } from "./non-visual-properties-attributes"; import { NonVisualPropertiesAttributes } from "./non-visual-properties-attributes";
// <complexType name="CT_NonVisualDrawingProps">
// <sequence>
// <element name="hlinkClick" type="CT_Hyperlink" minOccurs="0" maxOccurs="1" />
// <element name="hlinkHover" type="CT_Hyperlink" minOccurs="0" maxOccurs="1" />
// <element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1" />
// </sequence>
// <attribute name="id" type="ST_DrawingElementId" use="required" />
// <attribute name="name" type="xsd:string" use="required" />
// <attribute name="descr" type="xsd:string" use="optional" default="" />
// <attribute name="hidden" type="xsd:boolean" use="optional" default="false" />
// </complexType>
export class NonVisualProperties extends XmlComponent { export class NonVisualProperties extends XmlComponent {
public constructor() { public constructor() {
super("pic:cNvPr"); super("pic:cNvPr");
@ -13,4 +28,19 @@ export class NonVisualProperties extends XmlComponent {
}), }),
); );
} }
public prepForXml(context: IContext): IXmlableObject | undefined {
for (let i = context.stack.length - 1; i >= 0; i--) {
const element = context.stack[i];
if (!(element instanceof ConcreteHyperlink)) {
continue;
}
this.root.push(createHyperlinkClick(element.linkId, false));
break;
}
return super.prepForXml(context);
}
} }

5
src/file/file-child.ts Normal file
View File

@ -0,0 +1,5 @@
import { XmlComponent } from "@file/xml-components";
export class FileChild extends XmlComponent {
public readonly fileChild = Symbol();
}

View File

@ -1,11 +0,0 @@
import { IDocumentTemplate } from "../import-dotx";
export interface IFileProperties {
readonly template?: IDocumentTemplate;
}
// Needed because of: https://github.com/s-panferov/awesome-typescript-loader/issues/432
/**
* @ignore
*/
export const WORKAROUND = "";

View File

@ -1,12 +1,11 @@
import { expect } from "chai"; import { expect } from "chai";
import { Formatter } from "@export/formatter"; import { Formatter } from "@export/formatter";
import { sectionMarginDefaults, sectionPageSizeDefaults } from "./document";
import { sectionMarginDefaults, sectionPageSizeDefaults } from "./document";
import { File } from "./file"; import { File } from "./file";
import { Footer, Header } from "./header"; import { Footer, Header } from "./header";
import { Paragraph } from "./paragraph"; import { Paragraph } from "./paragraph";
import { Media } from "./media";
const PAGE_SIZE_DEFAULTS = { const PAGE_SIZE_DEFAULTS = {
"w:h": sectionPageSizeDefaults.HEIGHT, "w:h": sectionPageSizeDefaults.HEIGHT,
@ -433,29 +432,6 @@ describe("File", () => {
}); });
}); });
describe("#templates", () => {
// Test will be deprecated when import-dotx and templates are deprecated
it("should work with template", () => {
const doc = new File(
{
sections: [],
},
{
template: {
currentRelationshipId: 1,
headers: [],
footers: [],
styles: "",
titlePageIsDefined: true,
media: new Media(),
},
},
);
expect(doc).to.not.be.undefined;
});
});
describe("#externalStyles", () => { describe("#externalStyles", () => {
it("should work with external styles", () => { it("should work with external styles", () => {
const doc = new File({ const doc = new File({

View File

@ -4,22 +4,19 @@ import { CoreProperties, IPropertiesOptions } from "./core-properties";
import { CustomProperties } from "./custom-properties"; import { CustomProperties } from "./custom-properties";
import { DocumentWrapper } from "./document-wrapper"; import { DocumentWrapper } from "./document-wrapper";
import { HeaderFooterReferenceType, ISectionPropertiesOptions } from "./document/body/section-properties"; import { HeaderFooterReferenceType, ISectionPropertiesOptions } from "./document/body/section-properties";
import { IFileProperties } from "./file-properties";
import { FooterWrapper, IDocumentFooter } from "./footer-wrapper"; import { FooterWrapper, IDocumentFooter } from "./footer-wrapper";
import { FootnotesWrapper } from "./footnotes-wrapper"; import { FootnotesWrapper } from "./footnotes-wrapper";
import { Footer, Header } from "./header"; import { Footer, Header } from "./header";
import { HeaderWrapper, IDocumentHeader } from "./header-wrapper"; import { HeaderWrapper, IDocumentHeader } from "./header-wrapper";
import { Media } from "./media"; import { Media } from "./media";
import { Numbering } from "./numbering"; import { Numbering } from "./numbering";
import { Paragraph } from "./paragraph";
import { Comments } from "./paragraph/run/comment-run"; import { Comments } from "./paragraph/run/comment-run";
import { Relationships } from "./relationships"; import { Relationships } from "./relationships";
import { Settings } from "./settings"; import { Settings } from "./settings";
import { Styles } from "./styles"; 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 { Table } from "./table"; import { FileChild } from "./file-child";
import { TableOfContents } from "./table-of-contents";
export interface ISectionOptions { export interface ISectionOptions {
readonly headers?: { readonly headers?: {
@ -33,7 +30,7 @@ export interface ISectionOptions {
readonly even?: Footer; readonly even?: Footer;
}; };
readonly properties?: ISectionPropertiesOptions; readonly properties?: ISectionPropertiesOptions;
readonly children: readonly (Paragraph | Table | TableOfContents)[]; readonly children: readonly FileChild[];
} }
export class File { export class File {
@ -57,7 +54,7 @@ export class File {
private readonly styles: Styles; private readonly styles: Styles;
private readonly comments: Comments; private readonly comments: Comments;
public constructor(options: IPropertiesOptions, fileProperties: IFileProperties = {}) { public constructor(options: IPropertiesOptions) {
this.coreProperties = new CoreProperties({ this.coreProperties = new CoreProperties({
...options, ...options,
creator: options.creator ?? "Un-named", creator: options.creator ?? "Un-named",
@ -82,20 +79,9 @@ export class File {
updateFields: options.features?.updateFields, updateFields: options.features?.updateFields,
}); });
this.media = fileProperties.template && fileProperties.template.media ? fileProperties.template.media : new Media(); this.media = new Media();
if (fileProperties.template) { if (options.externalStyles) {
this.currentRelationshipId = fileProperties.template.currentRelationshipId + 1;
}
// set up styles
if (fileProperties.template && options.externalStyles) {
throw Error("can not use both template and external styles");
}
if (fileProperties.template && fileProperties.template.styles) {
const stylesFactory = new ExternalStylesFactory();
this.styles = stylesFactory.newInstance(fileProperties.template.styles);
} else if (options.externalStyles) {
const stylesFactory = new ExternalStylesFactory(); const stylesFactory = new ExternalStylesFactory();
this.styles = stylesFactory.newInstance(options.externalStyles); this.styles = stylesFactory.newInstance(options.externalStyles);
} else if (options.styles) { } else if (options.styles) {
@ -112,18 +98,6 @@ export class File {
this.addDefaultRelationships(); this.addDefaultRelationships();
if (fileProperties.template && fileProperties.template.headers) {
for (const templateHeader of fileProperties.template.headers) {
this.addHeaderToDocument(templateHeader.header, templateHeader.type);
}
}
if (fileProperties.template && fileProperties.template.footers) {
for (const templateFooter of fileProperties.template.footers) {
this.addFooterToDocument(templateFooter.footer, templateFooter.type);
}
}
for (const section of options.sections) { for (const section of options.sections) {
this.addSection(section); this.addSection(section);
} }

View File

@ -1,7 +1,6 @@
export * from "./paragraph"; export * from "./paragraph";
export * from "./table"; export * from "./table";
export * from "./file"; export * from "./file";
export * from "./file-properties";
export * from "./numbering"; export * from "./numbering";
export * from "./media"; export * from "./media";
export * from "./drawing"; export * from "./drawing";

View File

@ -15,94 +15,28 @@ describe("Media", () => {
(convenienceFunctions.uniqueId as SinonStub).restore(); (convenienceFunctions.uniqueId as SinonStub).restore();
}); });
describe("#addMedia", () => { describe("#Array", () => {
it("should add media", () => { it("Get images as array", () => {
const image = new Media().addMedia("", {
width: 100,
height: 100,
});
expect(image.fileName).to.equal("test.png");
expect(image.transformation).to.deep.equal({
pixels: {
x: 100,
y: 100,
},
flip: undefined,
emus: {
x: 952500,
y: 952500,
},
rotation: undefined,
});
});
it("should return UInt8Array if atob is present", () => {
// eslint-disable-next-line functional/immutable-data
global.atob = () => "atob result";
const image = new Media().addMedia("", {
width: 100,
height: 100,
});
expect(image.stream).to.be.an.instanceof(Uint8Array);
// eslint-disable-next-line @typescript-eslint/no-explicit-any, functional/immutable-data
(global as any).atob = undefined;
});
it("should use data as is if its not a string", () => {
// eslint-disable-next-line functional/immutable-data
global.atob = () => "atob result";
const image = new Media().addMedia(Buffer.from(""), {
width: 100,
height: 100,
});
expect(image.stream).to.be.an.instanceof(Uint8Array);
// eslint-disable-next-line @typescript-eslint/no-explicit-any, functional/immutable-data
(global as any).atob = undefined;
});
});
describe("#addImage", () => {
it("should add media", () => {
const media = new Media(); const media = new Media();
media.addMedia("", {
width: 100,
height: 100,
});
media.addImage("test2.png", { media.addImage("test2.png", {
stream: Buffer.from(""), stream: Buffer.from(""),
fileName: "", fileName: "test.png",
transformation: { transformation: {
pixels: { pixels: {
x: Math.round(1), x: Math.round(100),
y: Math.round(1), y: Math.round(100),
},
flip: {
vertical: true,
horizontal: true,
}, },
emus: { emus: {
x: Math.round(1 * 9525), x: Math.round(1 * 9525),
y: Math.round(1 * 9525), y: Math.round(1 * 9525),
}, },
},
});
expect(media.Array).to.be.lengthOf(2);
});
});
describe("#Array", () => {
it("Get images as array", () => {
const media = new Media();
media.addMedia("", {
width: 100,
height: 100,
flip: {
vertical: true,
horizontal: true,
},
rotation: 90, rotation: 90,
},
}); });
const array = media.Array; const array = media.Array;
@ -121,10 +55,10 @@ describe("Media", () => {
horizontal: true, horizontal: true,
}, },
emus: { emus: {
x: 952500, x: 9525,
y: 952500, y: 9525,
}, },
rotation: 5400000, rotation: 90,
}); });
}); });
}); });

View File

@ -1,5 +1,3 @@
import { uniqueId } from "@util/convenience-functions";
import { IMediaData } from "./data"; import { IMediaData } from "./data";
export interface IMediaTransformation { export interface IMediaTransformation {
@ -20,33 +18,6 @@ export class Media {
this.map = new Map<string, IMediaData>(); this.map = new Map<string, IMediaData>();
} }
public addMedia(data: Buffer | string | Uint8Array | ArrayBuffer, transformation: IMediaTransformation): IMediaData {
const key = `${uniqueId()}.png`;
const newData = typeof data === "string" ? this.convertDataURIToBinary(data) : data;
const imageData: IMediaData = {
stream: newData,
fileName: key,
transformation: {
pixels: {
x: Math.round(transformation.width),
y: Math.round(transformation.height),
},
emus: {
x: Math.round(transformation.width * 9525),
y: Math.round(transformation.height * 9525),
},
flip: transformation.flip,
rotation: transformation.rotation ? transformation.rotation * 60000 : undefined,
},
};
this.map.set(key, imageData);
return imageData;
}
public addImage(key: string, mediaData: IMediaData): void { public addImage(key: string, mediaData: IMediaData): void {
this.map.set(key, mediaData); this.map.set(key, mediaData);
} }
@ -54,24 +25,4 @@ export class Media {
public get Array(): readonly IMediaData[] { public get Array(): readonly IMediaData[] {
return Array.from(this.map.values()); return Array.from(this.map.values());
} }
private convertDataURIToBinary(dataURI: string): Uint8Array {
// https://gist.github.com/borismus/1032746
// https://github.com/mafintosh/base64-to-uint8array
const BASE64_MARKER = ";base64,";
const base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
if (typeof atob === "function") {
return new Uint8Array(
atob(dataURI.substring(base64Index))
.split("")
.map((c) => c.charCodeAt(0)),
);
} else {
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
const b = require("buf" + "fer");
return new b.Buffer(dataURI, "base64");
}
}
} }

View File

@ -12,9 +12,11 @@ describe("ConcreteNumbering", () => {
abstractNumId: 1, abstractNumId: 1,
reference: "1", reference: "1",
instance: 0, instance: 0,
overrideLevel: { overrideLevels: [
{
num: 3, num: 3,
}, },
],
}); });
const tree = new Formatter().format(concreteNumbering); const tree = new Formatter().format(concreteNumbering);
@ -44,16 +46,61 @@ describe("ConcreteNumbering", () => {
}); });
}); });
it("sets a new override level for two different level numbers", () => {
const concreteNumbering = new ConcreteNumbering({
numId: 0,
abstractNumId: 1,
reference: "1",
instance: 0,
overrideLevels: [{ num: 3 }, { num: 5 }],
});
const tree = new Formatter().format(concreteNumbering);
expect(tree).to.deep.equal({
"w:num": [
{
_attr: {
"w:numId": 0,
},
},
{
"w:abstractNumId": {
_attr: {
"w:val": 1,
},
},
},
{
"w:lvlOverride": {
_attr: {
"w:ilvl": 3,
},
},
},
{
"w:lvlOverride": {
_attr: {
"w:ilvl": 5,
},
},
},
],
});
});
it("sets the startOverride element if start is given", () => { it("sets the startOverride element if start is given", () => {
const concreteNumbering = new ConcreteNumbering({ const concreteNumbering = new ConcreteNumbering({
numId: 0, numId: 0,
abstractNumId: 1, abstractNumId: 1,
reference: "1", reference: "1",
instance: 0, instance: 0,
overrideLevel: { overrideLevels: [
{
num: 1, num: 1,
start: 9, start: 9,
}, },
],
}); });
const tree = new Formatter().format(concreteNumbering); const tree = new Formatter().format(concreteNumbering);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -90,15 +137,143 @@ describe("ConcreteNumbering", () => {
}); });
}); });
it("sets the startOverride element for several levels if start is given", () => {
const concreteNumbering = new ConcreteNumbering({
numId: 0,
abstractNumId: 1,
reference: "1",
instance: 0,
overrideLevels: [
{
num: 1,
start: 9,
},
{
num: 3,
start: 10,
},
],
});
const tree = new Formatter().format(concreteNumbering);
expect(tree).to.deep.equal({
"w:num": [
{
_attr: {
"w:numId": 0,
},
},
{
"w:abstractNumId": {
_attr: {
"w:val": 1,
},
},
},
{
"w:lvlOverride": [
{
_attr: {
"w:ilvl": 1,
},
},
{
"w:startOverride": {
_attr: {
"w:val": 9,
},
},
},
],
},
{
"w:lvlOverride": [
{
_attr: {
"w:ilvl": 3,
},
},
{
"w:startOverride": {
_attr: {
"w:val": 10,
},
},
},
],
},
],
});
});
it("Mix of overrideLevels with start and without", () => {
const concreteNumbering = new ConcreteNumbering({
numId: 0,
abstractNumId: 1,
reference: "1",
instance: 0,
overrideLevels: [
{
num: 1,
start: 9,
},
{
num: 3,
},
],
});
const tree = new Formatter().format(concreteNumbering);
expect(tree).to.deep.equal({
"w:num": [
{
_attr: {
"w:numId": 0,
},
},
{
"w:abstractNumId": {
_attr: {
"w:val": 1,
},
},
},
{
"w:lvlOverride": [
{
_attr: {
"w:ilvl": 1,
},
},
{
"w:startOverride": {
_attr: {
"w:val": 9,
},
},
},
],
},
{
"w:lvlOverride": {
_attr: {
"w:ilvl": 3,
},
},
},
],
});
});
it("sets the lvl element if overrideLevel.Level is accessed", () => { it("sets the lvl element if overrideLevel.Level is accessed", () => {
const concreteNumbering = new ConcreteNumbering({ const concreteNumbering = new ConcreteNumbering({
numId: 0, numId: 0,
abstractNumId: 1, abstractNumId: 1,
reference: "1", reference: "1",
instance: 0, instance: 0,
overrideLevel: { overrideLevels: [
{
num: 1, num: 1,
}, },
],
}); });
const tree = new Formatter().format(concreteNumbering); const tree = new Formatter().format(concreteNumbering);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({

View File

@ -18,15 +18,17 @@ class NumAttributes extends XmlAttributeComponent<{
protected readonly xmlKeys = { numId: "w:numId" }; protected readonly xmlKeys = { numId: "w:numId" };
} }
interface IOverrideLevel {
readonly num: number;
readonly start?: number;
}
export interface IConcreteNumberingOptions { export interface IConcreteNumberingOptions {
readonly numId: number; readonly numId: number;
readonly abstractNumId: number; readonly abstractNumId: number;
readonly reference: string; readonly reference: string;
readonly instance: number; readonly instance: number;
readonly overrideLevel?: { readonly overrideLevels?: readonly IOverrideLevel[];
readonly num: number;
readonly start?: number;
};
} }
// <xsd:complexType name="CT_Numbering"> // <xsd:complexType name="CT_Numbering">
@ -60,8 +62,10 @@ export class ConcreteNumbering extends XmlComponent {
this.root.push(new AbstractNumId(decimalNumber(options.abstractNumId))); this.root.push(new AbstractNumId(decimalNumber(options.abstractNumId)));
if (options.overrideLevel) { if (options.overrideLevels && options.overrideLevels.length) {
this.root.push(new LevelOverride(options.overrideLevel.num, options.overrideLevel.start)); for (const level of options.overrideLevels) {
this.root.push(new LevelOverride(level.num, level.start));
}
} }
} }
} }

View File

@ -164,10 +164,12 @@ export class Numbering extends XmlComponent {
abstractNumId: abstractNumbering.id, abstractNumId: abstractNumbering.id,
reference: "default-bullet-numbering", reference: "default-bullet-numbering",
instance: 0, instance: 0,
overrideLevel: { overrideLevels: [
{
num: 0, num: 0,
start: 1, start: 1,
}, },
],
}), }),
); );

View File

@ -1,16 +1,23 @@
// http://officeopenxml.com/WPindentation.php // http://officeopenxml.com/WPindentation.php
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { NextAttributeComponent, XmlComponent } from "@file/xml-components";
import { signedTwipsMeasureValue, twipsMeasureValue } from "@util/values"; import { PositiveUniversalMeasure, signedTwipsMeasureValue, twipsMeasureValue, UniversalMeasure } from "@util/values";
export interface IIndentAttributesProperties { export interface IIndentAttributesProperties {
readonly start?: number | string; readonly start?: number | UniversalMeasure;
readonly end?: number | string; readonly end?: number | UniversalMeasure;
readonly left?: number | string; readonly left?: number | UniversalMeasure;
readonly right?: number | string; readonly right?: number | UniversalMeasure;
readonly hanging?: number | string; readonly hanging?: number | PositiveUniversalMeasure;
readonly firstLine?: number | string; readonly firstLine?: number | PositiveUniversalMeasure;
} }
// <xsd:complexType name="CT_PPrBase">
// <xsd:sequence>
// ...
// <xsd:element name="ind" type="CT_Ind" minOccurs="0"/>
export class Indent extends XmlComponent {
public constructor({ start, end, left, right, hanging, firstLine }: IIndentAttributesProperties) {
super("w:ind");
// <xsd:complexType name="CT_Ind"> // <xsd:complexType name="CT_Ind">
// <xsd:attribute name="start" type="ST_SignedTwipsMeasure" use="optional"/> // <xsd:attribute name="start" type="ST_SignedTwipsMeasure" use="optional"/>
// <xsd:attribute name="startChars" type="ST_DecimalNumber" use="optional"/> // <xsd:attribute name="startChars" type="ST_DecimalNumber" use="optional"/>
@ -25,32 +32,39 @@ export interface IIndentAttributesProperties {
// <xsd:attribute name="firstLine" type="s:ST_TwipsMeasure" use="optional"/> // <xsd:attribute name="firstLine" type="s:ST_TwipsMeasure" use="optional"/>
// <xsd:attribute name="firstLineChars" type="ST_DecimalNumber" use="optional"/> // <xsd:attribute name="firstLineChars" type="ST_DecimalNumber" use="optional"/>
// </xsd:complexType> // </xsd:complexType>
class IndentAttributes extends XmlAttributeComponent<IIndentAttributesProperties> {
protected readonly xmlKeys = {
start: "w:start",
end: "w:end",
left: "w:left",
right: "w:right",
hanging: "w:hanging",
firstLine: "w:firstLine",
};
}
// <xsd:complexType name="CT_PPrBase">
// <xsd:sequence>
// ...
// <xsd:element name="ind" type="CT_Ind" minOccurs="0"/>
export class Indent extends XmlComponent {
public constructor({ start, end, left, right, hanging, firstLine }: IIndentAttributesProperties) {
super("w:ind");
this.root.push( this.root.push(
new IndentAttributes({ new NextAttributeComponent<{
start: start === undefined ? undefined : signedTwipsMeasureValue(start), readonly start?: number | UniversalMeasure;
end: end === undefined ? undefined : signedTwipsMeasureValue(end), readonly end?: number | UniversalMeasure;
left: left === undefined ? undefined : signedTwipsMeasureValue(left), readonly left?: number | UniversalMeasure;
right: right === undefined ? undefined : signedTwipsMeasureValue(right), readonly right?: number | UniversalMeasure;
hanging: hanging === undefined ? undefined : twipsMeasureValue(hanging), readonly hanging?: number | PositiveUniversalMeasure;
firstLine: firstLine === undefined ? undefined : twipsMeasureValue(firstLine), readonly firstLine?: number | PositiveUniversalMeasure;
}>({
start: {
key: "w:start",
value: start === undefined ? undefined : signedTwipsMeasureValue(start),
},
end: {
key: "w:end",
value: end === undefined ? undefined : signedTwipsMeasureValue(end),
},
left: {
key: "w:left",
value: left === undefined ? undefined : signedTwipsMeasureValue(left),
},
right: {
key: "w:right",
value: right === undefined ? undefined : signedTwipsMeasureValue(right),
},
hanging: {
key: "w:hanging",
value: hanging === undefined ? undefined : twipsMeasureValue(hanging),
},
firstLine: {
key: "w:firstLine",
value: firstLine === undefined ? undefined : twipsMeasureValue(firstLine),
},
}), }),
); );
} }

View File

@ -954,6 +954,7 @@ describe("Paragraph", () => {
paragraph.prepForXml({ paragraph.prepForXml({
viewWrapper: viewWrapperMock, viewWrapper: viewWrapperMock,
file: file, file: file,
stack: [],
}); });
const tree = new Formatter().format(paragraph); const tree = new Formatter().format(paragraph);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({

View File

@ -1,7 +1,8 @@
// http://officeopenxml.com/WPparagraph.php // http://officeopenxml.com/WPparagraph.php
import { FootnoteReferenceRun } from "@file/footnotes"; import { FootnoteReferenceRun } from "@file/footnotes";
import { IContext, IXmlableObject, XmlComponent } from "@file/xml-components"; import { IContext, IXmlableObject } from "@file/xml-components";
import { uniqueId } from "@util/convenience-functions"; import { uniqueId } from "@util/convenience-functions";
import { FileChild } from "@file/file-child";
import { TargetModeType } from "../relationships/relationship/relationship"; import { TargetModeType } from "../relationships/relationship/relationship";
import { DeletedTextRun, InsertedTextRun } from "../track-revision"; import { DeletedTextRun, InsertedTextRun } from "../track-revision";
@ -39,7 +40,7 @@ export interface IParagraphOptions extends IParagraphPropertiesOptions {
readonly children?: readonly ParagraphChild[]; readonly children?: readonly ParagraphChild[];
} }
export class Paragraph extends XmlComponent { export class Paragraph extends FileChild {
private readonly properties: ParagraphProperties; private readonly properties: ParagraphProperties;
public constructor(options: string | IParagraphOptions) { public constructor(options: string | IParagraphOptions) {

View File

@ -31,6 +31,7 @@ describe("ParagraphProperties", () => {
} as File, } as File,
// tslint:disable-next-line: no-object-literal-type-assertion // tslint:disable-next-line: no-object-literal-type-assertion
viewWrapper: new DocumentWrapper({ background: {} }), viewWrapper: new DocumentWrapper({ background: {} }),
stack: [],
}); });
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -124,6 +125,21 @@ describe("ParagraphProperties", () => {
}); });
}); });
it("should create with the autoSpaceEastAsianText property", () => {
const properties = new ParagraphProperties({
autoSpaceEastAsianText: true,
});
const tree = new Formatter().format(properties);
expect(tree).to.deep.equal({
"w:pPr": [
{
"w:autoSpaceDN": {},
},
],
});
});
it("should create with the wordWrap property", () => { it("should create with the wordWrap property", () => {
const properties = new ParagraphProperties({ const properties = new ParagraphProperties({
wordWrap: true, wordWrap: true,

View File

@ -53,6 +53,11 @@ export interface IParagraphPropertiesOptions extends IParagraphStylePropertiesOp
readonly suppressLineNumbers?: boolean; readonly suppressLineNumbers?: boolean;
readonly wordWrap?: boolean; readonly wordWrap?: 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 only works in Microsoft Word. It is not part of the ECMA-376 OOXML standard.
*/
readonly autoSpaceEastAsianText?: boolean;
} }
export class ParagraphProperties extends IgnoreIfEmptyXmlComponent { export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
@ -179,6 +184,10 @@ export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
if (options.suppressLineNumbers !== undefined) { if (options.suppressLineNumbers !== undefined) {
this.push(new OnOffElement("w:suppressLineNumbers", options.suppressLineNumbers)); this.push(new OnOffElement("w:suppressLineNumbers", options.suppressLineNumbers));
} }
if (options.autoSpaceEastAsianText !== undefined) {
this.push(new OnOffElement("w:autoSpaceDN", options.autoSpaceEastAsianText));
}
} }
public push(item: XmlComponent): void { public push(item: XmlComponent): void {

View File

@ -2,6 +2,8 @@ import { expect } from "chai";
import * as sinon from "sinon"; import * as sinon from "sinon";
import { Formatter } from "@export/formatter"; import { Formatter } from "@export/formatter";
import { Paragraph } from "../paragraph";
import { Comment, CommentRangeEnd, CommentRangeStart, CommentReference, Comments } from "./comment-run"; import { Comment, CommentRangeEnd, CommentRangeStart, CommentReference, Comments } from "./comment-run";
describe("CommentRangeStart", () => { describe("CommentRangeStart", () => {
@ -44,7 +46,7 @@ describe("Comment", () => {
let clock: sinon.SinonFakeTimers; let clock: sinon.SinonFakeTimers;
beforeEach(() => { beforeEach(() => {
const now = new Date(1999, 0, 1); const now = new Date("1999-01-01T00:00:00.000Z");
clock = sinon.useFakeTimers(now.getTime()); clock = sinon.useFakeTimers(now.getTime());
}); });
@ -56,8 +58,8 @@ describe("Comment", () => {
it("should create", () => { it("should create", () => {
const component = new Comment({ const component = new Comment({
id: 0, id: 0,
text: "test-comment", children: [new Paragraph("test-comment")],
date: new Date(1999, 0, 1), date: new Date("1999-01-01T00:00:00.000Z"),
}); });
const tree = new Formatter().format(component); const tree = new Formatter().format(component);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -88,7 +90,7 @@ describe("Comment", () => {
it("should create by using default date", () => { it("should create by using default date", () => {
const component = new Comment({ const component = new Comment({
id: 0, id: 0,
text: "test-comment", children: [new Paragraph("test-comment")],
}); });
const tree = new Formatter().format(component); const tree = new Formatter().format(component);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -125,13 +127,13 @@ describe("Comments", () => {
children: [ children: [
{ {
id: 0, id: 0,
text: "test-comment", children: [new Paragraph("test-comment")],
date: new Date(1999, 0, 1), date: new Date("1999-01-01T00:00:00.000Z"),
}, },
{ {
id: 1, id: 1,
text: "test-comment-2", children: [new Paragraph("test-comment-2")],
date: new Date(1999, 0, 1), date: new Date("1999-01-01T00:00:00.000Z"),
}, },
], ],
}); });

View File

@ -1,11 +1,9 @@
import { Paragraph } from "@file/paragraph"; import { FileChild } from "@file/file-child";
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
import { TextRun } from "./text-run";
export interface ICommentOptions { export interface ICommentOptions {
readonly id: number; readonly id: number;
readonly text: string; readonly children: readonly FileChild[];
readonly initials?: string; readonly initials?: string;
readonly author?: string; readonly author?: string;
readonly date?: Date; readonly date?: Date;
@ -120,7 +118,7 @@ export class CommentReference extends XmlComponent {
} }
export class Comment extends XmlComponent { export class Comment extends XmlComponent {
public constructor({ id, initials, author, date = new Date(), text }: ICommentOptions) { public constructor({ id, initials, author, date = new Date(), children }: ICommentOptions) {
super("w:comment"); super("w:comment");
this.root.push( this.root.push(
@ -132,7 +130,9 @@ export class Comment extends XmlComponent {
}), }),
); );
this.root.push(new Paragraph({ children: [new TextRun(text)] })); for (const child of children) {
this.root.push(child);
}
} }
} }
export class Comments extends XmlComponent { export class Comments extends XmlComponent {

View File

@ -0,0 +1,229 @@
import { expect } from "chai";
import { Formatter } from "@export/formatter";
import {
AnnotationReference,
CarriageReturn,
ContinuationSeparator,
DayLong,
DayShort,
EndnoteReference,
FootnoteReferenceElement,
LastRenderedPageBreak,
MonthLong,
MonthShort,
NoBreakHyphen,
PageNumberElement,
Separator,
SoftHyphen,
Tab,
YearLong,
YearShort,
} from "./empty-children";
// <xsd:element name="noBreakHyphen" type="CT_Empty"/>
// <xsd:element name="softHyphen" type="CT_Empty" minOccurs="0" />
// <xsd:element name="dayShort" type="CT_Empty" minOccurs="0" />
// <xsd:element name="monthShort" type="CT_Empty" minOccurs="0" />
// <xsd:element name="yearShort" type="CT_Empty" minOccurs="0" />
// <xsd:element name="dayLong" type="CT_Empty" minOccurs="0" />
// <xsd:element name="monthLong" type="CT_Empty" minOccurs="0" />
// <xsd:element name="yearLong" type="CT_Empty" minOccurs="0" />
// <xsd:element name="annotationRef" type="CT_Empty" minOccurs="0" />
// <xsd:element name="footnoteRef" type="CT_Empty" minOccurs="0" />
// <xsd:element name="endnoteRef" type="CT_Empty" minOccurs="0" />
// <xsd:element name="separator" type="CT_Empty" minOccurs="0" />
// <xsd:element name="continuationSeparator" type="CT_Empty" minOccurs="0" />
// ...
// <xsd:element name="pgNum" type="CT_Empty" minOccurs="0" />
// <xsd:element name="cr" type="CT_Empty" minOccurs="0" />
// <xsd:element name="tab" type="CT_Empty" minOccurs="0" />
// ...
// <xsd:element name="lastRenderedPageBreak" type="CT_Empty" minOccurs="0" maxOccurs="1" />
describe("NoBreakHyphen", () => {
describe("#constructor()", () => {
it("should create a NoBreakHyphen with correct root key", () => {
const tree = new Formatter().format(new NoBreakHyphen());
expect(tree).to.deep.equal({
"w:noBreakHyphen": {},
});
});
});
});
describe("SoftHyphen", () => {
describe("#constructor()", () => {
it("should create a SoftHyphen with correct root key", () => {
const tree = new Formatter().format(new SoftHyphen());
expect(tree).to.deep.equal({
"w:softHyphen": {},
});
});
});
});
describe("DayShort", () => {
describe("#constructor()", () => {
it("should create a DayShort with correct root key", () => {
const tree = new Formatter().format(new DayShort());
expect(tree).to.deep.equal({
"w:dayShort": {},
});
});
});
});
describe("MonthShort", () => {
describe("#constructor()", () => {
it("should create a MonthShort with correct root key", () => {
const tree = new Formatter().format(new MonthShort());
expect(tree).to.deep.equal({
"w:monthShort": {},
});
});
});
});
describe("YearShort", () => {
describe("#constructor()", () => {
it("should create a YearShort with correct root key", () => {
const tree = new Formatter().format(new YearShort());
expect(tree).to.deep.equal({
"w:yearShort": {},
});
});
});
});
describe("DayLong", () => {
describe("#constructor()", () => {
it("should create a DayLong with correct root key", () => {
const tree = new Formatter().format(new DayLong());
expect(tree).to.deep.equal({
"w:dayLong": {},
});
});
});
});
describe("MonthLong", () => {
describe("#constructor()", () => {
it("should create a MonthLong with correct root key", () => {
const tree = new Formatter().format(new MonthLong());
expect(tree).to.deep.equal({
"w:monthLong": {},
});
});
});
});
describe("YearLong", () => {
describe("#constructor()", () => {
it("should create a YearLong with correct root key", () => {
const tree = new Formatter().format(new YearLong());
expect(tree).to.deep.equal({
"w:yearLong": {},
});
});
});
});
describe("AnnotationReference", () => {
describe("#constructor()", () => {
it("should create a AnnotationReference with correct root key", () => {
const tree = new Formatter().format(new AnnotationReference());
expect(tree).to.deep.equal({
"w:annotationRef": {},
});
});
});
});
describe("FootnoteReferenceElement", () => {
describe("#constructor()", () => {
it("should create a FootnoteReferenceElement with correct root key", () => {
const tree = new Formatter().format(new FootnoteReferenceElement());
expect(tree).to.deep.equal({
"w:footnoteRef": {},
});
});
});
});
describe("EndnoteReference", () => {
describe("#constructor()", () => {
it("should create a EndnoteReference with correct root key", () => {
const tree = new Formatter().format(new EndnoteReference());
expect(tree).to.deep.equal({
"w:endnoteRef": {},
});
});
});
});
describe("Separator", () => {
describe("#constructor()", () => {
it("should create a Separator with correct root key", () => {
const tree = new Formatter().format(new Separator());
expect(tree).to.deep.equal({
"w:separator": {},
});
});
});
});
describe("ContinuationSeparator", () => {
describe("#constructor()", () => {
it("should create a ContinuationSeparator with correct root key", () => {
const tree = new Formatter().format(new ContinuationSeparator());
expect(tree).to.deep.equal({
"w:continuationSeparator": {},
});
});
});
});
describe("PageNumberElement", () => {
describe("#constructor()", () => {
it("should create a PageNumberElement with correct root key", () => {
const tree = new Formatter().format(new PageNumberElement());
expect(tree).to.deep.equal({
"w:pgNum": {},
});
});
});
});
describe("CarriageReturn", () => {
describe("#constructor()", () => {
it("should create a CarriageReturn with correct root key", () => {
const tree = new Formatter().format(new CarriageReturn());
expect(tree).to.deep.equal({
"w:cr": {},
});
});
});
});
describe("Tab", () => {
describe("#constructor()", () => {
it("should create a Tab with correct root key", () => {
const tree = new Formatter().format(new Tab());
expect(tree).to.deep.equal({
"w:tab": {},
});
});
});
});
describe("LastRenderedPageBreak", () => {
describe("#constructor()", () => {
it("should create a LastRenderedPageBreak with correct root key", () => {
const tree = new Formatter().format(new LastRenderedPageBreak());
expect(tree).to.deep.equal({
"w:lastRenderedPageBreak": {},
});
});
});
});

View File

@ -0,0 +1,127 @@
import { EmptyElement } from "@file/xml-components";
// <xsd:group name="EG_RunInnerContent">
// ...
// <xsd:element name="noBreakHyphen" type="CT_Empty"/>
// <xsd:element name="softHyphen" type="CT_Empty" minOccurs="0" />
// <xsd:element name="dayShort" type="CT_Empty" minOccurs="0" />
// <xsd:element name="monthShort" type="CT_Empty" minOccurs="0" />
// <xsd:element name="yearShort" type="CT_Empty" minOccurs="0" />
// <xsd:element name="dayLong" type="CT_Empty" minOccurs="0" />
// <xsd:element name="monthLong" type="CT_Empty" minOccurs="0" />
// <xsd:element name="yearLong" type="CT_Empty" minOccurs="0" />
// <xsd:element name="annotationRef" type="CT_Empty" minOccurs="0" />
// <xsd:element name="footnoteRef" type="CT_Empty" minOccurs="0" />
// <xsd:element name="endnoteRef" type="CT_Empty" minOccurs="0" />
// <xsd:element name="separator" type="CT_Empty" minOccurs="0" />
// <xsd:element name="continuationSeparator" type="CT_Empty" minOccurs="0" />
// ...
// <xsd:element name="pgNum" type="CT_Empty" minOccurs="0" />
// <xsd:element name="cr" type="CT_Empty" minOccurs="0" />
// <xsd:element name="tab" type="CT_Empty" minOccurs="0" />
// ...
// <xsd:element name="lastRenderedPageBreak" type="CT_Empty" minOccurs="0" maxOccurs="1" />
// </xsd:choice>
// </xsd:group>
export class NoBreakHyphen extends EmptyElement {
public constructor() {
super("w:noBreakHyphen");
}
}
export class SoftHyphen extends EmptyElement {
public constructor() {
super("w:softHyphen");
}
}
export class DayShort extends EmptyElement {
public constructor() {
super("w:dayShort");
}
}
export class MonthShort extends EmptyElement {
public constructor() {
super("w:monthShort");
}
}
export class YearShort extends EmptyElement {
public constructor() {
super("w:yearShort");
}
}
export class DayLong extends EmptyElement {
public constructor() {
super("w:dayLong");
}
}
export class MonthLong extends EmptyElement {
public constructor() {
super("w:monthLong");
}
}
export class YearLong extends EmptyElement {
public constructor() {
super("w:yearLong");
}
}
export class AnnotationReference extends EmptyElement {
public constructor() {
super("w:annotationRef");
}
}
export class FootnoteReferenceElement extends EmptyElement {
public constructor() {
super("w:footnoteRef");
}
}
export class EndnoteReference extends EmptyElement {
public constructor() {
super("w:endnoteRef");
}
}
export class Separator extends EmptyElement {
public constructor() {
super("w:separator");
}
}
export class ContinuationSeparator extends EmptyElement {
public constructor() {
super("w:continuationSeparator");
}
}
export class PageNumberElement extends EmptyElement {
public constructor() {
super("w:pgNum");
}
}
export class CarriageReturn extends EmptyElement {
public constructor() {
super("w:cr");
}
}
export class Tab extends EmptyElement {
public constructor() {
super("w:tab");
}
}
export class LastRenderedPageBreak extends EmptyElement {
public constructor() {
super("w:lastRenderedPageBreak");
}
}

View File

@ -1,8 +1,8 @@
import { Attributes, XmlComponent } from "@file/xml-components"; import { Attributes, XmlComponent } from "@file/xml-components";
import { hexColorValue, signedTwipsMeasureValue } from "@util/values"; import { hexColorValue, signedTwipsMeasureValue, UniversalMeasure } from "@util/values";
export class CharacterSpacing extends XmlComponent { export class CharacterSpacing extends XmlComponent {
public constructor(value: number | string) { public constructor(value: number | UniversalMeasure) {
super("w:spacing"); super("w:spacing");
this.root.push( this.root.push(
new Attributes({ new Attributes({

View File

@ -47,6 +47,7 @@ describe("ImageRun", () => {
}, },
} as unknown as File, } as unknown as File,
viewWrapper: {} as unknown as IViewWrapper, viewWrapper: {} as unknown as IViewWrapper,
stack: [],
}); });
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
"w:r": [ "w:r": [
@ -298,6 +299,7 @@ describe("ImageRun", () => {
}, },
} as unknown as File, } as unknown as File,
viewWrapper: {} as unknown as IViewWrapper, viewWrapper: {} as unknown as IViewWrapper,
stack: [],
}); });
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
"w:r": [ "w:r": [
@ -552,6 +554,7 @@ describe("ImageRun", () => {
}, },
} as unknown as File, } as unknown as File,
viewWrapper: {} as unknown as IViewWrapper, viewWrapper: {} as unknown as IViewWrapper,
stack: [],
}); });
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -810,6 +813,7 @@ describe("ImageRun", () => {
}, },
} as unknown as File, } as unknown as File,
viewWrapper: {} as unknown as IViewWrapper, viewWrapper: {} as unknown as IViewWrapper,
stack: [],
}); });
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({

View File

@ -7,6 +7,7 @@ export * from "./run-fonts";
export * from "./sequential-identifier"; export * from "./sequential-identifier";
export * from "./underline"; export * from "./underline";
export * from "./emphasis-mark"; export * from "./emphasis-mark";
export * from "./tab";
export * from "./simple-field"; export * from "./simple-field";
export * from "./comment-run"; export * from "./comment-run";
export * from "./empty-children";
export * from "./positional-tab";

View File

@ -0,0 +1,29 @@
import { expect } from "chai";
import { Formatter } from "@export/formatter";
import { createLanguageComponent } from "./language";
describe("Language", () => {
describe("#createLanguageComponent", () => {
it("should create a language component", () => {
const tree = new Formatter().format(
createLanguageComponent({
value: "en-US",
eastAsia: "zh-CN",
bidirectional: "ar-SA",
}),
);
expect(tree).to.deep.equal({
"w:lang": {
_attr: {
"w:bidi": "ar-SA",
"w:eastAsia": "zh-CN",
"w:val": "en-US",
},
},
});
});
});
});

View File

@ -0,0 +1,35 @@
import { BuilderElement, XmlComponent } from "@file/xml-components";
// <xsd:complexType name="CT_Language">
// <xsd:attribute name="val" type="s:ST_Lang" use="optional"/>
// <xsd:attribute name="eastAsia" type="s:ST_Lang" use="optional"/>
// <xsd:attribute name="bidi" type="s:ST_Lang" use="optional"/>
// </xsd:complexType>
export interface ILanguageOptions {
readonly value?: string;
readonly eastAsia?: string;
readonly bidirectional?: string;
}
export const createLanguageComponent = (options: ILanguageOptions): XmlComponent =>
new BuilderElement<{
readonly value?: string;
readonly eastAsia?: string;
readonly bidirectional?: string;
}>({
name: "w:lang",
attributes: {
value: {
key: "w:val",
value: options.value,
},
eastAsia: {
key: "w:eastAsia",
value: options.eastAsia,
},
bidirectional: {
key: "w:bidi",
value: options.bidirectional,
},
},
});

View File

@ -0,0 +1,27 @@
import { expect } from "chai";
import { Formatter } from "@export/formatter";
import { PositionalTab, PositionalTabAlignment, PositionalTabLeader, PositionalTabRelativeTo } from "./positional-tab";
describe("PositionalTab", () => {
it("should create a PositionalTab with correct root key", () => {
const tree = new Formatter().format(
new PositionalTab({
alignment: PositionalTabAlignment.CENTER,
relativeTo: PositionalTabRelativeTo.MARGIN,
leader: PositionalTabLeader.DOT,
}),
);
expect(tree).to.deep.equal({
"w:ptab": {
_attr: {
"w:alignment": "center",
"w:relativeTo": "margin",
"w:leader": "dot",
},
},
});
});
});

View File

@ -0,0 +1,80 @@
import { NextAttributeComponent, XmlComponent } from "@file/xml-components";
// <xsd:simpleType name="ST_PTabAlignment">
// <xsd:restriction base="xsd:string">
// <xsd:enumeration value="left" />
// <xsd:enumeration value="center" />
// <xsd:enumeration value="right" />
// </xsd:restriction>
// </xsd:simpleType>
export enum PositionalTabAlignment {
LEFT = "left",
CENTER = "center",
RIGHT = "right",
}
// <xsd:simpleType name="ST_PTabRelativeTo">
// <xsd:restriction base="xsd:string">
// <xsd:enumeration value="margin" />
// <xsd:enumeration value="indent" />
// </xsd:restriction>
// </xsd:simpleType>
export enum PositionalTabRelativeTo {
MARGIN = "margin",
INDENT = "indent",
}
// <xsd:simpleType name="ST_PTabLeader">
// <xsd:restriction base="xsd:string">
// <xsd:enumeration value="none" />
// <xsd:enumeration value="dot" />
// <xsd:enumeration value="hyphen" />
// <xsd:enumeration value="underscore" />
// <xsd:enumeration value="middleDot" />
// </xsd:restriction>
// </xsd:simpleType>
export enum PositionalTabLeader {
NONE = "none",
DOT = "dot",
HYPHEN = "hyphen",
UNDERSCORE = "underscore",
MIDDLE_DOT = "middleDot",
}
export interface PositionalTabOptions {
readonly alignment: PositionalTabAlignment;
readonly relativeTo: PositionalTabRelativeTo;
readonly leader: PositionalTabLeader;
}
// <xsd:complexType name="CT_PTab">
// <xsd:attribute name="alignment" type="ST_PTabAlignment" use="required" />
// <xsd:attribute name="relativeTo" type="ST_PTabRelativeTo" use="required" />
// <xsd:attribute name="leader" type="ST_PTabLeader" use="required" />
// </xsd:complexType>
export class PositionalTab extends XmlComponent {
public constructor(options: PositionalTabOptions) {
super("w:ptab");
this.root.push(
new NextAttributeComponent<{
readonly alignment: PositionalTabAlignment;
readonly relativeTo: PositionalTabRelativeTo;
readonly leader: PositionalTabLeader;
}>({
alignment: {
key: "w:alignment",
value: options.alignment,
},
relativeTo: {
key: "w:relativeTo",
value: options.relativeTo,
},
leader: {
key: "w:leader",
value: options.leader,
},
}),
);
}
}

View File

@ -9,9 +9,11 @@ import {
StringValueElement, StringValueElement,
XmlComponent, XmlComponent,
} from "@file/xml-components"; } from "@file/xml-components";
import { PositiveUniversalMeasure, UniversalMeasure } from "@util/values";
import { EmphasisMark, EmphasisMarkType } from "./emphasis-mark"; import { EmphasisMark, EmphasisMarkType } from "./emphasis-mark";
import { CharacterSpacing, Color, Highlight, HighlightComplexScript } from "./formatting"; import { CharacterSpacing, Color, Highlight, HighlightComplexScript } from "./formatting";
import { createLanguageComponent, ILanguageOptions } from "./language";
import { IFontAttributesProperties, RunFonts } from "./run-fonts"; import { IFontAttributesProperties, RunFonts } from "./run-fonts";
import { SubScript, SuperScript } from "./script"; import { SubScript, SuperScript } from "./script";
import { Underline, UnderlineType } from "./underline"; import { Underline, UnderlineType } from "./underline";
@ -21,6 +23,16 @@ interface IFontOptions {
readonly hint?: string; readonly hint?: string;
} }
export enum TextEffect {
BLINK_BACKGROUND = "blinkBackground",
LIGHTS = "lights",
ANTS_BLACK = "antsBlack",
ANTS_RED = "antsRed",
SHIMMER = "shimmer",
SPARKLE = "sparkle",
NONE = "none",
}
export interface IRunStylePropertiesOptions { export interface IRunStylePropertiesOptions {
readonly bold?: boolean; readonly bold?: boolean;
readonly boldComplexScript?: boolean; readonly boldComplexScript?: boolean;
@ -30,12 +42,15 @@ export interface IRunStylePropertiesOptions {
readonly color?: string; readonly color?: string;
readonly type?: UnderlineType; readonly type?: UnderlineType;
}; };
readonly effect?: TextEffect;
readonly emphasisMark?: { readonly emphasisMark?: {
readonly type?: EmphasisMarkType; readonly type?: EmphasisMarkType;
}; };
readonly color?: string; readonly color?: string;
readonly size?: number | string; readonly kern?: number | PositiveUniversalMeasure;
readonly sizeComplexScript?: boolean | number | string; readonly position?: UniversalMeasure;
readonly size?: number | PositiveUniversalMeasure;
readonly sizeComplexScript?: boolean | number | PositiveUniversalMeasure;
readonly rightToLeft?: boolean; readonly rightToLeft?: boolean;
readonly smallCaps?: boolean; readonly smallCaps?: boolean;
readonly allCaps?: boolean; readonly allCaps?: boolean;
@ -51,10 +66,13 @@ export interface IRunStylePropertiesOptions {
readonly emboss?: boolean; readonly emboss?: boolean;
readonly imprint?: boolean; readonly imprint?: boolean;
readonly revision?: IRunPropertiesChangeOptions; readonly revision?: IRunPropertiesChangeOptions;
readonly language?: ILanguageOptions;
readonly border?: IBorderOptions; readonly border?: IBorderOptions;
readonly snapToGrid?: boolean;
readonly vanish?: boolean; readonly vanish?: boolean;
readonly specVanish?: boolean; readonly specVanish?: boolean;
readonly scale?: number; readonly scale?: number;
readonly math?: boolean;
} }
export interface IRunPropertiesOptions extends IRunStylePropertiesOptions { export interface IRunPropertiesOptions extends IRunStylePropertiesOptions {
@ -133,6 +151,10 @@ export class RunProperties extends IgnoreIfEmptyXmlComponent {
this.push(new Underline(options.underline.type, options.underline.color)); this.push(new Underline(options.underline.type, options.underline.color));
} }
if (options.effect) {
this.push(new StringValueElement("w:effect", options.effect));
}
if (options.emphasisMark) { if (options.emphasisMark) {
this.push(new EmphasisMark(options.emphasisMark.type)); this.push(new EmphasisMark(options.emphasisMark.type));
} }
@ -141,6 +163,14 @@ export class RunProperties extends IgnoreIfEmptyXmlComponent {
this.push(new Color(options.color)); this.push(new Color(options.color));
} }
if (options.kern) {
this.push(new HpsMeasureElement("w:kern", options.kern));
}
if (options.position) {
this.push(new StringValueElement("w:position", options.position));
}
if (options.size !== undefined) { if (options.size !== undefined) {
this.push(new HpsMeasureElement("w:sz", options.size)); this.push(new HpsMeasureElement("w:sz", options.size));
} }
@ -226,6 +256,10 @@ export class RunProperties extends IgnoreIfEmptyXmlComponent {
this.push(new BorderElement("w:bdr", options.border)); this.push(new BorderElement("w:bdr", options.border));
} }
if (options.snapToGrid) {
this.push(new OnOffElement("w:snapToGrid", options.snapToGrid));
}
if (options.vanish) { if (options.vanish) {
// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_vanish_topic_ID0E6W3O.html // https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_vanish_topic_ID0E6W3O.html
// http://www.datypic.com/sc/ooxml/e-w_vanish-1.html // http://www.datypic.com/sc/ooxml/e-w_vanish-1.html
@ -240,6 +274,14 @@ export class RunProperties extends IgnoreIfEmptyXmlComponent {
if (options.scale !== undefined) { if (options.scale !== undefined) {
this.push(new NumberValueElement("w:w", options.scale)); this.push(new NumberValueElement("w:w", options.scale));
} }
if (options.language) {
this.push(createLanguageComponent(options.language));
}
if (options.math) {
this.push(new OnOffElement("w:oMath", options.math));
}
} }
public push(item: XmlComponent): void { public push(item: XmlComponent): void {

View File

@ -23,11 +23,11 @@ export class Text extends XmlComponent {
if (typeof options === "string") { if (typeof options === "string") {
this.root.push(new TextAttributes({ space: SpaceType.PRESERVE })); this.root.push(new TextAttributes({ space: SpaceType.PRESERVE }));
this.root.push(options); this.root.push(options);
return; return this;
} else { } else {
this.root.push(new TextAttributes({ space: options.space ?? SpaceType.DEFAULT })); this.root.push(new TextAttributes({ space: options.space ?? SpaceType.DEFAULT }));
this.root.push(options.text); this.root.push(options.text);
return; return this;
} }
} }
} }

View File

@ -7,6 +7,7 @@ import { ShadingType } from "@file/shading";
import { EmphasisMarkType } from "./emphasis-mark"; import { EmphasisMarkType } from "./emphasis-mark";
import { PageNumber, Run } from "./run"; import { PageNumber, Run } from "./run";
import { UnderlineType } from "./underline"; import { UnderlineType } from "./underline";
import { TextEffect } from "./properties";
describe("Run", () => { describe("Run", () => {
describe("#bold()", () => { describe("#bold()", () => {
@ -580,5 +581,147 @@ describe("Run", () => {
}); });
}); });
}); });
describe("#language", () => {
it("should correctly set the language", () => {
const run = new Run({
language: {
value: "en-US",
eastAsia: "zh-CN",
bidirectional: "ar-SA",
},
});
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
"w:r": [
{
"w:rPr": [
{
"w:lang": {
_attr: {
"w:val": "en-US",
"w:eastAsia": "zh-CN",
"w:bidi": "ar-SA",
},
},
},
],
},
],
});
});
});
describe("#position", () => {
it("should correctly set the position", () => {
const run = new Run({
position: "2mm",
});
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
"w:r": [
{
"w:rPr": [
{
"w:position": {
_attr: {
"w:val": "2mm",
},
},
},
],
},
],
});
});
});
describe("#effect", () => {
it("should correctly set the effect", () => {
const run = new Run({
effect: TextEffect.ANTS_BLACK,
});
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
"w:r": [
{
"w:rPr": [
{
"w:effect": {
_attr: {
"w:val": "antsBlack",
},
},
},
],
},
],
});
});
});
describe("#math", () => {
it("should correctly set the math", () => {
const run = new Run({
math: true,
});
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
"w:r": [
{
"w:rPr": [
{
"w:oMath": {},
},
],
},
],
});
});
});
describe("#kern", () => {
it("should correctly set the kern", () => {
const run = new Run({
kern: "2mm",
});
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
"w:r": [
{
"w:rPr": [
{
"w:kern": {
_attr: {
"w:val": "2mm",
},
},
},
],
},
],
});
});
});
describe("#snapToGrid", () => {
it("should correctly set the snapToGrid", () => {
const run = new Run({
snapToGrid: true,
});
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
"w:r": [
{
"w:rPr": [
{
"w:snapToGrid": {},
},
],
},
],
});
});
});
}); });
}); });

View File

@ -9,10 +9,91 @@ import { Begin, End, Separate } from "./field";
import { NumberOfPages, NumberOfPagesSection, Page } from "./page-number"; import { NumberOfPages, NumberOfPagesSection, Page } from "./page-number";
import { IRunPropertiesOptions, RunProperties } from "./properties"; import { IRunPropertiesOptions, RunProperties } from "./properties";
import { Text } from "./run-components/text"; import { Text } from "./run-components/text";
import { Tab } from "./tab"; import {
AnnotationReference,
CarriageReturn,
ContinuationSeparator,
DayLong,
DayShort,
EndnoteReference,
FootnoteReferenceElement,
LastRenderedPageBreak,
MonthLong,
MonthShort,
NoBreakHyphen,
PageNumberElement,
Separator,
SoftHyphen,
Tab,
YearLong,
YearShort,
} from "./empty-children";
import { PositionalTab } from "./positional-tab";
export interface IRunOptions extends IRunPropertiesOptions { export interface IRunOptions extends IRunPropertiesOptions {
readonly children?: readonly (Begin | FieldInstruction | Separate | End | PageNumber | FootnoteReferenceRun | Tab | string)[]; // <xsd:choice>
// <xsd:element name="br" type="CT_Br" />
// <xsd:element name="t" type="CT_Text" />
// <xsd:element name="contentPart" type="CT_Rel" />
// <xsd:element name="delText" type="CT_Text" />
// <xsd:element name="instrText" type="CT_Text" />
// <xsd:element name="delInstrText" type="CT_Text" />
// <xsd:element name="noBreakHyphen" type="CT_Empty" />
// <xsd:element name="softHyphen" type="CT_Empty" minOccurs="0" />
// <xsd:element name="dayShort" type="CT_Empty" minOccurs="0" />
// <xsd:element name="monthShort" type="CT_Empty" minOccurs="0" />
// <xsd:element name="yearShort" type="CT_Empty" minOccurs="0" />
// <xsd:element name="dayLong" type="CT_Empty" minOccurs="0" />
// <xsd:element name="monthLong" type="CT_Empty" minOccurs="0" />
// <xsd:element name="yearLong" type="CT_Empty" minOccurs="0" />
// <xsd:element name="annotationRef" type="CT_Empty" minOccurs="0" />
// <xsd:element name="footnoteRef" type="CT_Empty" minOccurs="0" />
// <xsd:element name="endnoteRef" type="CT_Empty" minOccurs="0" />
// <xsd:element name="separator" type="CT_Empty" minOccurs="0" />
// <xsd:element name="continuationSeparator" type="CT_Empty" minOccurs="0" />
// <xsd:element name="sym" type="CT_Sym" minOccurs="0" />
// <xsd:element name="pgNum" type="CT_Empty" minOccurs="0" />
// <xsd:element name="cr" type="CT_Empty" minOccurs="0" />
// <xsd:element name="tab" type="CT_Empty" minOccurs="0" />
// <xsd:element name="object" type="CT_Object" />
// <xsd:element name="pict" type="CT_Picture" />
// <xsd:element name="fldChar" type="CT_FldChar" />
// <xsd:element name="ruby" type="CT_Ruby" />
// <xsd:element name="footnoteReference" type="CT_FtnEdnRef" />
// <xsd:element name="endnoteReference" type="CT_FtnEdnRef" />
// <xsd:element name="commentReference" type="CT_Markup" />
// <xsd:element name="drawing" type="CT_Drawing" />
// <xsd:element name="ptab" type="CT_PTab" minOccurs="0" />
// <xsd:element name="lastRenderedPageBreak" type="CT_Empty" minOccurs="0" maxOccurs="1" />
// </xsd:choice>
readonly children?: readonly (
| Begin
| FieldInstruction
| Separate
| End
| PageNumber
| FootnoteReferenceRun
| Break
| AnnotationReference
| CarriageReturn
| ContinuationSeparator
| DayLong
| DayShort
| EndnoteReference
| FootnoteReferenceElement
| LastRenderedPageBreak
| MonthLong
| MonthShort
| NoBreakHyphen
| PageNumberElement
| Separator
| SoftHyphen
| Tab
| YearLong
| YearShort
| PositionalTab
| string
)[];
readonly break?: number; readonly break?: number;
readonly text?: string; readonly text?: string;
} }

View File

@ -11,7 +11,7 @@ export class SymbolRun extends Run {
if (typeof options === "string") { if (typeof options === "string") {
super({}); super({});
this.root.push(new Symbol(options)); this.root.push(new Symbol(options));
return; return this;
} }
super(options); super(options);

View File

@ -1,22 +0,0 @@
import { expect } from "chai";
import { Formatter } from "@export/formatter";
import { Tab } from "./tab";
describe("Tab", () => {
let tab: Tab;
beforeEach(() => {
tab = new Tab();
});
describe("#constructor()", () => {
it("should create a Tab with correct root key", () => {
const tree = new Formatter().format(tab);
expect(tree).to.deep.equal({
"w:tab": {},
});
});
});
});

View File

@ -1,14 +0,0 @@
// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_tab_topic_ID0EM6AO.html
import { XmlComponent } from "@file/xml-components";
// <xsd:group name="EG_RunInnerContent">
// ...
// <xsd:element name="tab" type="CT_Empty" minOccurs="0"/>
//
// TODO: this is unused and undocumented currently.
// I think the intended use was for users to import, and insert as a child of `Run`.
export class Tab extends XmlComponent {
public constructor() {
super("w:tab");
}
}

View File

@ -12,13 +12,9 @@ export class Relationships extends XmlComponent {
); );
} }
public addRelationship(relationship: Relationship): void {
this.root.push(relationship);
}
public createRelationship(id: number | string, type: RelationshipType, target: string, targetMode?: TargetModeType): Relationship { public createRelationship(id: number | string, type: RelationshipType, target: string, targetMode?: TargetModeType): Relationship {
const relationship = new Relationship(`rId${id}`, type, target, targetMode); const relationship = new Relationship(`rId${id}`, type, target, targetMode);
this.addRelationship(relationship); this.root.push(relationship);
return relationship; return relationship;
} }

View File

@ -1,4 +1,10 @@
const createLsdException = (name: string, uiPriority?: number, qFormat?: number, semiHidden?: number, unhideWhenUsed?: number) => { const createLsdException = (
name: string,
uiPriority?: number,
qFormat?: number,
semiHidden?: number,
unhideWhenUsed?: number,
): readonly object[] => {
"use strict"; "use strict";
return [ return [

View File

@ -3,13 +3,13 @@
import { Paragraph } from "@file/paragraph"; import { Paragraph } from "@file/paragraph";
import { Run } from "@file/paragraph/run"; import { Run } from "@file/paragraph/run";
import { Begin, End, Separate } from "@file/paragraph/run/field"; import { Begin, End, Separate } from "@file/paragraph/run/field";
import { XmlComponent } from "@file/xml-components"; import { FileChild } from "@file/file-child";
import { FieldInstruction } from "./field-instruction"; import { FieldInstruction } from "./field-instruction";
import { StructuredDocumentTagContent } from "./sdt-content"; import { StructuredDocumentTagContent } from "./sdt-content";
import { StructuredDocumentTagProperties } from "./sdt-properties"; import { StructuredDocumentTagProperties } from "./sdt-properties";
import { ITableOfContentsOptions } from "./table-of-contents-properties"; import { ITableOfContentsOptions } from "./table-of-contents-properties";
export class TableOfContents extends XmlComponent { export class TableOfContents extends FileChild {
public constructor(alias: string = "Table of Contents", properties?: ITableOfContentsOptions) { public constructor(alias: string = "Table of Contents", properties?: ITableOfContentsOptions) {
super("w:sdt"); super("w:sdt");
this.root.push(new StructuredDocumentTagProperties(alias)); this.root.push(new StructuredDocumentTagProperties(alias));

View File

@ -9,11 +9,11 @@
// </xsd:sequence> // </xsd:sequence>
// </xsd:complexType> // </xsd:complexType>
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { NextAttributeComponent, XmlComponent } from "@file/xml-components";
import { twipsMeasureValue } from "@util/values"; import { PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
export class TableGrid extends XmlComponent { export class TableGrid extends XmlComponent {
public constructor(widths: readonly number[] | readonly string[]) { public constructor(widths: readonly number[] | readonly PositiveUniversalMeasure[]) {
super("w:tblGrid"); super("w:tblGrid");
for (const width of widths) { for (const width of widths) {
this.root.push(new GridCol(width)); this.root.push(new GridCol(width));
@ -21,15 +21,15 @@ export class TableGrid extends XmlComponent {
} }
} }
class GridColAttributes extends XmlAttributeComponent<{ readonly w: number | string }> {
protected readonly xmlKeys = { w: "w:w" };
}
export class GridCol extends XmlComponent { export class GridCol extends XmlComponent {
public constructor(width?: number | string) { public constructor(width?: number | PositiveUniversalMeasure) {
super("w:gridCol"); super("w:gridCol");
if (width !== undefined) { if (width !== undefined) {
this.root.push(new GridColAttributes({ w: twipsMeasureValue(width) })); this.root.push(
new NextAttributeComponent<{ readonly width: number | PositiveUniversalMeasure }>({
width: { key: "w:w", value: twipsMeasureValue(width) },
}),
);
} }
} }
} }

View File

@ -38,9 +38,7 @@ describe("Table Float Properties", () => {
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
"w:tblpPr": [ "w:tblpPr": [
{ {
_attr: { _attr: {},
overlap: "never",
},
}, },
{ {
"w:tblOverlap": { "w:tblOverlap": {

View File

@ -1,5 +1,5 @@
import { StringEnumValueElement, XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { NextAttributeComponent, StringEnumValueElement, XmlComponent } from "@file/xml-components";
import { signedTwipsMeasureValue, twipsMeasureValue } from "@util/values"; import { PositiveUniversalMeasure, signedTwipsMeasureValue, twipsMeasureValue, UniversalMeasure } from "@util/values";
export enum TableAnchorType { export enum TableAnchorType {
MARGIN = "margin", MARGIN = "margin",
@ -35,7 +35,7 @@ export enum OverlapType {
OVERLAP = "overlap", OVERLAP = "overlap",
} }
export interface ITableFloatOptions { export type ITableFloatOptions = {
/* cSpell:disable */ /* cSpell:disable */
/** /**
* Specifies the horizontal anchor or the base object from which the horizontal positioning in the * Specifies the horizontal anchor or the base object from which the horizontal positioning in the
@ -55,7 +55,7 @@ export interface ITableFloatOptions {
* If relativeHorizontalPosition is also specified, then the absoluteHorizontalPosition attribute is ignored. * If relativeHorizontalPosition is also specified, then the absoluteHorizontalPosition attribute is ignored.
* If the attribute is omitted, the value is assumed to be zero. * If the attribute is omitted, the value is assumed to be zero.
*/ */
readonly absoluteHorizontalPosition?: number | string; readonly absoluteHorizontalPosition?: number | UniversalMeasure;
/** /**
* Specifies a relative horizontal position for the table, relative to the horizontalAnchor attribute. * Specifies a relative horizontal position for the table, relative to the horizontalAnchor attribute.
@ -86,7 +86,7 @@ export interface ITableFloatOptions {
* If relativeVerticalPosition is also specified, then the absoluteVerticalPosition attribute is ignored. * If relativeVerticalPosition is also specified, then the absoluteVerticalPosition attribute is ignored.
* If the attribute is omitted, the value is assumed to be zero. * If the attribute is omitted, the value is assumed to be zero.
*/ */
readonly absoluteVerticalPosition?: number | string; readonly absoluteVerticalPosition?: number | UniversalMeasure;
/** /**
* Specifies a relative vertical position for the table, relative to the verticalAnchor attribute. * Specifies a relative vertical position for the table, relative to the verticalAnchor attribute.
@ -104,27 +104,27 @@ export interface ITableFloatOptions {
* Specifies the minimum distance to be maintained between the table and the top of text in the paragraph * Specifies the minimum distance to be maintained between the table and the top of text in the paragraph
* below the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero. * below the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero.
*/ */
readonly bottomFromText?: number | string; readonly bottomFromText?: number | PositiveUniversalMeasure;
/** /**
* Specifies the minimum distance to be maintained between the table and the bottom edge of text in the paragraph * Specifies the minimum distance to be maintained between the table and the bottom edge of text in the paragraph
* above the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero. * above the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero.
*/ */
readonly topFromText?: number | string; readonly topFromText?: number | PositiveUniversalMeasure;
/** /**
* Specifies the minimum distance to be maintained between the table and the edge of text in the paragraph * Specifies the minimum distance to be maintained between the table and the edge of text in the paragraph
* to the left of the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero. * to the left of the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero.
*/ */
readonly leftFromText?: number | string; readonly leftFromText?: number | PositiveUniversalMeasure;
/** /**
* Specifies the minimum distance to be maintained between the table and the edge of text in the paragraph * Specifies the minimum distance to be maintained between the table and the edge of text in the paragraph
* to the right of the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero. * to the right of the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero.
*/ */
readonly rightFromText?: number | string; readonly rightFromText?: number | PositiveUniversalMeasure;
readonly overlap?: OverlapType; readonly overlap?: OverlapType;
} };
// <xsd:complexType name="CT_TblPPr"> // <xsd:complexType name="CT_TblPPr">
// <xsd:attribute name="leftFromText" type="s:ST_TwipsMeasure"/> // <xsd:attribute name="leftFromText" type="s:ST_TwipsMeasure"/>
@ -139,51 +139,65 @@ export interface ITableFloatOptions {
// <xsd:attribute name="tblpY" type="ST_SignedTwipsMeasure"/> // <xsd:attribute name="tblpY" type="ST_SignedTwipsMeasure"/>
// </xsd:complexType> // </xsd:complexType>
export class TableFloatOptionsAttributes extends XmlAttributeComponent<ITableFloatOptions> {
protected readonly xmlKeys = {
horizontalAnchor: "w:horzAnchor",
verticalAnchor: "w:vertAnchor",
absoluteHorizontalPosition: "w:tblpX",
relativeHorizontalPosition: "w:tblpXSpec",
absoluteVerticalPosition: "w:tblpY",
relativeVerticalPosition: "w:tblpYSpec",
bottomFromText: "w:bottomFromText",
topFromText: "w:topFromText",
leftFromText: "w:leftFromText",
rightFromText: "w:rightFromText",
};
}
export class TableFloatProperties extends XmlComponent { export class TableFloatProperties extends XmlComponent {
public constructor({ public constructor({
horizontalAnchor,
verticalAnchor,
absoluteHorizontalPosition,
relativeHorizontalPosition,
absoluteVerticalPosition,
relativeVerticalPosition,
bottomFromText,
topFromText,
leftFromText, leftFromText,
rightFromText, rightFromText,
topFromText, overlap,
bottomFromText,
absoluteHorizontalPosition,
absoluteVerticalPosition,
...options
}: ITableFloatOptions) { }: ITableFloatOptions) {
super("w:tblpPr"); super("w:tblpPr");
this.root.push( this.root.push(
new TableFloatOptionsAttributes({ new NextAttributeComponent<Omit<ITableFloatOptions, "overlap">>({
leftFromText: leftFromText === undefined ? undefined : twipsMeasureValue(leftFromText), leftFromText: { key: "w:leftFromText", value: leftFromText === undefined ? undefined : twipsMeasureValue(leftFromText) },
rightFromText: rightFromText === undefined ? undefined : twipsMeasureValue(rightFromText), rightFromText: {
topFromText: topFromText === undefined ? undefined : twipsMeasureValue(topFromText), key: "w:rightFromText",
bottomFromText: bottomFromText === undefined ? undefined : twipsMeasureValue(bottomFromText), value: rightFromText === undefined ? undefined : twipsMeasureValue(rightFromText),
absoluteHorizontalPosition: },
absoluteHorizontalPosition === undefined ? undefined : signedTwipsMeasureValue(absoluteHorizontalPosition), topFromText: { key: "w:topFromText", value: topFromText === undefined ? undefined : twipsMeasureValue(topFromText) },
absoluteVerticalPosition: bottomFromText: {
absoluteVerticalPosition === undefined ? undefined : signedTwipsMeasureValue(absoluteVerticalPosition), key: "w:bottomFromText",
...options, value: bottomFromText === undefined ? undefined : twipsMeasureValue(bottomFromText),
},
absoluteHorizontalPosition: {
key: "w:tblpX",
value: absoluteHorizontalPosition === undefined ? undefined : signedTwipsMeasureValue(absoluteHorizontalPosition),
},
absoluteVerticalPosition: {
key: "w:tblpY",
value: absoluteVerticalPosition === undefined ? undefined : signedTwipsMeasureValue(absoluteVerticalPosition),
},
horizontalAnchor: {
key: "w:horzAnchor",
value: horizontalAnchor === undefined ? undefined : horizontalAnchor,
},
relativeHorizontalPosition: {
key: "w:tblpXSpec",
value: relativeHorizontalPosition,
},
relativeVerticalPosition: {
key: "w:tblpYSpec",
value: relativeVerticalPosition,
},
verticalAnchor: {
key: "w:vertAnchor",
value: verticalAnchor,
},
}), }),
); );
if (options.overlap) { if (overlap) {
// <xsd:complexType name="CT_TblOverlap"> // <xsd:complexType name="CT_TblOverlap">
// <xsd:attribute name="val" type="ST_TblOverlap" use="required"/> // <xsd:attribute name="val" type="ST_TblOverlap" use="required"/>
// </xsd:complexType> // </xsd:complexType>
this.root.push(new StringEnumValueElement<OverlapType>("w:tblOverlap", options.overlap)); this.root.push(new StringEnumValueElement<OverlapType>("w:tblOverlap", overlap));
} }
} }
} }

View File

@ -1,5 +1,5 @@
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
import { twipsMeasureValue } from "@util/values"; import { PositiveUniversalMeasure, twipsMeasureValue } from "@util/values";
// <xsd:complexType name="CT_Height"> // <xsd:complexType name="CT_Height">
// <xsd:attribute name="val" type="s:ST_TwipsMeasure"/> // <xsd:attribute name="val" type="s:ST_TwipsMeasure"/>
@ -30,7 +30,7 @@ export class TableRowHeightAttributes extends XmlAttributeComponent<{
} }
export class TableRowHeight extends XmlComponent { export class TableRowHeight extends XmlComponent {
public constructor(value: number | string, rule: HeightRule) { public constructor(value: number | PositiveUniversalMeasure, rule: HeightRule) {
super("w:trHeight"); super("w:trHeight");
this.root.push( this.root.push(

View File

@ -28,6 +28,7 @@
// </xsd:complexContent> // </xsd:complexContent>
// </xsd:complexType> // </xsd:complexType>
import { IgnoreIfEmptyXmlComponent, OnOffElement } from "@file/xml-components"; import { IgnoreIfEmptyXmlComponent, OnOffElement } from "@file/xml-components";
import { PositiveUniversalMeasure } from "@util/values";
import { HeightRule, TableRowHeight } from "./table-row-height"; import { HeightRule, TableRowHeight } from "./table-row-height";
@ -35,7 +36,7 @@ export interface ITableRowPropertiesOptions {
readonly cantSplit?: boolean; readonly cantSplit?: boolean;
readonly tableHeader?: boolean; readonly tableHeader?: boolean;
readonly height?: { readonly height?: {
readonly value: number | string; readonly value: number | PositiveUniversalMeasure;
readonly rule: HeightRule; readonly rule: HeightRule;
}; };
} }

View File

@ -1,6 +1,6 @@
// http://officeopenxml.com/WPtableWidth.php // http://officeopenxml.com/WPtableWidth.php
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { NextAttributeComponent, XmlComponent } from "@file/xml-components";
import { measurementOrPercentValue } from "@util/values"; import { measurementOrPercentValue, Percentage, UniversalMeasure } from "@util/values";
// <xsd:simpleType name="ST_TblWidth"> // <xsd:simpleType name="ST_TblWidth">
// <xsd:restriction base="xsd:string"> // <xsd:restriction base="xsd:string">
@ -25,14 +25,10 @@ export enum WidthType {
// <xsd:attribute name="w" type="ST_MeasurementOrPercent"/> // <xsd:attribute name="w" type="ST_MeasurementOrPercent"/>
// <xsd:attribute name="type" type="ST_TblWidth"/> // <xsd:attribute name="type" type="ST_TblWidth"/>
// </xsd:complexType> // </xsd:complexType>
export interface ITableWidthProperties { export type ITableWidthProperties = {
readonly size: string | number; readonly size: number | Percentage | UniversalMeasure;
readonly type?: WidthType; readonly type?: WidthType;
} };
class TableWidthAttributes extends XmlAttributeComponent<ITableWidthProperties> {
protected readonly xmlKeys = { type: "w:type", size: "w:w" };
}
export class TableWidthElement extends XmlComponent { export class TableWidthElement extends XmlComponent {
public constructor(name: string, { type = WidthType.AUTO, size }: ITableWidthProperties) { public constructor(name: string, { type = WidthType.AUTO, size }: ITableWidthProperties) {
@ -42,6 +38,12 @@ export class TableWidthElement extends XmlComponent {
if (type === WidthType.PERCENTAGE && typeof size === "number") { if (type === WidthType.PERCENTAGE && typeof size === "number") {
tableWidthValue = `${size}%`; tableWidthValue = `${size}%`;
} }
this.root.push(new TableWidthAttributes({ type: type, size: measurementOrPercentValue(tableWidthValue) }));
this.root.push(
new NextAttributeComponent<ITableWidthProperties>({
type: { key: "w:type", value: type },
size: { key: "w:w", value: measurementOrPercentValue(tableWidthValue) },
}),
);
} }
} }

View File

@ -1,5 +1,5 @@
// http://officeopenxml.com/WPtableGrid.php // http://officeopenxml.com/WPtableGrid.php
import { XmlComponent } from "@file/xml-components"; import { FileChild } from "@file/file-child";
import { AlignmentType } from "../paragraph"; import { AlignmentType } from "../paragraph";
import { TableGrid } from "./grid"; import { TableGrid } from "./grid";
@ -34,7 +34,7 @@ export interface ITableOptions {
readonly visuallyRightToLeft?: boolean; readonly visuallyRightToLeft?: boolean;
} }
export class Table extends XmlComponent { export class Table extends FileChild {
public constructor({ public constructor({
rows, rows,
width, width,

View File

@ -5,6 +5,8 @@ import { IXmlableObject } from "./xmlable-object";
export interface IContext { export interface IContext {
readonly file: File; readonly file: File;
readonly viewWrapper: IViewWrapper; readonly viewWrapper: IViewWrapper;
// eslint-disable-next-line functional/prefer-readonly-type
readonly stack: IXmlableObject[];
} }
export abstract class BaseXmlComponent { export abstract class BaseXmlComponent {

View File

@ -1,16 +1,16 @@
import { BaseXmlComponent, IContext } from "./base"; import { BaseXmlComponent, IContext } from "./base";
import { IXmlableObject } from "./xmlable-object"; import { IXmlableObject, IXmlAttribute } from "./xmlable-object";
export type AttributeMap<T> = { readonly [P in keyof T]: string }; export type AttributeMap<T> = { readonly [P in keyof T]: string };
export type AttributeData = { readonly [key: string]: boolean | number | string };
export type AttributePayload<T> = { readonly [P in keyof T]: { readonly key: string; readonly value: T[P] } };
export abstract class XmlAttributeComponent<T extends object> extends BaseXmlComponent { export abstract class XmlAttributeComponent<T extends object> extends BaseXmlComponent {
// tslint:disable-next-line:readonly-keyword
protected readonly root: T;
protected readonly xmlKeys?: AttributeMap<T>; protected readonly xmlKeys?: AttributeMap<T>;
public constructor(properties: T) { public constructor(private readonly root: T) {
super("_attr"); super("_attr");
this.root = properties;
} }
public prepForXml(_: IContext): IXmlableObject { public prepForXml(_: IContext): IXmlableObject {
@ -26,3 +26,16 @@ export abstract class XmlAttributeComponent<T extends object> extends BaseXmlCom
return { _attr: attrs }; return { _attr: attrs };
} }
} }
export class NextAttributeComponent<T extends AttributeData> extends BaseXmlComponent {
public constructor(private readonly root: AttributePayload<T>) {
super("_attr");
}
public prepForXml(_: IContext): IXmlableObject {
const attrs = Object.values<{ readonly key: string; readonly value: string | boolean | number }>(this.root)
.filter(({ value }) => value !== undefined)
.reduce((acc, { key, value }) => ({ ...acc, [key]: value }), {} as IXmlAttribute);
return { _attr: attrs };
}
}

View File

@ -62,7 +62,7 @@ describe("ImportedXmlComponent", () => {
describe("#prepForXml()", () => { describe("#prepForXml()", () => {
it("should transform for xml", () => { it("should transform for xml", () => {
// tslint:disable-next-line: no-object-literal-type-assertion // tslint:disable-next-line: no-object-literal-type-assertion
const converted = importedXmlComponent.prepForXml({} as IContext); const converted = importedXmlComponent.prepForXml({ stack: [] } as unknown as IContext);
expect(converted).to.deep.equal({ expect(converted).to.deep.equal({
"w:test": [ "w:test": [
{ {

View File

@ -0,0 +1,41 @@
import { expect } from "chai";
import { Formatter } from "@export/formatter";
import { BuilderElement } from "./simple-elements";
describe("BuilderElement", () => {
describe("#constructor()", () => {
it("should create a simple BuilderElement", () => {
const element = new BuilderElement({
name: "test",
});
const tree = new Formatter().format(element);
expect(tree).to.deep.equal({
test: {},
});
});
it("should create a simple BuilderElement with attributes", () => {
const element = new BuilderElement<{ readonly testAttr: string }>({
name: "test",
attributes: {
testAttr: {
key: "w:testAttr",
value: "test",
},
},
});
const tree = new Formatter().format(element);
expect(tree).to.deep.equal({
test: {
_attr: {
"w:testAttr": "test",
},
},
});
});
});
});

View File

@ -1,6 +1,6 @@
import { Attributes, XmlComponent } from "@file/xml-components"; import { AttributeData, AttributePayload, Attributes, NextAttributeComponent, XmlComponent } from "@file/xml-components";
import { hpsMeasureValue } from "@util/values"; import { hpsMeasureValue, PositiveUniversalMeasure } from "@util/values";
// This represents element type CT_OnOff, which indicate a boolean value. // This represents element type CT_OnOff, which indicate a boolean value.
// //
@ -26,8 +26,13 @@ export class OnOffElement extends XmlComponent {
// <xsd:complexType name="CT_HpsMeasure"> // <xsd:complexType name="CT_HpsMeasure">
// <xsd:attribute name="val" type="ST_HpsMeasure" use="required"/> // <xsd:attribute name="val" type="ST_HpsMeasure" use="required"/>
// </xsd:complexType> // </xsd:complexType>
// <xsd:simpleType name="ST_HpsMeasure">
// <xsd:union memberTypes="s:ST_UnsignedDecimalNumber s:ST_PositiveUniversalMeasure" />
// </xsd:simpleType>
export class HpsMeasureElement extends XmlComponent { export class HpsMeasureElement extends XmlComponent {
public constructor(name: string, val: number | string) { public constructor(name: string, val: number | PositiveUniversalMeasure) {
super(name); super(name);
this.root.push(new Attributes({ val: hpsMeasureValue(val) })); this.root.push(new Attributes({ val: hpsMeasureValue(val) }));
} }
@ -35,6 +40,11 @@ export class HpsMeasureElement extends XmlComponent {
// This represents element type CT_String, which indicate a string value. // This represents element type CT_String, which indicate a string value.
// //
// <xsd:complexType name="CT_Empty"/>
export class EmptyElement extends XmlComponent {}
// This represents element type CT_Empty, which indicate aan empty element.
//
// <xsd:complexType name="CT_String"> // <xsd:complexType name="CT_String">
// <xsd:attribute name="val" type="s:ST_String" use="required"/> // <xsd:attribute name="val" type="s:ST_String" use="required"/>
// </xsd:complexType> // </xsd:complexType>
@ -70,3 +80,19 @@ export class StringContainer extends XmlComponent {
this.root.push(val); this.root.push(val);
} }
} }
export class BuilderElement<T extends AttributeData> extends XmlComponent {
public constructor(options: {
readonly name: string;
readonly attributes?: AttributePayload<T>;
readonly children?: readonly XmlComponent[];
}) {
super(options.name);
if (options.attributes) {
this.root.push(new NextAttributeComponent(options.attributes));
}
// TODO: Children
}
}

View File

@ -12,7 +12,15 @@ export abstract class XmlComponent extends BaseXmlComponent {
this.root = new Array<BaseXmlComponent | string>(); this.root = new Array<BaseXmlComponent | string>();
} }
// This method is called by the formatter to get the XML representation of this component.
// It is called recursively for all child components.
// It is a serializer to be used in the xml library.
// https://www.npmjs.com/package/xml
// Child components can override this method to customize the XML representation, or execute side effects.
public prepForXml(context: IContext): IXmlableObject | undefined { public prepForXml(context: IContext): IXmlableObject | undefined {
// Mutating the stack is required for performance reasons
// eslint-disable-next-line functional/immutable-data
context.stack.push(this);
const children = this.root const children = this.root
.map((comp) => { .map((comp) => {
if (comp instanceof BaseXmlComponent) { if (comp instanceof BaseXmlComponent) {
@ -21,6 +29,9 @@ export abstract class XmlComponent extends BaseXmlComponent {
return comp; return comp;
}) })
.filter((comp) => comp !== undefined); // Exclude undefined .filter((comp) => comp !== undefined); // Exclude undefined
// eslint-disable-next-line functional/immutable-data
context.stack.pop();
// If we only have a single IXmlableObject in our children array and it // If we only have a single IXmlableObject in our children array and it
// represents our attributes, use the object itself as our children to // represents our attributes, use the object itself as our children to
// avoid an unneeded XML close element. // avoid an unneeded XML close element.

View File

@ -1,26 +0,0 @@
import { expect } from "chai";
import { ImportDotx } from "./import-dotx";
describe("ImportDotx", () => {
describe("#constructor", () => {
it("should create", () => {
const file = new ImportDotx();
expect(file).to.deep.equal({});
});
});
// describe("#extract", () => {
// it("should create", async () => {
// const file = new ImportDotx();
// const filePath = "./demo/dotx/template.dotx";
// const templateDocument = await file.extract(data);
// await file.extract(data);
// expect(templateDocument).to.be.equal({ currentRelationshipId: 1 });
// });
// });
});

View File

@ -1,266 +0,0 @@
/* eslint-disable */
// This will be deprecated soon
import * as JSZip from "jszip";
import { Element as XMLElement, ElementCompact as XMLElementCompact, xml2js } from "xml-js";
import { HeaderFooterReferenceType } from "@file/document/body/section-properties";
import { FooterWrapper, IDocumentFooter } from "@file/footer-wrapper";
import { HeaderWrapper, IDocumentHeader } from "@file/header-wrapper";
import { Media } from "@file/media";
import { TargetModeType } from "@file/relationships/relationship/relationship";
import { convertToXmlComponent, ImportedXmlComponent } from "@file/xml-components";
const schemeToType = {
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/header": "header",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer": "footer",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image": "image",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink": "hyperlink",
};
interface IDocumentRefs {
readonly headers: { readonly id: number; readonly type: HeaderFooterReferenceType }[];
readonly footers: { readonly id: number; readonly type: HeaderFooterReferenceType }[];
}
enum RelationshipType {
HEADER = "header",
FOOTER = "footer",
IMAGE = "image",
HYPERLINK = "hyperlink",
}
interface IRelationshipFileInfo {
readonly id: number;
readonly target: string;
readonly type: RelationshipType;
}
// Document Template
// https://fileinfo.com/extension/dotx
export interface IDocumentTemplate {
readonly currentRelationshipId: number;
readonly headers: IDocumentHeader[];
readonly footers: IDocumentFooter[];
readonly styles: string;
readonly titlePageIsDefined: boolean;
readonly media: Media;
}
export class ImportDotx {
public async extract(
data: Buffer | string | number[] | Uint8Array | ArrayBuffer | Blob | NodeJS.ReadableStream,
): Promise<IDocumentTemplate> {
const zipContent = await JSZip.loadAsync(data);
const documentContent = await zipContent.files["word/document.xml"].async("text");
const relationshipContent = await zipContent.files["word/_rels/document.xml.rels"].async("text");
const documentRefs = this.extractDocumentRefs(documentContent);
const documentRelationships = this.findReferenceFiles(relationshipContent);
const media = new Media();
const templateDocument: IDocumentTemplate = {
headers: await this.createHeaders(zipContent, documentRefs, documentRelationships, media, 0),
footers: await this.createFooters(zipContent, documentRefs, documentRelationships, media, documentRefs.headers.length),
currentRelationshipId: documentRefs.footers.length + documentRefs.headers.length,
styles: await zipContent.files["word/styles.xml"].async("text"),
titlePageIsDefined: this.checkIfTitlePageIsDefined(documentContent),
media: media,
};
return templateDocument;
}
private async createFooters(
zipContent: JSZip,
documentRefs: IDocumentRefs,
documentRelationships: IRelationshipFileInfo[],
media: Media,
startingRelationshipId: number,
): Promise<IDocumentFooter[]> {
const result = documentRefs.footers
.map(async (reference, i) => {
const relationshipFileInfo = documentRelationships.find((rel) => rel.id === reference.id);
if (relationshipFileInfo === null || !relationshipFileInfo) {
throw new Error(`Can not find target file for id ${reference.id}`);
}
const xmlData = await zipContent.files[`word/${relationshipFileInfo.target}`].async("text");
const xmlObj = xml2js(xmlData, { compact: false, captureSpacesBetweenElements: true }) as XMLElement;
if (!xmlObj.elements) {
return undefined;
}
const xmlElement = xmlObj.elements.reduce((acc, current) => (current.name === "w:ftr" ? current : acc));
const importedComp = convertToXmlComponent(xmlElement) as ImportedXmlComponent;
const wrapper = new FooterWrapper(media, startingRelationshipId + i, importedComp);
await this.addRelationshipToWrapper(relationshipFileInfo, zipContent, wrapper, media);
return { type: reference.type, footer: wrapper };
})
.filter((x) => !!x) as Promise<IDocumentFooter>[];
return Promise.all(result);
}
private async createHeaders(
zipContent: JSZip,
documentRefs: IDocumentRefs,
documentRelationships: IRelationshipFileInfo[],
media: Media,
startingRelationshipId: number,
): Promise<IDocumentHeader[]> {
const result = documentRefs.headers
.map(async (reference, i) => {
const relationshipFileInfo = documentRelationships.find((rel) => rel.id === reference.id);
if (relationshipFileInfo === null || !relationshipFileInfo) {
throw new Error(`Can not find target file for id ${reference.id}`);
}
const xmlData = await zipContent.files[`word/${relationshipFileInfo.target}`].async("text");
const xmlObj = xml2js(xmlData, { compact: false, captureSpacesBetweenElements: true }) as XMLElement;
if (!xmlObj.elements) {
return undefined;
}
const xmlElement = xmlObj.elements.reduce((acc, current) => (current.name === "w:hdr" ? current : acc));
const importedComp = convertToXmlComponent(xmlElement) as ImportedXmlComponent;
const wrapper = new HeaderWrapper(media, startingRelationshipId + i, importedComp);
await this.addRelationshipToWrapper(relationshipFileInfo, zipContent, wrapper, media);
return { type: reference.type, header: wrapper };
})
.filter((x) => !!x) as Promise<IDocumentHeader>[];
return Promise.all(result);
}
private async addRelationshipToWrapper(
relationshipFile: IRelationshipFileInfo,
zipContent: JSZip,
wrapper: HeaderWrapper | FooterWrapper,
media: Media,
): Promise<void> {
const refFile = zipContent.files[`word/_rels/${relationshipFile.target}.rels`];
if (!refFile) {
return;
}
const xmlRef = await refFile.async("text");
const wrapperImagesReferences = this.findReferenceFiles(xmlRef).filter((r) => r.type === RelationshipType.IMAGE);
const hyperLinkReferences = this.findReferenceFiles(xmlRef).filter((r) => r.type === RelationshipType.HYPERLINK);
for (const r of wrapperImagesReferences) {
const bufferType = JSZip.support.arraybuffer ? "arraybuffer" : "nodebuffer";
const buffer = await zipContent.files[`word/${r.target}`].async(bufferType);
const mediaData = media.addMedia(buffer, {
width: 100,
height: 100,
});
wrapper.Relationships.createRelationship(
r.id,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
}
for (const r of hyperLinkReferences) {
wrapper.Relationships.createRelationship(
r.id,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
r.target,
TargetModeType.EXTERNAL,
);
}
}
private findReferenceFiles(xmlData: string): IRelationshipFileInfo[] {
const xmlObj = xml2js(xmlData, { compact: true }) as XMLElementCompact;
const relationXmlArray = Array.isArray(xmlObj.Relationships.Relationship)
? xmlObj.Relationships.Relationship
: [xmlObj.Relationships.Relationship];
const relationships: IRelationshipFileInfo[] = relationXmlArray
.map((item: XMLElementCompact) => {
if (item._attributes === undefined) {
throw Error("relationship element has no attributes");
}
return {
id: this.parseRefId(item._attributes.Id as string),
type: schemeToType[item._attributes.Type as string],
target: item._attributes.Target as string,
};
})
.filter((item) => item.type !== null);
return relationships;
}
private extractDocumentRefs(xmlData: string): IDocumentRefs {
const xmlObj = xml2js(xmlData, { compact: true }) as XMLElementCompact;
const sectionProp = xmlObj["w:document"]["w:body"]["w:sectPr"];
const headerProps: XMLElementCompact = sectionProp["w:headerReference"];
let headersXmlArray: XMLElementCompact[];
if (headerProps === undefined) {
headersXmlArray = [];
} else if (Array.isArray(headerProps)) {
headersXmlArray = headerProps;
} else {
headersXmlArray = [headerProps];
}
const headers = headersXmlArray.map((item) => {
if (item._attributes === undefined) {
throw Error("header reference element has no attributes");
}
return {
type: item._attributes["w:type"] as HeaderFooterReferenceType,
id: this.parseRefId(item._attributes["r:id"] as string),
};
});
const footerProps: XMLElementCompact = sectionProp["w:footerReference"];
let footersXmlArray: XMLElementCompact[];
if (footerProps === undefined) {
footersXmlArray = [];
} else if (Array.isArray(footerProps)) {
footersXmlArray = footerProps;
} else {
footersXmlArray = [footerProps];
}
const footers = footersXmlArray.map((item) => {
if (item._attributes === undefined) {
throw Error("footer reference element has no attributes");
}
return {
type: item._attributes["w:type"] as HeaderFooterReferenceType,
id: this.parseRefId(item._attributes["r:id"] as string),
};
});
return { headers, footers };
}
private checkIfTitlePageIsDefined(xmlData: string): boolean {
const xmlObj = xml2js(xmlData, { compact: true }) as XMLElementCompact;
const sectionProp = xmlObj["w:document"]["w:body"]["w:sectPr"];
return sectionProp["w:titlePg"] !== undefined;
}
private parseRefId(str: string): number {
const match = /^rId(\d+)$/.exec(str);
if (match === null) {
throw new Error("Invalid ref id");
}
return parseInt(match[1], 10);
}
}

View File

@ -1 +0,0 @@
export * from "./import-dotx";

View File

@ -3,5 +3,5 @@
export { File as Document } from "./file"; export { File as Document } from "./file";
export * from "./file"; export * from "./file";
export * from "./export"; export * from "./export";
export * from "./import-dotx";
export * from "./util"; export * from "./util";
export * from "./patcher";

View File

@ -0,0 +1,51 @@
import { expect } from "chai";
import { appendContentType } from "./content-types-manager";
describe("content-types-manager", () => {
describe("appendContentType", () => {
it("should append a content type", () => {
const element = {
type: "element",
name: "xml",
elements: [
{
type: "element",
name: "Types",
elements: [
{
type: "element",
name: "Default",
},
],
},
],
};
appendContentType(element, "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "docx");
expect(element).to.deep.equal({
elements: [
{
elements: [
{
name: "Default",
type: "element",
},
{
attributes: {
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
Extension: "docx",
},
name: "Default",
type: "element",
},
],
name: "Types",
type: "element",
},
],
name: "xml",
type: "element",
});
});
});
});

View File

@ -0,0 +1,16 @@
import { Element } from "xml-js";
import { getFirstLevelElements } from "./util";
export const appendContentType = (element: Element, contentType: string, extension: string): void => {
const relationshipElements = getFirstLevelElements(element, "Types");
// eslint-disable-next-line functional/immutable-data
relationshipElements.push({
attributes: {
ContentType: contentType,
Extension: extension,
},
name: "Default",
type: "element",
});
};

View File

@ -0,0 +1,370 @@
import * as chai from "chai";
import * as sinon from "sinon";
import * as JSZip from "jszip";
import * as chaiAsPromised from "chai-as-promised";
import { ExternalHyperlink, ImageRun, Paragraph, TextRun } from "@file/paragraph";
import { patchDocument, PatchType } from "./from-docx";
chai.use(chaiAsPromised);
const { expect } = chai;
const MOCK_XML = `
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex"
xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex"
xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex"
xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex"
xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex"
xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex"
xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex"
xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex"
xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink"
xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:oel="http://schemas.microsoft.com/office/2019/extlst"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"
xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex"
xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid"
xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml"
xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash"
xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex"
xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"
xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk"
xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"
xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
<w:body>
<w:p w14:paraId="2499FE9F" w14:textId="0A3D130F" w:rsidR="00B51233"
w:rsidRDefault="007B52ED" w:rsidP="007B52ED">
<w:pPr>
<w:pStyle w:val="Title" />
</w:pPr>
<w:r>
<w:t>Hello World</w:t>
</w:r>
</w:p>
<w:p w14:paraId="6410D9A0" w14:textId="7579AB49" w:rsidR="007B52ED"
w:rsidRDefault="007B52ED" />
<w:p w14:paraId="57ACF964" w14:textId="315D7A05" w:rsidR="007B52ED"
w:rsidRDefault="007B52ED">
<w:r>
<w:t>Hello {{name}},</w:t>
</w:r>
<w:r w:rsidR="008126CB">
<w:t xml:space="preserve"> how are you?</w:t>
</w:r>
</w:p>
<w:p w14:paraId="38C7DF4A" w14:textId="66CDEC9A" w:rsidR="007B52ED"
w:rsidRDefault="007B52ED" />
<w:p w14:paraId="04FABE2B" w14:textId="3DACA001" w:rsidR="007B52ED"
w:rsidRDefault="007B52ED">
<w:r>
<w:t>{{paragraph_replace}}</w:t>
</w:r>
</w:p>
<w:p w14:paraId="7AD7975D" w14:textId="77777777" w:rsidR="00EF161F"
w:rsidRDefault="00EF161F" />
<w:p w14:paraId="3BD6D75A" w14:textId="19AE3121" w:rsidR="00EF161F"
w:rsidRDefault="00EF161F">
<w:r>
<w:t>{{table}}</w:t>
</w:r>
</w:p>
<w:p w14:paraId="76023962" w14:textId="4E606AB9" w:rsidR="007B52ED"
w:rsidRDefault="007B52ED" />
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="TableGrid" />
<w:tblW w:w="0" w:type="auto" />
<w:tblLook w:val="04A0" w:firstRow="1" w:lastRow="0" w:firstColumn="1"
w:lastColumn="0" w:noHBand="0" w:noVBand="1" />
</w:tblPr>
<w:tblGrid>
<w:gridCol w:w="3003" />
<w:gridCol w:w="3003" />
<w:gridCol w:w="3004" />
</w:tblGrid>
<w:tr w:rsidR="00EF161F" w14:paraId="1DEC5955" w14:textId="77777777" w:rsidTr="00EF161F">
<w:tc>
<w:tcPr>
<w:tcW w:w="3003" w:type="dxa" />
</w:tcPr>
<w:p w14:paraId="54DA5587" w14:textId="625BAC60" w:rsidR="00EF161F"
w:rsidRDefault="00EF161F">
<w:r>
<w:t>{{table_heading_1}}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="3003" w:type="dxa" />
</w:tcPr>
<w:p w14:paraId="57100910" w14:textId="71FD5616" w:rsidR="00EF161F"
w:rsidRDefault="00EF161F" />
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="3004" w:type="dxa" />
</w:tcPr>
<w:p w14:paraId="1D388FAB" w14:textId="77777777" w:rsidR="00EF161F"
w:rsidRDefault="00EF161F" />
</w:tc>
</w:tr>
<w:tr w:rsidR="00EF161F" w14:paraId="0F53D2DC" w14:textId="77777777" w:rsidTr="00EF161F">
<w:tc>
<w:tcPr>
<w:tcW w:w="3003" w:type="dxa" />
</w:tcPr>
<w:p w14:paraId="0F2BCCED" w14:textId="3C3B6706" w:rsidR="00EF161F"
w:rsidRDefault="00EF161F">
<w:r>
<w:t>Item: {{item_1}}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="3003" w:type="dxa" />
</w:tcPr>
<w:p w14:paraId="1E6158AC" w14:textId="77777777" w:rsidR="00EF161F"
w:rsidRDefault="00EF161F" />
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="3004" w:type="dxa" />
</w:tcPr>
<w:p w14:paraId="17937748" w14:textId="77777777" w:rsidR="00EF161F"
w:rsidRDefault="00EF161F" />
</w:tc>
</w:tr>
<w:tr w:rsidR="00EF161F" w14:paraId="781DAC1A" w14:textId="77777777" w:rsidTr="00EF161F">
<w:tc>
<w:tcPr>
<w:tcW w:w="3003" w:type="dxa" />
</w:tcPr>
<w:p w14:paraId="1DCD0343" w14:textId="77777777" w:rsidR="00EF161F"
w:rsidRDefault="00EF161F" />
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="3003" w:type="dxa" />
</w:tcPr>
<w:p w14:paraId="5D02E3CD" w14:textId="77777777" w:rsidR="00EF161F"
w:rsidRDefault="00EF161F" />
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="3004" w:type="dxa" />
</w:tcPr>
<w:p w14:paraId="52EA0DBB" w14:textId="77777777" w:rsidR="00EF161F"
w:rsidRDefault="00EF161F" />
</w:tc>
</w:tr>
</w:tbl>
<w:p w14:paraId="47CD1FBC" w14:textId="23474CBC" w:rsidR="007B52ED"
w:rsidRDefault="007B52ED" />
<w:p w14:paraId="0ACCEE90" w14:textId="67907499" w:rsidR="00EF161F"
w:rsidRDefault="0077578F">
<w:r>
<w:t>{{image_test}}</w:t>
</w:r>
</w:p>
<w:p w14:paraId="23FA9862" w14:textId="77777777" w:rsidR="0077578F"
w:rsidRDefault="0077578F" />
<w:p w14:paraId="01578F2F" w14:textId="3BDC6C85" w:rsidR="007B52ED"
w:rsidRDefault="007B52ED">
<w:r>
<w:t>Thank you</w:t>
</w:r>
</w:p>
<w:sectPr w:rsidR="007B52ED" w:rsidSect="0072043F">
<w:headerReference w:type="default" r:id="rId6" />
<w:footerReference w:type="default" r:id="rId7" />
<w:pgSz w:w="11900" w:h="16840" />
<w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="708"
w:footer="708" w:gutter="0" />
<w:cols w:space="708" />
<w:docGrid w:linePitch="360" />
</w:sectPr>
</w:body>
</w:document>
`;
describe("from-docx", () => {
describe("patchDocument", () => {
describe("document.xml and [Content_Types].xml", () => {
before(() => {
sinon.createStubInstance(JSZip, {});
sinon.stub(JSZip, "loadAsync").callsFake(
() =>
new Promise<JSZip>((resolve) => {
const zip = new JSZip();
zip.file("word/document.xml", MOCK_XML);
zip.file("[Content_Types].xml", `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>`);
resolve(zip);
}),
);
});
after(() => {
(JSZip.loadAsync as unknown as sinon.SinonStub).restore();
});
it("should patch the document", async () => {
const output = await patchDocument(Buffer.from(""), {
patches: {
name: {
type: PatchType.PARAGRAPH,
children: [new TextRun("Sir. "), new TextRun("John Doe"), new TextRun("(The Conqueror)")],
},
item_1: {
type: PatchType.PARAGRAPH,
children: [
new TextRun("#657"),
new ExternalHyperlink({
children: [
new TextRun({
text: "BBC News Link",
}),
],
link: "https://www.bbc.co.uk/news",
}),
],
},
// eslint-disable-next-line @typescript-eslint/naming-convention
paragraph_replace: {
type: PatchType.DOCUMENT,
children: [
new Paragraph({
children: [
new TextRun("This is a "),
new ExternalHyperlink({
children: [
new TextRun({
text: "Google Link",
}),
],
link: "https://www.google.co.uk",
}),
new ImageRun({
data: Buffer.from(""),
transformation: { width: 100, height: 100 },
}),
],
}),
],
},
// eslint-disable-next-line @typescript-eslint/naming-convention
image_test: {
type: PatchType.PARAGRAPH,
children: [
new ImageRun({
data: Buffer.from(""),
transformation: { width: 100, height: 100 },
}),
],
},
},
});
expect(output).to.not.be.undefined;
});
it("should patch the document", async () => {
const output = await patchDocument(Buffer.from(""), {
patches: {},
});
expect(output).to.not.be.undefined;
});
});
describe("document.xml and [Content_Types].xml with relationships", () => {
before(() => {
sinon.createStubInstance(JSZip, {});
sinon.stub(JSZip, "loadAsync").callsFake(
() =>
new Promise<JSZip>((resolve) => {
const zip = new JSZip();
zip.file("word/document.xml", MOCK_XML);
zip.file("word/_rels/document.xml.rels", `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>`);
zip.file("[Content_Types].xml", `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>`);
resolve(zip);
}),
);
});
after(() => {
(JSZip.loadAsync as unknown as sinon.SinonStub).restore();
});
it("should use the relationships file rather than create one", async () => {
const output = await patchDocument(Buffer.from(""), {
patches: {
// eslint-disable-next-line @typescript-eslint/naming-convention
image_test: {
type: PatchType.PARAGRAPH,
children: [
new ImageRun({
data: Buffer.from(""),
transformation: { width: 100, height: 100 },
}),
],
},
},
});
expect(output).to.not.be.undefined;
});
});
describe("document.xml", () => {
before(() => {
sinon.createStubInstance(JSZip, {});
sinon.stub(JSZip, "loadAsync").callsFake(
() =>
new Promise<JSZip>((resolve) => {
const zip = new JSZip();
zip.file("word/document.xml", MOCK_XML);
resolve(zip);
}),
);
});
after(() => {
(JSZip.loadAsync as unknown as sinon.SinonStub).restore();
});
it("should throw an error if the content types is not found", () =>
expect(
patchDocument(Buffer.from(""), {
patches: {
// eslint-disable-next-line @typescript-eslint/naming-convention
image_test: {
type: PatchType.PARAGRAPH,
children: [
new ImageRun({
data: Buffer.from(""),
transformation: { width: 100, height: 100 },
}),
],
},
},
}),
).to.eventually.be.rejected);
});
});
});

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