@docx4j/core-ts 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +4 -0
- package/README.md +32 -4
- package/dist/html/convert.mjs +2 -1
- package/dist/html/elements.mjs +2 -1
- package/dist/model/color/ColorMath.d.mts +29 -0
- package/dist/model/color/ColorMath.mjs +146 -0
- package/dist/model/color/ColorTables.d.mts +6 -0
- package/dist/model/color/ColorTables.mjs +83 -0
- package/dist/model/color/DrawingMLColors.d.mts +52 -0
- package/dist/model/color/DrawingMLColors.mjs +374 -0
- package/dist/model/color/ResolvedColor.d.mts +36 -0
- package/dist/model/color/ResolvedColor.mjs +65 -0
- package/dist/model/color/SpreadsheetColors.d.mts +36 -0
- package/dist/model/color/SpreadsheetColors.mjs +84 -0
- package/dist/model/color/StyleFill.d.mts +28 -0
- package/dist/model/color/StyleFill.mjs +21 -0
- package/dist/model/color/ThemeColors.d.mts +86 -0
- package/dist/model/color/ThemeColors.mjs +304 -0
- package/dist/model/color/WordColors.d.mts +71 -0
- package/dist/model/color/WordColors.mjs +121 -0
- package/dist/model/color/index.d.mts +6 -0
- package/dist/model/color/index.mjs +30 -0
- package/dist/model/content/Body.d.mts +145 -23
- package/dist/model/content/Body.mjs +509 -141
- package/dist/model/content/Comment.d.mts +21 -3
- package/dist/model/content/Comment.mjs +195 -19
- package/dist/model/content/ContentControl.d.mts +197 -18
- package/dist/model/content/ContentControl.mjs +664 -95
- package/dist/model/content/Font.d.mts +67 -17
- package/dist/model/content/Font.mjs +114 -35
- package/dist/model/content/InlinePicture.d.mts +11 -0
- package/dist/model/content/InlinePicture.mjs +21 -1
- package/dist/model/content/List.mjs +3 -0
- package/dist/model/content/Paragraph.d.mts +189 -13
- package/dist/model/content/Paragraph.mjs +870 -74
- package/dist/model/content/Range.d.mts +227 -12
- package/dist/model/content/Range.mjs +785 -59
- package/dist/model/content/ResolvedView.d.mts +104 -0
- package/dist/model/content/ResolvedView.mjs +596 -0
- package/dist/model/content/Table.d.mts +29 -3
- package/dist/model/content/Table.mjs +109 -33
- package/dist/model/content/TrackedChange.d.mts +172 -13
- package/dist/model/content/TrackedChange.mjs +728 -167
- package/dist/model/content/comments.d.mts +20 -6
- package/dist/model/content/comments.mjs +67 -57
- package/dist/model/content/generalException.d.mts +18 -0
- package/dist/model/content/generalException.mjs +24 -0
- package/dist/model/content/index.d.mts +8 -3
- package/dist/model/content/index.mjs +7 -2
- package/dist/model/content/mathText.d.mts +21 -0
- package/dist/model/content/mathText.mjs +267 -0
- package/dist/model/content/officeText.d.mts +27 -0
- package/dist/model/content/officeText.mjs +74 -0
- package/dist/model/content/outline.d.mts +5 -0
- package/dist/model/content/outline.mjs +13 -0
- package/dist/model/content/placeholders.d.mts +110 -0
- package/dist/model/content/placeholders.mjs +253 -0
- package/dist/model/content/search.d.mts +72 -0
- package/dist/model/content/search.mjs +204 -2
- package/dist/model/content/spanEdits.d.mts +159 -0
- package/dist/model/content/spanEdits.mjs +728 -0
- package/dist/model/content/story.d.mts +44 -0
- package/dist/model/content/story.mjs +92 -0
- package/dist/model/content/tableColumns.d.mts +1 -1
- package/dist/model/content/tableColumns.mjs +108 -80
- package/dist/model/content/tableRevisions.d.mts +11 -3
- package/dist/model/content/tableRevisions.mjs +72 -42
- package/dist/model/content/tableRules.d.mts +30 -0
- package/dist/model/content/tableRules.mjs +100 -0
- package/dist/model/content/textBoxes.d.mts +18 -0
- package/dist/model/content/textBoxes.mjs +105 -0
- package/dist/model/content/trackedChangeFilter.d.mts +39 -0
- package/dist/model/content/trackedChangeFilter.mjs +81 -0
- package/dist/model/content/tracking.d.mts +28 -0
- package/dist/model/content/tracking.mjs +149 -10
- package/dist/model/content/tree.d.mts +171 -22
- package/dist/model/content/tree.mjs +329 -53
- package/dist/model/customxml/CustomXmlPartCollection.d.mts +8 -0
- package/dist/model/customxml/CustomXmlPartCollection.mjs +34 -11
- package/dist/model/customxml/XmlMapping.d.mts +1 -1
- package/dist/model/customxml/XmlMapping.mjs +11 -0
- package/dist/model/customxml/bindings.d.mts +21 -2
- package/dist/model/customxml/bindings.mjs +76 -32
- package/dist/model/customxml/kinds.d.mts +8 -3
- package/dist/model/customxml/kinds.mjs +26 -5
- package/dist/model/customxml/picturePlaceholder.d.mts +17 -0
- package/dist/model/customxml/picturePlaceholder.mjs +32 -0
- package/dist/model/customxml/pictures.d.mts +4 -3
- package/dist/model/customxml/pictures.mjs +18 -6
- package/dist/model/customxml/xhtml.mjs +8 -2
- package/dist/model/index.d.mts +2 -0
- package/dist/model/index.mjs +4 -0
- package/dist/model/listnumbering/Emulator.d.mts +37 -5
- package/dist/model/listnumbering/Emulator.mjs +63 -9
- package/dist/model/properties/PropertyResolver.d.mts +60 -1
- package/dist/model/properties/PropertyResolver.mjs +115 -2
- package/dist/model/properties/catalogue.d.mts +19 -5
- package/dist/model/properties/catalogue.mjs +41 -15
- package/dist/model/properties/log.d.mts +1 -1
- package/dist/model/properties/log.mjs +5 -5
- package/dist/model/properties/table.mjs +4 -2
- package/dist/model/text/Extractor.d.mts +289 -0
- package/dist/model/text/Extractor.mjs +2162 -0
- package/dist/model/text/LinkTargets.d.mts +45 -0
- package/dist/model/text/LinkTargets.mjs +170 -0
- package/dist/model/text/MarkdownExporter.d.mts +140 -0
- package/dist/model/text/MarkdownExporter.mjs +255 -0
- package/dist/model/text/PlainText.d.mts +29 -0
- package/dist/model/text/PlainText.mjs +539 -0
- package/dist/model/text/TextContext.d.mts +161 -0
- package/dist/model/text/TextContext.mjs +425 -0
- package/dist/model/text/TextOptions.d.mts +150 -0
- package/dist/model/text/TextOptions.mjs +278 -0
- package/dist/model/text/TextResult.d.mts +504 -0
- package/dist/model/text/TextResult.mjs +526 -0
- package/dist/model/text/Texts.d.mts +99 -0
- package/dist/model/text/Texts.mjs +187 -0
- package/dist/model/text/WmlToMarkdown.d.mts +120 -0
- package/dist/model/text/WmlToMarkdown.mjs +911 -0
- package/dist/model/text/commonmark.d.mts +121 -0
- package/dist/model/text/commonmark.mjs +655 -0
- package/dist/model/text/index.d.mts +7 -0
- package/dist/model/text/index.mjs +8 -0
- package/dist/model/text/normalize.d.mts +8 -0
- package/dist/model/text/normalize.mjs +13 -0
- package/dist/model/text/outline.d.mts +4 -0
- package/dist/model/text/outline.mjs +71 -0
- package/dist/office-js/fragment.d.mts +7 -5
- package/dist/office-js/fragment.mjs +63 -14
- package/dist/office-js/proxy.d.mts +8 -0
- package/dist/office-js/proxy.mjs +29 -0
- package/dist/office-js/run.mjs +2 -0
- package/dist/office-js/supported.generated.mjs +16 -0
- package/dist/office-js/toApiScript.mjs +21 -5
- package/dist/opc/Save.d.mts +17 -0
- package/dist/opc/Save.mjs +12 -2
- package/dist/opc/index.d.mts +3 -3
- package/dist/opc/index.mjs +1 -1
- package/dist/opc/mce/preprocessor.d.mts +28 -3
- package/dist/opc/mce/preprocessor.mjs +4 -4
- package/dist/opc/mce/understood.d.mts +30 -6
- package/dist/opc/mce/understood.mjs +37 -7
- package/dist/packages/OpcPackage.d.mts +13 -0
- package/dist/packages/OpcPackage.mjs +1 -0
- package/dist/packages/WordprocessingMLPackage.d.mts +45 -8
- package/dist/packages/WordprocessingMLPackage.mjs +155 -20
- package/dist/parts/DefaultXmlPart.mjs +2 -2
- package/dist/parts/Part.d.mts +10 -2
- package/dist/parts/XmlPart.d.mts +12 -30
- package/dist/parts/XmlPart.mjs +44 -93
- package/dist/parts/wml/comments.mjs +30 -0
- package/dist/parts/wml/index.mjs +12 -0
- package/dist/xml/dom.d.mts +7 -0
- package/dist/xml/dom.mjs +18 -0
- package/package.json +2 -2
package/NOTICE
CHANGED
|
@@ -10,3 +10,7 @@ resolution utilities follow docx4j's design and names. It depends on @docx4j/gen
|
|
|
10
10
|
(https://github.com/plutext/docx4j-generated-objects-ts) for the Office Open XML object model and on
|
|
11
11
|
@docx4j/jsonix (https://github.com/plutext/jsonix) for XML binding; see their NOTICE files for the
|
|
12
12
|
material they derive from (ECMA-376, Microsoft Open Specifications, Jsonix).
|
|
13
|
+
|
|
14
|
+
The Markdown writer (src/model/text/commonmark.mts) is a port of the Markdown renderer of
|
|
15
|
+
commonmark-java (https://github.com/commonmark/commonmark-java), Copyright (c) 2015, Atlassian Pty
|
|
16
|
+
Ltd, under the BSD 2-Clause License; its notice and conditions are kept in that file.
|
package/README.md
CHANGED
|
@@ -45,9 +45,11 @@ const ooxml = await pkg.saveFlatOpc(); // pkg:package, for insertOo
|
|
|
45
45
|
A part that is never touched is written back byte for byte; `getContents()` (or a view over
|
|
46
46
|
it) marks a part for re-marshalling. `mc:AlternateContent` is kept with every branch, as docx4j
|
|
47
47
|
keeps it: the content API reads the branch Word would (the first `mc:Choice` whose namespaces are
|
|
48
|
-
understood, else the `mc:Fallback`)
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
understood, else the `mc:Fallback`) at every level, and a save writes them all (`{ mcePreprocess: true }`
|
|
49
|
+
resolves the element when a part is unmarshalled instead, as Word does on open). Among a paragraph's runs
|
|
50
|
+
the branch read is edited in place and the others kept (CR-012 section 12). At block, row and cell level a
|
|
51
|
+
view in a branch is read-only (`NotSupportedError`), while resolving tracked changes, `replaceText`, a
|
|
52
|
+
tracked deletion, the column edits and the binding passes reach every branch (CR-013). Subpaths
|
|
51
53
|
`@docx4j/core-ts/opc`, `/parts`, `/packages` and `/model` give the layers separately,
|
|
52
54
|
`/office-js` the `Word` shim (below), `/html` HTML to WordprocessingML (a converter to an
|
|
53
55
|
intermediate form and a builder from it, CR-005 section 8; the HTML parser is yours, a browser's
|
|
@@ -238,7 +240,33 @@ body.acceptAll(); // or rejectAll(), or accept()/reject() one at a time
|
|
|
238
240
|
`getTrackedChanges()` is also on `Paragraph` and `Range`. Text and searches read the accepted
|
|
239
241
|
view throughout, so an agent sees the document as it will read once the changes are taken. A moved
|
|
240
242
|
paragraph is listed as its two halves, and accepting or rejecting either resolves the whole move,
|
|
241
|
-
as Word's Review tab does.
|
|
243
|
+
as Word's Review tab does. `accept()` and `reject()` return whether they acted: a change already
|
|
244
|
+
resolved since it was listed, by its own view or another, is left alone and gives `false` (Office
|
|
245
|
+
JS's return nothing).
|
|
246
|
+
|
|
247
|
+
A body is one story. Every story at once - the main document, each footnote, endnote and comment,
|
|
248
|
+
the headers and footers in the order the sections reference them, and the text boxes in each - is
|
|
249
|
+
the package's, as docx4j lists it (`TrackedChanges.in`), with docx4j's kind and the part of each
|
|
250
|
+
change. The listing and the resolve-all verbs take a filter: docx4j's conditions as an object, which
|
|
251
|
+
travels as JSON, or a function over each single change. A group of touching changes is listed whole
|
|
252
|
+
when any of its pieces matches, and resolved only in the pieces that match:
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
for (const change of await pkg.getAllTrackedChanges()) {
|
|
256
|
+
change.kind; // docx4j's: 'RUN_INSERTION', 'PARAGRAPH_MARK_DELETION', 'TABLE_PROPERTIES', ...
|
|
257
|
+
change.part.partName.name; // '/word/document.xml', '/word/footnotes.xml', '/word/header1.xml', ...
|
|
258
|
+
}
|
|
259
|
+
await pkg.rejectAllRevisions({ authors: ['Author B'] });
|
|
260
|
+
await pkg.acceptAllRevisions({ types: ['Deleted'], from: '2026-10-01', parts: ['/word/document.xml'] });
|
|
261
|
+
await pkg.acceptAllRevisions((change) => change.author === 'Claude');
|
|
262
|
+
body.acceptAll({ kinds: ['RUN_DELETION'] }); // one story; a deleted paragraph's text goes, its mark stays
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
The conditions are `authors`, `types` (Office JS's names or docx4j's `ADDED`, `DELETED`,
|
|
266
|
+
`FORMATTED`), `kinds`, `from` (inclusive) and `to` (exclusive), and `parts` (a part or its name).
|
|
267
|
+
A key or a value the filter does not know throws a `TypeError`, before anything is resolved. With a
|
|
268
|
+
filter, what no change owns (a `w:cellMerge`, a `w:numberingChange`) is left alone; without one it is
|
|
269
|
+
swept, as before. Each verb returns how many listed changes had a matching piece.
|
|
242
270
|
|
|
243
271
|
To record one caller's edits without touching the document's own setting - an agent working in a
|
|
244
272
|
document whose `w:trackRevisions` belongs to its owner - use `withTracking`. Nothing is written
|
package/dist/html/convert.mjs
CHANGED
|
@@ -415,7 +415,8 @@ function cellFrom(el, w) {
|
|
|
415
415
|
var _a, _b;
|
|
416
416
|
const blocks = [];
|
|
417
417
|
walkBlocks(el, blocks, w);
|
|
418
|
-
|
|
418
|
+
// a cell ends with a paragraph, as Word reads it, after a table too (CR-002 section 55)
|
|
419
|
+
if (blocks.length === 0 || blocks[blocks.length - 1].kind === 'table') {
|
|
419
420
|
blocks.push({ kind: 'paragraph', style: null, inlines: [] });
|
|
420
421
|
w.report.paragraphs++;
|
|
421
422
|
}
|
package/dist/html/elements.mjs
CHANGED
|
@@ -142,7 +142,8 @@ function tableXml(t, resolve) {
|
|
|
142
142
|
w += (_a = widths[col + k]) !== null && _a !== void 0 ? _a : widths[0]; return w; };
|
|
143
143
|
const tcPr = (col, span, merge) => `<w:tcPr><w:tcW w:w="${widthOf(col, span)}" w:type="dxa"/>${span > 1 ? `<w:gridSpan w:val="${span}"/>` : ''}${merge === 'restart' ? '<w:vMerge w:val="restart"/>' : merge === 'continue' ? '<w:vMerge/>' : ''}</w:tcPr>`;
|
|
144
144
|
const cellXml = (c, col) => {
|
|
145
|
-
const
|
|
145
|
+
const last = c.blocks[c.blocks.length - 1];
|
|
146
|
+
const blocks = last === undefined ? '<w:p/>' : blocksToXml(c.blocks, resolve) + (last.kind === 'table' ? '<w:p/>' : '');
|
|
146
147
|
return `<w:tc>${tcPr(col, c.colspan, c.rowspan > 1 ? 'restart' : undefined)}${blocks}</w:tc>`;
|
|
147
148
|
};
|
|
148
149
|
// A cell spanning rows holds its place in the rows below with a continuation cell, as WordprocessingML writes a vertical merge.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** sRGB (0 to 1) to linear RGB (IEC 61966-2-1). */
|
|
2
|
+
export declare function toLinear(c: number): number;
|
|
3
|
+
/** linear RGB to sRGB, clamped to 0 to 1. */
|
|
4
|
+
export declare function toSrgb(l: number): number;
|
|
5
|
+
export declare function clamp01(v: number): number;
|
|
6
|
+
/** a channel, 0 to 1, as 0 to 255, rounded half up */
|
|
7
|
+
export declare function channel(v: number): number;
|
|
8
|
+
/** a channel, 0 to 1, as 0 to 255, rounded half down (Office's luminance transforms) */
|
|
9
|
+
export declare function channelHalfDown(v: number): number;
|
|
10
|
+
/** [h, s, l], each 0 to 1, from sRGB channels 0 to 1; a grey's hue is 0 */
|
|
11
|
+
export declare function rgbToHsl(r: number, g: number, b: number): [number, number, number];
|
|
12
|
+
/**
|
|
13
|
+
* sRGB channels (0 to 1, clamped) from HSL; the saturation is not clamped, as Office does not clamp it (a
|
|
14
|
+
* saturation above 1 pushes a channel past its range, which is then clamped).
|
|
15
|
+
*/
|
|
16
|
+
export declare function hslToRgb(h: number, s: number, l: number): [number, number, number];
|
|
17
|
+
/**
|
|
18
|
+
* sRGB channels (0 to 1, not clamped) from HSL as Foley and van Dam give it: the same colour as {@link hslToRgb}
|
|
19
|
+
* but not the same rounding error, and the one Office's luminance transforms round as.
|
|
20
|
+
*/
|
|
21
|
+
export declare function hslToRgbFoley(h: number, s: number, l: number): [number, number, number];
|
|
22
|
+
export declare const HLSMAX = 240;
|
|
23
|
+
/** [h, l, s] on 0 to 240, as Windows' ColorRGBToHLS (KB29240) computes them */
|
|
24
|
+
export declare function rgbToHls240(r: number, g: number, b: number): [number, number, number];
|
|
25
|
+
/**
|
|
26
|
+
* RGB from {@link rgbToHls240}'s values, as Windows' ColorHLSToRGB, except that a grey is rounded rather than
|
|
27
|
+
* truncated, which is what Excel's fills show (docx4j CR-034 section 11, P4).
|
|
28
|
+
*/
|
|
29
|
+
export declare function hls240ToRgb(h: number, l: number, s: number): [number, number, number];
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// The colour arithmetic Office uses, as docx4j CR-034's probes measured it (section 11): sRGB's transfer function,
|
|
2
|
+
// HSL with an unclamped saturation, and Windows' integer HLS for SpreadsheetML tints. docx4j
|
|
3
|
+
// `org.docx4j.model.color.ColorMath`, expression for expression: JS numbers are IEEE doubles as Java's are, so the
|
|
4
|
+
// same expressions in the same order give the same bits, which the luminance transforms' rounding depends on
|
|
5
|
+
// (CR-008 section 3). Java's integer division is `Math.trunc` of the quotient here; nothing is simplified.
|
|
6
|
+
// ------------------------------------------------------------------ sRGB and linear RGB
|
|
7
|
+
/** sRGB (0 to 1) to linear RGB (IEC 61966-2-1). */
|
|
8
|
+
export function toLinear(c) {
|
|
9
|
+
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
10
|
+
}
|
|
11
|
+
/** linear RGB to sRGB, clamped to 0 to 1. */
|
|
12
|
+
export function toSrgb(l) {
|
|
13
|
+
const c = clamp01(l);
|
|
14
|
+
return c <= 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
|
|
15
|
+
}
|
|
16
|
+
export function clamp01(v) {
|
|
17
|
+
return v < 0 ? 0 : v > 1 ? 1 : v;
|
|
18
|
+
}
|
|
19
|
+
/** a channel, 0 to 1, as 0 to 255, rounded half up */
|
|
20
|
+
export function channel(v) {
|
|
21
|
+
return Math.floor(clamp01(v) * 255 + 0.5);
|
|
22
|
+
}
|
|
23
|
+
/** a channel, 0 to 1, as 0 to 255, rounded half down (Office's luminance transforms) */
|
|
24
|
+
export function channelHalfDown(v) {
|
|
25
|
+
// Math.ceil(-0.5) is -0 in JS, 0 in Java's (int) cast; ResolvedColor's clamp makes either 0
|
|
26
|
+
return Math.ceil(clamp01(v) * 255 - 0.5);
|
|
27
|
+
}
|
|
28
|
+
// ------------------------------------------------------------------ HSL
|
|
29
|
+
/** [h, s, l], each 0 to 1, from sRGB channels 0 to 1; a grey's hue is 0 */
|
|
30
|
+
export function rgbToHsl(r, g, b) {
|
|
31
|
+
const max = Math.max(r, Math.max(g, b)), min = Math.min(r, Math.min(g, b));
|
|
32
|
+
const l = (max + min) / 2;
|
|
33
|
+
if (max === min)
|
|
34
|
+
return [0, 0, l];
|
|
35
|
+
const d = max - min;
|
|
36
|
+
const s = l <= 0.5 ? d / (max + min) : d / (2 - max - min);
|
|
37
|
+
let h;
|
|
38
|
+
if (max === r) {
|
|
39
|
+
h = ((g - b) / d) % 6;
|
|
40
|
+
if (h < 0)
|
|
41
|
+
h += 6;
|
|
42
|
+
}
|
|
43
|
+
else if (max === g) {
|
|
44
|
+
h = (b - r) / d + 2;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
h = (r - g) / d + 4;
|
|
48
|
+
}
|
|
49
|
+
return [h / 6, s, l];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* sRGB channels (0 to 1, clamped) from HSL; the saturation is not clamped, as Office does not clamp it (a
|
|
53
|
+
* saturation above 1 pushes a channel past its range, which is then clamped).
|
|
54
|
+
*/
|
|
55
|
+
export function hslToRgb(h, s, l) {
|
|
56
|
+
return [hslChannel(0, h, s, l), hslChannel(8, h, s, l), hslChannel(4, h, s, l)];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* sRGB channels (0 to 1, not clamped) from HSL as Foley and van Dam give it: the same colour as {@link hslToRgb}
|
|
60
|
+
* but not the same rounding error, and the one Office's luminance transforms round as.
|
|
61
|
+
*/
|
|
62
|
+
export function hslToRgbFoley(h, s, l) {
|
|
63
|
+
// keep this form and its order of operations, and don't fold it into hslToRgb: a channel that is exactly half a
|
|
64
|
+
// unit rounds (channelHalfDown) the way this form's floating-point error leans, which is the way Office rounds it
|
|
65
|
+
// (docx4j CR-034 section 11, follow-up: 29 of 30 halves; hslToRgb's error leans otherwise)
|
|
66
|
+
const m2 = l <= 0.5 ? l * (1 + s) : l + s - l * s, m1 = 2 * l - m2;
|
|
67
|
+
return [foley(m1, m2, h + 1 / 3.0), foley(m1, m2, h), foley(m1, m2, h - 1 / 3.0)];
|
|
68
|
+
}
|
|
69
|
+
function foley(m1, m2, h) {
|
|
70
|
+
h -= Math.floor(h);
|
|
71
|
+
if (h < 1 / 6.0)
|
|
72
|
+
return m1 + (m2 - m1) * 6 * h;
|
|
73
|
+
if (h < 1 / 2.0)
|
|
74
|
+
return m2;
|
|
75
|
+
if (h < 2 / 3.0)
|
|
76
|
+
return m1 + (m2 - m1) * (2 / 3.0 - h) * 6;
|
|
77
|
+
return m1;
|
|
78
|
+
}
|
|
79
|
+
function hslChannel(n, h, s, l) {
|
|
80
|
+
let k = (n + h * 12) % 12;
|
|
81
|
+
if (k < 0)
|
|
82
|
+
k += 12;
|
|
83
|
+
const a = s * Math.min(l, 1 - l);
|
|
84
|
+
return clamp01(l - a * Math.max(-1, Math.min(Math.min(k - 3, 9 - k), 1)));
|
|
85
|
+
}
|
|
86
|
+
// ------------------------------------------------------------------ Windows' integer HLS (Excel)
|
|
87
|
+
export const HLSMAX = 240;
|
|
88
|
+
const RGBMAX = 255;
|
|
89
|
+
/** Java's int division. */
|
|
90
|
+
const div = (a, b) => Math.trunc(a / b);
|
|
91
|
+
/** [h, l, s] on 0 to 240, as Windows' ColorRGBToHLS (KB29240) computes them */
|
|
92
|
+
export function rgbToHls240(r, g, b) {
|
|
93
|
+
const max = Math.max(r, Math.max(g, b)), min = Math.min(r, Math.min(g, b));
|
|
94
|
+
const l = div((max + min) * HLSMAX + RGBMAX, 2 * RGBMAX);
|
|
95
|
+
if (max === min)
|
|
96
|
+
return [div(HLSMAX * 2, 3), l, 0];
|
|
97
|
+
const s = l <= div(HLSMAX, 2)
|
|
98
|
+
? div((max - min) * HLSMAX + div(max + min, 2), max + min)
|
|
99
|
+
: div((max - min) * HLSMAX + div(2 * RGBMAX - max - min, 2), 2 * RGBMAX - max - min);
|
|
100
|
+
const d = max - min;
|
|
101
|
+
const rd = div((max - r) * div(HLSMAX, 6) + div(d, 2), d);
|
|
102
|
+
const gd = div((max - g) * div(HLSMAX, 6) + div(d, 2), d);
|
|
103
|
+
const bd = div((max - b) * div(HLSMAX, 6) + div(d, 2), d);
|
|
104
|
+
let h;
|
|
105
|
+
if (r === max)
|
|
106
|
+
h = bd - gd;
|
|
107
|
+
else if (g === max)
|
|
108
|
+
h = div(HLSMAX, 3) + rd - bd;
|
|
109
|
+
else
|
|
110
|
+
h = div(2 * HLSMAX, 3) + gd - rd;
|
|
111
|
+
if (h < 0)
|
|
112
|
+
h += HLSMAX;
|
|
113
|
+
if (h > HLSMAX)
|
|
114
|
+
h -= HLSMAX;
|
|
115
|
+
return [h, l, s];
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* RGB from {@link rgbToHls240}'s values, as Windows' ColorHLSToRGB, except that a grey is rounded rather than
|
|
119
|
+
* truncated, which is what Excel's fills show (docx4j CR-034 section 11, P4).
|
|
120
|
+
*/
|
|
121
|
+
export function hls240ToRgb(h, l, s) {
|
|
122
|
+
if (s === 0) {
|
|
123
|
+
const v = div(l * RGBMAX + div(HLSMAX, 2), HLSMAX);
|
|
124
|
+
return [v, v, v];
|
|
125
|
+
}
|
|
126
|
+
const m2 = l <= div(HLSMAX, 2) ? div(l * (HLSMAX + s) + div(HLSMAX, 2), HLSMAX) : l + s - div(l * s + div(HLSMAX, 2), HLSMAX);
|
|
127
|
+
const m1 = 2 * l - m2;
|
|
128
|
+
return [
|
|
129
|
+
div(hueToRgb(m1, m2, h + div(HLSMAX, 3)) * RGBMAX + div(HLSMAX, 2), HLSMAX),
|
|
130
|
+
div(hueToRgb(m1, m2, h) * RGBMAX + div(HLSMAX, 2), HLSMAX),
|
|
131
|
+
div(hueToRgb(m1, m2, h - div(HLSMAX, 3)) * RGBMAX + div(HLSMAX, 2), HLSMAX)
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
function hueToRgb(n1, n2, hue) {
|
|
135
|
+
if (hue < 0)
|
|
136
|
+
hue += HLSMAX;
|
|
137
|
+
if (hue > HLSMAX)
|
|
138
|
+
hue -= HLSMAX;
|
|
139
|
+
if (hue < div(HLSMAX, 6))
|
|
140
|
+
return n1 + div((n2 - n1) * hue + div(HLSMAX, 12), div(HLSMAX, 6));
|
|
141
|
+
if (hue < div(HLSMAX, 2))
|
|
142
|
+
return n2;
|
|
143
|
+
if (hue < div(HLSMAX * 2, 3))
|
|
144
|
+
return n1 + div((n2 - n1) * (div(HLSMAX * 2, 3) - hue) + div(HLSMAX, 12), div(HLSMAX, 6));
|
|
145
|
+
return n1;
|
|
146
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** `a:prstClr` names to RRGGBB. */
|
|
2
|
+
export declare const PRESET: ReadonlyMap<string, string>;
|
|
3
|
+
/** `a:sysClr` names to Windows' default RRGGBB. */
|
|
4
|
+
export declare const SYSTEM: ReadonlyMap<string, string>;
|
|
5
|
+
/** SpreadsheetML indexed colours 0 to 65. */
|
|
6
|
+
export declare const INDEXED: readonly string[];
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// The fixed colour tables: DrawingML's preset colours (`a:prstClr`), Windows' default system colours (`a:sysClr`,
|
|
2
|
+
// which Office draws as the machine's colour, not `lastClr`: docx4j CR-034 section 11), and SpreadsheetML's legacy
|
|
3
|
+
// indexed palette. docx4j `org.docx4j.model.color.ColorTables`, copied entry for entry.
|
|
4
|
+
//
|
|
5
|
+
// The preset and system values are Apache POI's `org.apache.poi.sl.usermodel.PresetColor` (trunk ae62bb5116,
|
|
6
|
+
// Apache-2.0), keyed by the names docx4j's schema gives `ST_PresetColorVal` and `ST_SystemColorVal`. The indexed
|
|
7
|
+
// palette is Excel 365's, read from its PDF of CR-034's probe tc-p4-spreadsheet.xlsx (2026-10-12): entries 0 to 63,
|
|
8
|
+
// then 64 and 65, the system foreground and background.
|
|
9
|
+
/** `a:prstClr` names to RRGGBB. */
|
|
10
|
+
export const PRESET = new Map(Object.entries({
|
|
11
|
+
aliceBlue: 'F0F8FF', antiqueWhite: 'FAEBD7', aqua: '00FFFF',
|
|
12
|
+
aquamarine: '7FFFD4', azure: 'F0FFFF', beige: 'F5F5DC',
|
|
13
|
+
bisque: 'FFE4C4', black: '000000', blanchedAlmond: 'FFEBCD',
|
|
14
|
+
blue: '0000FF', blueViolet: '8A2BE2', brown: 'A52A2A',
|
|
15
|
+
burlyWood: 'DEB887', cadetBlue: '5F9EA0', chartreuse: '7FFF00',
|
|
16
|
+
chocolate: 'D2691E', coral: 'FF7F50', cornflowerBlue: '6495ED',
|
|
17
|
+
cornsilk: 'FFF8DC', crimson: 'DC143C', cyan: '00FFFF',
|
|
18
|
+
dkBlue: '00008B', dkCyan: '008B8B', dkGoldenrod: 'B8860B',
|
|
19
|
+
dkGray: 'A9A9A9', dkGreen: '006400', dkKhaki: 'BDB76B',
|
|
20
|
+
dkMagenta: '8B008B', dkOliveGreen: '556B2F', dkOrange: 'FF8C00',
|
|
21
|
+
dkOrchid: '9932CC', dkRed: '8B0000', dkSalmon: 'E9967A',
|
|
22
|
+
dkSeaGreen: '8FBC8B', dkSlateBlue: '483D8B', dkSlateGray: '2F4F4F',
|
|
23
|
+
dkTurquoise: '00CED1', dkViolet: '9400D3', deepPink: 'FF1493',
|
|
24
|
+
deepSkyBlue: '00BFFF', dimGray: '696969', dodgerBlue: '1E90FF',
|
|
25
|
+
firebrick: 'B22222', floralWhite: 'FFFAF0', forestGreen: '228B22',
|
|
26
|
+
fuchsia: 'FF00FF', gainsboro: 'DCDCDC', ghostWhite: 'F8F8FF',
|
|
27
|
+
gold: 'FFD700', goldenrod: 'DAA520', gray: '808080',
|
|
28
|
+
green: '008000', greenYellow: 'ADFF2F', honeydew: 'F0FFF0',
|
|
29
|
+
hotPink: 'FF69B4', indianRed: 'CD5C5C', indigo: '4B0082',
|
|
30
|
+
ivory: 'FFFFF0', khaki: 'F0E68C', lavender: 'E6E6FA',
|
|
31
|
+
lavenderBlush: 'FFF0F5', lawnGreen: '7CFC00', lemonChiffon: 'FFFACD',
|
|
32
|
+
ltBlue: 'ADD8E6', ltCoral: 'F08080', ltCyan: 'E0FFFF',
|
|
33
|
+
ltGoldenrodYellow: 'FAFA78', ltGray: 'D3D3D3', ltGreen: '90EE90',
|
|
34
|
+
ltPink: 'FFB6C1', ltSalmon: 'FFA07A', ltSeaGreen: '20B2AA',
|
|
35
|
+
ltSkyBlue: '87CEFA', ltSlateGray: '778899', ltSteelBlue: 'B0C4DE',
|
|
36
|
+
ltYellow: 'FFFFE0', lime: '00FF00', limeGreen: '32CD32',
|
|
37
|
+
linen: 'FAF0E6', magenta: 'FF00FF', maroon: '800000',
|
|
38
|
+
medAquamarine: '66CDAA', medBlue: '0000CD', medOrchid: 'BA55D3',
|
|
39
|
+
medPurple: '9370DB', medSeaGreen: '3CB371', medSlateBlue: '7B68EE',
|
|
40
|
+
medSpringGreen: '00FA9A', medTurquoise: '48D1CC', medVioletRed: 'C71585',
|
|
41
|
+
midnightBlue: '191970', mintCream: 'F5FFFA', mistyRose: 'FFE4E1',
|
|
42
|
+
moccasin: 'FFE4B5', navajoWhite: 'FFDEAD', navy: '000080',
|
|
43
|
+
oldLace: 'FDF5E6', olive: '808000', oliveDrab: '6B8E23',
|
|
44
|
+
orange: 'FFA500', orangeRed: 'FF4500', orchid: 'DA70D6',
|
|
45
|
+
paleGoldenrod: 'EEE8AA', paleGreen: '98FB98', paleTurquoise: 'AFEEEE',
|
|
46
|
+
paleVioletRed: 'DB7093', papayaWhip: 'FFEFD5', peachPuff: 'FFDAB9',
|
|
47
|
+
peru: 'CD853F', pink: 'FFC0CB', plum: 'DDA0DD',
|
|
48
|
+
powderBlue: 'B0E0E6', purple: '800080', red: 'FF0000',
|
|
49
|
+
rosyBrown: 'BC8F8F', royalBlue: '4169E1', saddleBrown: '8B4513',
|
|
50
|
+
salmon: 'FA8072', sandyBrown: 'F4A460', seaGreen: '2E8B57',
|
|
51
|
+
seaShell: 'FFF5EE', sienna: 'A0522D', silver: 'C0C0C0',
|
|
52
|
+
skyBlue: '87CEEB', slateBlue: '6A5ACD', slateGray: '708090',
|
|
53
|
+
snow: 'FFFAFA', springGreen: '00FF7F', steelBlue: '4682B4',
|
|
54
|
+
tan: 'D2B48C', teal: '008080', thistle: 'D8BFD8',
|
|
55
|
+
tomato: 'FF6347', turquoise: '40E0D0', violet: 'EE82EE',
|
|
56
|
+
wheat: 'F5DEB3', white: 'FFFFFF', whiteSmoke: 'F5F5F5',
|
|
57
|
+
yellow: 'FFFF00', yellowGreen: '9ACD32',
|
|
58
|
+
}));
|
|
59
|
+
/** `a:sysClr` names to Windows' default RRGGBB. */
|
|
60
|
+
export const SYSTEM = new Map(Object.entries({
|
|
61
|
+
scrollBar: 'C8C8C8', background: '000000', activeCaption: '99B4D1',
|
|
62
|
+
inactiveCaption: 'BFCDDB', menu: 'F0F0F0', window: 'FFFFFF',
|
|
63
|
+
windowFrame: '646464', menuText: '000000', windowText: '000000',
|
|
64
|
+
captionText: '000000', activeBorder: 'B4B4B4', inactiveBorder: 'F4F7FC',
|
|
65
|
+
appWorkspace: 'ABABAB', highlight: '3399FF', highlightText: 'FFFFFF',
|
|
66
|
+
btnFace: 'F0F0F0', btnShadow: '696969', grayText: '6D6D6D',
|
|
67
|
+
btnText: '000000', inactiveCaptionText: '000000', btnHighlight: 'E3E3E3',
|
|
68
|
+
'3dDkShadow': '000000', '3dLight': 'E3E3E3', infoText: '000000',
|
|
69
|
+
infoBk: 'FFFFE1', hotLight: '0066CC', gradientActiveCaption: 'B9D1EA',
|
|
70
|
+
gradientInactiveCaption: 'D7E4F2', menuHighlight: '3399FF', menuBar: 'F0F0F0',
|
|
71
|
+
}));
|
|
72
|
+
/** SpreadsheetML indexed colours 0 to 65. */
|
|
73
|
+
export const INDEXED = Object.freeze([
|
|
74
|
+
'000000', 'FFFFFF', 'FF0000', '00FF00', '0000FF', 'FFFF00', 'FF00FF', '00FFFF',
|
|
75
|
+
'000000', 'FFFFFF', 'FF0000', '00FF00', '0000FF', 'FFFF00', 'FF00FF', '00FFFF',
|
|
76
|
+
'800000', '008000', '000080', '808000', '800080', '008080', 'C0C0C0', '808080',
|
|
77
|
+
'9999FF', '993366', 'FFFFCC', 'CCFFFF', '660066', 'FF8080', '0066CC', 'CCCCFF',
|
|
78
|
+
'000080', 'FF00FF', 'FFFF00', '00FFFF', '800080', '800000', '008080', '0000FF',
|
|
79
|
+
'00CCFF', 'CCFFFF', 'CCFFCC', 'FFFF99', '99CCFF', 'FF99CC', 'CC99FF', 'FFCC99',
|
|
80
|
+
'3366FF', '33CCCC', '99CC00', 'FFCC00', 'FF9900', 'FF6600', '666699', '969696',
|
|
81
|
+
'003366', '339966', '003300', '333300', '993300', '993366', '333399', '333333',
|
|
82
|
+
'000000', 'FFFFFF',
|
|
83
|
+
]);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type * as dml from '@docx4j/generated-objects-ts/modules/org_docx4j_dml';
|
|
2
|
+
import { ResolvedColor } from './ResolvedColor.mjs';
|
|
3
|
+
import { StyleFill } from './StyleFill.mjs';
|
|
4
|
+
import type { ThemeColors } from './ThemeColors.mjs';
|
|
5
|
+
/** hexBinary as the objects model has it at run time (byte numbers), or as its declarations say (hex digits). */
|
|
6
|
+
export declare function bytesOf(v: unknown): number[] | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* DrawingML colours (ISO/IEC 29500-1 section 20.1.2.3) resolved as Office draws them. The six kinds: `srgbClr`,
|
|
9
|
+
* `scrgbClr` (linear percentages), `hslClr`, `sysClr` (the machine's colour by name, not `lastClr`), `prstClr` and
|
|
10
|
+
* `schemeClr` (through {@link ThemeColors}). Their transforms apply in document order, in the spaces Word and
|
|
11
|
+
* PowerPoint use, measured on 403 cases each (docx4j CR-034 section 11, P3):
|
|
12
|
+
* - `tint`, `shade`, `inv`, `red`/`green`/`blue` and their `Off`/`Mod`: linear RGB; `gamma` and `invGamma`: the
|
|
13
|
+
* sRGB transfer function each way;
|
|
14
|
+
* - `hue`, `sat`, `lum` and their `Off`/`Mod`, `comp`: HSL of the sRGB colour, the saturation not clamped (the
|
|
15
|
+
* channels are, afterwards); a colour whose last change is a luminance transform converted back as Foley and van
|
|
16
|
+
* Dam do and rounded half down, as Office rounds it (so `tx1` at `lumMod 50000 lumOff 50000` is 7F7F7F);
|
|
17
|
+
* - `gray`: Rec.709 luma of the sRGB channels;
|
|
18
|
+
* - `alpha`, `alphaOff`, `alphaMod`: the alpha.
|
|
19
|
+
*
|
|
20
|
+
* MS-OI29500 says `lumOff` and `satOff` are not supported by Office; Office 365 applies both as above in every case
|
|
21
|
+
* measured. Known differences from Office: a saturation set on a grey (Office gives a grey's hue about 40 degrees),
|
|
22
|
+
* and some hue, saturation and luminance cases one unit off.
|
|
23
|
+
*
|
|
24
|
+
* An object is known by its `TYPE_NAME` (which the objects package's unmarshal and factories give it), or, wrapped
|
|
25
|
+
* as `{ name, value }`, by its element name; a holder of a colour also by its `srgbClr`, `schemeClr`, ... member.
|
|
26
|
+
* docx4j's `null` is `undefined` here.
|
|
27
|
+
*/
|
|
28
|
+
export declare const DrawingMLColors: {
|
|
29
|
+
/**
|
|
30
|
+
* The colour a DrawingML colour element, or an element holding one, resolves to.
|
|
31
|
+
*
|
|
32
|
+
* @param colour one of the six kinds (`CTSchemeColor`, `CTSRgbColor`, ...), or a holder of one: `CTColor` (a
|
|
33
|
+
* scheme slot), `CTSolidColorFillProperties`, `CTStyleMatrixReference`, `CTFontReference`; `{ name, value }`
|
|
34
|
+
* is unwrapped
|
|
35
|
+
* @param theme the theme and colour map for `schemeClr`; may be undefined where there is none
|
|
36
|
+
* @returns undefined where there is no colour, or a `schemeClr` cannot be resolved
|
|
37
|
+
*/
|
|
38
|
+
resolve(colour: unknown, theme: ThemeColors | undefined): ResolvedColor | undefined;
|
|
39
|
+
/** A fill: `a:noFill`, `a:solidFill` (its colour resolved), or a gradient, pattern, picture or group fill reported by kind. */
|
|
40
|
+
fill(fillProperties: unknown, theme: ThemeColors | undefined): StyleFill;
|
|
41
|
+
/** A line's fill: none, solid, gradient or pattern. */
|
|
42
|
+
lineFill(ln: dml.CTLineProperties | undefined | null, theme: ThemeColors | undefined): StyleFill;
|
|
43
|
+
/**
|
|
44
|
+
* A shape style's `a:fillRef`: index 0 is no fill, 1 to 999 the theme's `a:fillStyleLst`, 1001 and up its
|
|
45
|
+
* `a:bgFillStyleLst`, with `phClr` the reference's own colour.
|
|
46
|
+
*/
|
|
47
|
+
fillReference(ref: dml.CTStyleMatrixReference | undefined | null, theme: ThemeColors | undefined): StyleFill;
|
|
48
|
+
/** A shape style's `a:lnRef`: index 0 is no line, else the theme's `a:lnStyleLst` entry's fill. */
|
|
49
|
+
lineReference(ref: dml.CTStyleMatrixReference | undefined | null, theme: ThemeColors | undefined): StyleFill;
|
|
50
|
+
/** A shape style's `a:fontRef`: its colour, the text's where the text states none. */
|
|
51
|
+
fontReference(ref: dml.CTFontReference | undefined | null, theme: ThemeColors | undefined): ResolvedColor | undefined;
|
|
52
|
+
};
|