reamkit 1.21.0 → 1.23.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/dist/esm/core/bytes.d.ts +22 -4
- package/dist/esm/core/bytes.js +73 -5
- package/dist/esm/core/converter/ream.d.ts +16 -0
- package/dist/esm/core/converter/ream.js +59 -9
- package/dist/esm/core/document-model/types.d.ts +78 -0
- package/dist/esm/core/drawingml/chart-geometry.js +11 -5
- package/dist/esm/core/drawingml/chart-parser.d.ts +2 -1
- package/dist/esm/core/drawingml/chart-parser.js +23 -1
- package/dist/esm/core/drawingml/colors.d.ts +30 -4
- package/dist/esm/core/drawingml/colors.js +45 -6
- package/dist/esm/core/drawingml/preset-geometry.js +236 -0
- package/dist/esm/core/drawingml/theme-parser.d.ts +38 -0
- package/dist/esm/core/drawingml/theme-parser.js +64 -1
- package/dist/esm/core/fonts/families.d.ts +10 -0
- package/dist/esm/core/fonts/families.js +44 -0
- package/dist/esm/core/fonts/index.d.ts +3 -2
- package/dist/esm/core/fonts/remote-fonts.d.ts +50 -0
- package/dist/esm/core/fonts/remote-fonts.js +114 -8
- package/dist/esm/core/fonts/scripts.d.ts +26 -0
- package/dist/esm/core/fonts/scripts.js +177 -0
- package/dist/esm/core/metafile/blit.d.ts +33 -0
- package/dist/esm/core/metafile/blit.js +67 -0
- package/dist/esm/core/metafile/dib.d.ts +61 -0
- package/dist/esm/core/metafile/dib.js +205 -0
- package/dist/esm/core/metafile/emf.js +139 -24
- package/dist/esm/core/metafile/picture.d.ts +12 -1
- package/dist/esm/core/metafile/symbol-fonts.d.ts +42 -0
- package/dist/esm/core/metafile/symbol-fonts.js +154 -0
- package/dist/esm/core/metafile/wmf.js +183 -10
- package/dist/esm/core/ole/escher-blip.d.ts +12 -0
- package/dist/esm/core/ole/escher-blip.js +88 -0
- package/dist/esm/{pdf-reader → core}/png-encode.js +1 -1
- package/dist/esm/core/vector.d.ts +5 -0
- package/dist/esm/excel/print-model.js +3 -1
- package/dist/esm/excel/sheet-shape-parser.js +1 -12
- package/dist/esm/excel/styles-parser.js +1 -1
- package/dist/esm/excel/xls/biff-reader.js +53 -18
- package/dist/esm/excel/xls/biff-styles.d.ts +5 -2
- package/dist/esm/excel/xls/biff-styles.js +9 -7
- package/dist/esm/excel/xls/escher.js +90 -24
- package/dist/esm/excel/xlsx-reader.d.ts +1 -1
- package/dist/esm/excel/xlsx-reader.js +3 -3
- package/dist/esm/layout/page-doc.d.ts +77 -0
- package/dist/esm/layout/page-doc.js +34 -18
- package/dist/esm/layout/styled-layout.d.ts +2 -2
- package/dist/esm/layout/styled-layout.js +467 -76
- package/dist/esm/pdf/shading.d.ts +19 -0
- package/dist/esm/pdf/shading.js +84 -11
- package/dist/esm/pdf/styled-page-emitter.js +647 -444
- package/dist/esm/pdf-reader/image-decode.js +1 -1
- package/dist/esm/pptx/embedded-fonts.d.ts +31 -0
- package/dist/esm/pptx/embedded-fonts.js +104 -0
- package/dist/esm/pptx/ole-preview.d.ts +10 -0
- package/dist/esm/pptx/ole-preview.js +52 -0
- package/dist/esm/pptx/placeholder-cascade.d.ts +136 -5
- package/dist/esm/pptx/placeholder-cascade.js +260 -27
- package/dist/esm/pptx/ppt/ppt-reader.js +120 -10
- package/dist/esm/pptx/ppt/ppt-text.d.ts +66 -1
- package/dist/esm/pptx/ppt/ppt-text.js +576 -137
- package/dist/esm/pptx/pptx-reader.d.ts +8 -0
- package/dist/esm/pptx/pptx-reader.js +271 -41
- package/dist/esm/pptx/preset-table-styles.d.ts +9 -0
- package/dist/esm/pptx/preset-table-styles.js +27 -0
- package/dist/esm/pptx/slide-parser.d.ts +78 -10
- package/dist/esm/pptx/slide-parser.js +396 -95
- package/dist/esm/pptx/sp-helpers.d.ts +2 -1
- package/dist/esm/pptx/sp-helpers.js +22 -6
- package/dist/esm/pptx/table-style.d.ts +64 -0
- package/dist/esm/pptx/table-style.js +203 -0
- package/dist/esm/svg/svg-writer.js +53 -5
- package/dist/esm/word/document-parser.d.ts +7 -1
- package/dist/esm/word/document-parser.js +6 -6
- package/dist/esm/word/docx-reader.js +8 -5
- package/dist/esm/word/docx-to-pdf.d.ts +8 -7
- package/dist/esm/word/docx-to-pdf.js +25 -7
- package/dist/esm/word/drawing-parser.d.ts +34 -0
- package/dist/esm/word/drawing-parser.js +173 -15
- package/dist/esm/word/numbering-parser.d.ts +2 -1
- package/dist/esm/word/numbering-parser.js +6 -6
- package/dist/esm/word/paragraph-properties.d.ts +2 -1
- package/dist/esm/word/paragraph-properties.js +2 -2
- package/dist/esm/word/run-properties.d.ts +5 -2
- package/dist/esm/word/run-properties.js +13 -8
- package/dist/esm/word/styles-parser.d.ts +2 -1
- package/dist/esm/word/styles-parser.js +12 -12
- package/dist/esm/word/table-parser.js +3 -3
- package/dist/esm/word/theme-fonts.d.ts +10 -0
- package/dist/esm/word/theme-fonts.js +28 -0
- package/package.json +1 -1
- /package/dist/esm/{pdf-reader → core}/png-encode.d.ts +0 -0
package/dist/esm/core/bytes.d.ts
CHANGED
|
@@ -5,13 +5,31 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export declare function toBase64(bytes: Uint8Array): string;
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Whether the ZIP in `bytes` holds a part named `partName` — the name exactly,
|
|
9
|
+
* or anything under it when `partName` names a directory (ends with `/`).
|
|
10
|
+
*
|
|
11
|
+
* This is what a reader sniff should ask. A substring probe cannot tell a
|
|
12
|
+
* package from one EMBEDDED in it: a deck with a chart carries the chart's
|
|
13
|
+
* workbook as `ppt/embeddings/*.xlsx` STORED, uncompressed, so that workbook's
|
|
14
|
+
* own `xl/workbook.xml` sits in the outer file's bytes verbatim — and the xlsx
|
|
15
|
+
* sniff, which runs before the pptx one, claimed thirteen corpus presentations
|
|
16
|
+
* and then failed on them. The ZIP's central directory lists what is actually
|
|
17
|
+
* in this package, and walking that entry table is cheaper than scanning every
|
|
18
|
+
* byte for a needle.
|
|
19
|
+
*
|
|
20
|
+
* Names are compared without case, as OPC compares part names (§9.1.1.1) and
|
|
21
|
+
* as the package reader behind the sniff resolves them.
|
|
22
|
+
*
|
|
23
|
+
* @param bytes The package bytes.
|
|
24
|
+
* @param partName The part name, or a `/`-terminated directory prefix.
|
|
25
|
+
* @returns Whether the package's directory names it.
|
|
10
26
|
*/
|
|
27
|
+
export declare function packageHasPart(bytes: Uint8Array, partName: string): boolean;
|
|
11
28
|
/**
|
|
12
29
|
* Scan raw package bytes for an OPC part name (e.g. `'xl/workbook.xml'`)
|
|
13
|
-
* without unzipping
|
|
14
|
-
*
|
|
30
|
+
* without unzipping. Prefer {@link packageHasPart}, which asks the archive
|
|
31
|
+
* what it holds instead of hoping the name appears nowhere else. Accepts both
|
|
32
|
+
* the spec's `/` separator and the `\` that Windows producers write.
|
|
15
33
|
*/
|
|
16
34
|
export declare function bytesIncludePartName(haystack: Uint8Array, partName: string): boolean;
|
|
17
35
|
/**
|
package/dist/esm/core/bytes.js
CHANGED
|
@@ -10,13 +10,81 @@ function toBase64(bytes) {
|
|
|
10
10
|
return btoa(bin);
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* Whether the ZIP in `bytes` holds a part named `partName` — the name exactly,
|
|
14
|
+
* or anything under it when `partName` names a directory (ends with `/`).
|
|
15
|
+
*
|
|
16
|
+
* This is what a reader sniff should ask. A substring probe cannot tell a
|
|
17
|
+
* package from one EMBEDDED in it: a deck with a chart carries the chart's
|
|
18
|
+
* workbook as `ppt/embeddings/*.xlsx` STORED, uncompressed, so that workbook's
|
|
19
|
+
* own `xl/workbook.xml` sits in the outer file's bytes verbatim — and the xlsx
|
|
20
|
+
* sniff, which runs before the pptx one, claimed thirteen corpus presentations
|
|
21
|
+
* and then failed on them. The ZIP's central directory lists what is actually
|
|
22
|
+
* in this package, and walking that entry table is cheaper than scanning every
|
|
23
|
+
* byte for a needle.
|
|
24
|
+
*
|
|
25
|
+
* Names are compared without case, as OPC compares part names (§9.1.1.1) and
|
|
26
|
+
* as the package reader behind the sniff resolves them.
|
|
27
|
+
*
|
|
28
|
+
* @param bytes The package bytes.
|
|
29
|
+
* @param partName The part name, or a `/`-terminated directory prefix.
|
|
30
|
+
* @returns Whether the package's directory names it.
|
|
15
31
|
*/
|
|
32
|
+
function packageHasPart(bytes, partName) {
|
|
33
|
+
const names = zipEntryNames(bytes);
|
|
34
|
+
if (names === void 0) return bytesIncludePartName(bytes, partName);
|
|
35
|
+
const wanted = partName.toLowerCase();
|
|
36
|
+
const isDir = wanted.endsWith("/");
|
|
37
|
+
return names.some((raw) => {
|
|
38
|
+
const name = raw.replace(/\\/g, "/").replace(/^\//u, "").toLowerCase();
|
|
39
|
+
return isDir ? name.startsWith(wanted) : name === wanted;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The names in a ZIP's central directory (APPNOTE §4.3.12), or `undefined`
|
|
44
|
+
* when it cannot be located or is malformed — including the ZIP64 spelling of
|
|
45
|
+
* an archive with more than 65 534 entries.
|
|
46
|
+
*/
|
|
47
|
+
function zipEntryNames(bytes) {
|
|
48
|
+
if (bytes.length < 22) return void 0;
|
|
49
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
50
|
+
const floor = Math.max(0, bytes.length - 22 - 65535);
|
|
51
|
+
let end = -1;
|
|
52
|
+
for (let i = bytes.length - 22; i >= floor; i--) if (view.getUint32(i, true) === 101010256) {
|
|
53
|
+
end = i;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
if (end < 0) return void 0;
|
|
57
|
+
let count = view.getUint16(end + 10, true);
|
|
58
|
+
let start = view.getUint32(end + 16, true);
|
|
59
|
+
if (count === 65535 || start === 4294967295) {
|
|
60
|
+
const locator = end - 20;
|
|
61
|
+
if (locator < 0 || view.getUint32(locator, true) !== 117853008) return void 0;
|
|
62
|
+
const z64 = Number(view.getBigUint64(locator + 8, true));
|
|
63
|
+
if (z64 + 56 > bytes.length || view.getUint32(z64, true) !== 101075792) return void 0;
|
|
64
|
+
count = Number(view.getBigUint64(z64 + 32, true));
|
|
65
|
+
start = Number(view.getBigUint64(z64 + 48, true));
|
|
66
|
+
}
|
|
67
|
+
const names = [];
|
|
68
|
+
let p = start;
|
|
69
|
+
for (let i = 0; i < count; i++) {
|
|
70
|
+
if (p + 46 > bytes.length || view.getUint32(p, true) !== 33639248) return void 0;
|
|
71
|
+
const nameLen = view.getUint16(p + 28, true);
|
|
72
|
+
if (p + 46 + nameLen > bytes.length) return void 0;
|
|
73
|
+
names.push(decodeUtf8(bytes.subarray(p + 46, p + 46 + nameLen)));
|
|
74
|
+
p += 46 + nameLen + view.getUint16(p + 30, true) + view.getUint16(p + 32, true);
|
|
75
|
+
}
|
|
76
|
+
return names;
|
|
77
|
+
}
|
|
78
|
+
var utf8 = new TextDecoder();
|
|
79
|
+
/** An entry name as text. Names are UTF-8 or CP437; both decode ASCII alike. */
|
|
80
|
+
function decodeUtf8(bytes) {
|
|
81
|
+
return utf8.decode(bytes);
|
|
82
|
+
}
|
|
16
83
|
/**
|
|
17
84
|
* Scan raw package bytes for an OPC part name (e.g. `'xl/workbook.xml'`)
|
|
18
|
-
* without unzipping
|
|
19
|
-
*
|
|
85
|
+
* without unzipping. Prefer {@link packageHasPart}, which asks the archive
|
|
86
|
+
* what it holds instead of hoping the name appears nowhere else. Accepts both
|
|
87
|
+
* the spec's `/` separator and the `\` that Windows producers write.
|
|
20
88
|
*/
|
|
21
89
|
function bytesIncludePartName(haystack, partName) {
|
|
22
90
|
if (bytesInclude(haystack, partName)) return true;
|
|
@@ -36,4 +104,4 @@ function bytesInclude(haystack, needle) {
|
|
|
36
104
|
return false;
|
|
37
105
|
}
|
|
38
106
|
//#endregion
|
|
39
|
-
export { bytesInclude,
|
|
107
|
+
export { bytesInclude, packageHasPart, toBase64 };
|
|
@@ -143,6 +143,22 @@ export declare class Ream {
|
|
|
143
143
|
* @returns The font bytes and, for docx, optional per-family registries.
|
|
144
144
|
*/
|
|
145
145
|
private resolveFonts;
|
|
146
|
+
/**
|
|
147
|
+
* Fetch one face per writing system the document holds text in — the curated
|
|
148
|
+
* families are Latin, and Han, Kana, Hangul, Arabic and the geometric symbols
|
|
149
|
+
* are a notdef box in every one of them.
|
|
150
|
+
*
|
|
151
|
+
* Only the regular weight is fetched: Noto Sans SC is ten megabytes, and a
|
|
152
|
+
* bold run in it is better stroked (see `SyntheticFace`) than downloaded four
|
|
153
|
+
* times over. A face that fails to arrive is a recorded loss, not a throw —
|
|
154
|
+
* the rest of the document still renders.
|
|
155
|
+
*
|
|
156
|
+
* @param into The registry map the run resolver looks in.
|
|
157
|
+
* @param flow The parsed document.
|
|
158
|
+
* @param options The convert options (for the injectable `fetch`).
|
|
159
|
+
* @param losses Where a face that could not be fetched records itself.
|
|
160
|
+
*/
|
|
161
|
+
private addScriptFonts;
|
|
146
162
|
/**
|
|
147
163
|
* In strict mode, throw {@link ConversionLossError} for the first recorded loss.
|
|
148
164
|
*
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { fetchFontSet } from "../fonts/remote-fonts.js";
|
|
1
|
+
import { fetchFontSet, fetchScriptFont, resolveFamilyKey } from "../fonts/remote-fonts.js";
|
|
2
|
+
import { scriptsInFlow } from "../fonts/scripts.js";
|
|
2
3
|
import { FontRegistry } from "../font/font-registry.js";
|
|
3
4
|
import { createFontMeasure } from "../font/measure.js";
|
|
4
5
|
import { ConversionLossError } from "../ir/loss.js";
|
|
@@ -12,8 +13,8 @@ import { writeDocx } from "../../word/docx-writer.js";
|
|
|
12
13
|
import { writeXlsx } from "../../excel/xlsx-writer.js";
|
|
13
14
|
import { writeHtml } from "../../html/html-writer.js";
|
|
14
15
|
import { writeSvg } from "../../svg/svg-writer.js";
|
|
15
|
-
import { resolveDocxAutoFonts } from "../../word/docx-to-pdf.js";
|
|
16
16
|
import { DEFAULT_READERS, resolveFontsViaChain, toFlowDoc } from "./facade.js";
|
|
17
|
+
import { familiesInFlow } from "../fonts/families.js";
|
|
17
18
|
import { decryptPackage, isEncryptedPackage } from "../crypto/offcrypto.js";
|
|
18
19
|
//#region src/core/converter/ream.ts
|
|
19
20
|
/**
|
|
@@ -150,7 +151,7 @@ var Ream = class Ream {
|
|
|
150
151
|
losses
|
|
151
152
|
};
|
|
152
153
|
}
|
|
153
|
-
const { fonts, registriesByFamily } = await this.resolveFonts(options, losses);
|
|
154
|
+
const { fonts, registriesByFamily } = await this.resolveFonts(options, losses, flow);
|
|
154
155
|
const registry = FontRegistry.fromBytes(fonts);
|
|
155
156
|
const paginated = this.sheet ? projectSheetDoc(this.sheet, {
|
|
156
157
|
...options.now ? { now: options.now } : {},
|
|
@@ -209,7 +210,7 @@ var Ream = class Ream {
|
|
|
209
210
|
* @param losses The mutable loss list a substitution is appended to.
|
|
210
211
|
* @returns The font bytes and, for docx, optional per-family registries.
|
|
211
212
|
*/
|
|
212
|
-
async resolveFonts(options, losses) {
|
|
213
|
+
async resolveFonts(options, losses, flow) {
|
|
213
214
|
const explicit = options.fonts ?? (options.fontBytes ? { regular: options.fontBytes } : void 0);
|
|
214
215
|
if (explicit) return { fonts: explicit };
|
|
215
216
|
if (options.fontProviders && options.fontProviders.length > 0) {
|
|
@@ -217,11 +218,60 @@ var Ream = class Ream {
|
|
|
217
218
|
if (loss) losses.push(loss);
|
|
218
219
|
if (fonts) return { fonts };
|
|
219
220
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
221
|
+
const fetchOpt = options.fontFetch ? { fetch: options.fontFetch } : {};
|
|
222
|
+
const keys = options.fontFamily ? new Set([resolveFamilyKey(options.fontFamily)]) : familiesInFlow(flow);
|
|
223
|
+
if (keys.size <= 1 && scriptsInFlow(flow).scripts.size === 0) {
|
|
224
|
+
const family = keys.values().next().value;
|
|
225
|
+
return { fonts: await fetchFontSet({
|
|
226
|
+
...family ? { family } : {},
|
|
227
|
+
...fetchOpt
|
|
228
|
+
}) };
|
|
229
|
+
}
|
|
230
|
+
const registriesByFamily = /* @__PURE__ */ new Map();
|
|
231
|
+
let baseBytes;
|
|
232
|
+
for (const key of keys) {
|
|
233
|
+
const bytes = await fetchFontSet({
|
|
234
|
+
family: key,
|
|
235
|
+
...fetchOpt
|
|
236
|
+
});
|
|
237
|
+
registriesByFamily.set(key, FontRegistry.fromBytes(bytes));
|
|
238
|
+
if (key === "arimo" || !baseBytes) baseBytes = bytes;
|
|
239
|
+
}
|
|
240
|
+
await this.addScriptFonts(registriesByFamily, flow, options, losses);
|
|
241
|
+
return {
|
|
242
|
+
fonts: baseBytes,
|
|
243
|
+
registriesByFamily
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Fetch one face per writing system the document holds text in — the curated
|
|
248
|
+
* families are Latin, and Han, Kana, Hangul, Arabic and the geometric symbols
|
|
249
|
+
* are a notdef box in every one of them.
|
|
250
|
+
*
|
|
251
|
+
* Only the regular weight is fetched: Noto Sans SC is ten megabytes, and a
|
|
252
|
+
* bold run in it is better stroked (see `SyntheticFace`) than downloaded four
|
|
253
|
+
* times over. A face that fails to arrive is a recorded loss, not a throw —
|
|
254
|
+
* the rest of the document still renders.
|
|
255
|
+
*
|
|
256
|
+
* @param into The registry map the run resolver looks in.
|
|
257
|
+
* @param flow The parsed document.
|
|
258
|
+
* @param options The convert options (for the injectable `fetch`).
|
|
259
|
+
* @param losses Where a face that could not be fetched records itself.
|
|
260
|
+
*/
|
|
261
|
+
async addScriptFonts(into, flow, options, losses) {
|
|
262
|
+
const { scripts } = scriptsInFlow(flow);
|
|
263
|
+
for (const script of scripts) {
|
|
264
|
+
const bytes = await fetchScriptFont(script, options.fontFetch);
|
|
265
|
+
if (!bytes) {
|
|
266
|
+
losses.push({
|
|
267
|
+
feature: "font",
|
|
268
|
+
detail: `no face could be fetched for the ${script} script; its text draws as boxes`,
|
|
269
|
+
severity: "substituted"
|
|
270
|
+
});
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
into.set(script, FontRegistry.fromBytes(bytes));
|
|
274
|
+
}
|
|
225
275
|
}
|
|
226
276
|
/**
|
|
227
277
|
* In strict mode, throw {@link ConversionLossError} for the first recorded loss.
|
|
@@ -257,6 +257,17 @@ export interface InlineImage {
|
|
|
257
257
|
readonly gain: number;
|
|
258
258
|
readonly black: number;
|
|
259
259
|
};
|
|
260
|
+
/**
|
|
261
|
+
* §20.1.8.16 `a:clrChange` — one colour of the picture replaced by another,
|
|
262
|
+
* or knocked out entirely when the destination states `a:alpha` at zero. A
|
|
263
|
+
* logo on a white card goes onto a dark slide that way (corpus: tdf113163,
|
|
264
|
+
* whose whole slide is a metafile with its white ground declared away).
|
|
265
|
+
*/
|
|
266
|
+
readonly colorChange?: {
|
|
267
|
+
readonly fromHex: string;
|
|
268
|
+
readonly toHex: string;
|
|
269
|
+
readonly transparent: boolean;
|
|
270
|
+
};
|
|
260
271
|
readonly width: Pt;
|
|
261
272
|
readonly height: Pt;
|
|
262
273
|
/** §20.1.8.55 `a:srcRect` — the part of the source the frame shows. */
|
|
@@ -915,6 +926,22 @@ export interface ImageBlock {
|
|
|
915
926
|
readonly gain: number;
|
|
916
927
|
readonly black: number;
|
|
917
928
|
};
|
|
929
|
+
/**
|
|
930
|
+
* §20.1.8.4 `a:alphaModFix` — how opaque the picture is DRAWN, `0..1`; absent
|
|
931
|
+
* is opaque. A layout that lays a photograph behind its text sets it low
|
|
932
|
+
* (ArtisticEffectSample's cover shows one at 52%), and drawn full-strength
|
|
933
|
+
* the words on it are unreadable.
|
|
934
|
+
*/
|
|
935
|
+
readonly alpha?: number;
|
|
936
|
+
/**
|
|
937
|
+
* §20.1.8.16 `a:clrChange` — one colour of the picture replaced by another,
|
|
938
|
+
* or knocked out entirely when the destination states `a:alpha` at zero.
|
|
939
|
+
*/
|
|
940
|
+
readonly colorChange?: {
|
|
941
|
+
readonly fromHex: string;
|
|
942
|
+
readonly toHex: string;
|
|
943
|
+
readonly transparent: boolean;
|
|
944
|
+
};
|
|
918
945
|
readonly width: Pt;
|
|
919
946
|
readonly height: Pt;
|
|
920
947
|
/** §20.1.8.55 `a:srcRect` — the part of the source the frame shows. */
|
|
@@ -998,6 +1025,24 @@ export interface ShapeFill {
|
|
|
998
1025
|
* text box: stretched, such a fill is a blur where it should be a pattern.
|
|
999
1026
|
*/
|
|
1000
1027
|
readonly tiled?: boolean;
|
|
1028
|
+
/**
|
|
1029
|
+
* The size ONE copy of a tiled fill occupies, when the shape states it —
|
|
1030
|
+
* MS-ODRAW §2.3.7.11/.12 `fillWidth` / `fillHeight`. Absent, a tile is the
|
|
1031
|
+
* picture at its own resolution, which is the default both formats give.
|
|
1032
|
+
*/
|
|
1033
|
+
readonly tileSizePt?: {
|
|
1034
|
+
readonly widthPt: number;
|
|
1035
|
+
readonly heightPt: number;
|
|
1036
|
+
};
|
|
1037
|
+
/**
|
|
1038
|
+
* §20.1.8.58 `a:tile @sx @sy` — how far the picture is scaled BEFORE it is
|
|
1039
|
+
* repeated, as fractions of its own size (1 = 100 %). A texture halved tiles
|
|
1040
|
+
* four times as often, and read as a plain repeat it tiles once.
|
|
1041
|
+
*/
|
|
1042
|
+
readonly tileScale?: {
|
|
1043
|
+
readonly sx: number;
|
|
1044
|
+
readonly sy: number;
|
|
1045
|
+
};
|
|
1001
1046
|
/**
|
|
1002
1047
|
* §20.1.8.14 `a:blipFill` — the picture painted across the shape's box. A
|
|
1003
1048
|
* DrawingML picture IS a shape with one of these, which is how a `pic:pic`
|
|
@@ -1009,6 +1054,30 @@ export interface ShapeFill {
|
|
|
1009
1054
|
* of the picture the box shows, as the fractions cut from each side.
|
|
1010
1055
|
*/
|
|
1011
1056
|
readonly imageCrop?: ImageCrop;
|
|
1057
|
+
/**
|
|
1058
|
+
* §20.1.8.30 `a:stretch/a:fillRect` with POSITIVE insets — the part of the
|
|
1059
|
+
* shape's box the picture is stretched into, as fractions of that box. A
|
|
1060
|
+
* slide backed by a picture inset 55 % from the left shows it in the corner,
|
|
1061
|
+
* not across the slide (corpus: tdf153466.pptx). Negative insets are the
|
|
1062
|
+
* other case entirely — the picture zooming past the box — and read as a
|
|
1063
|
+
* crop of the source.
|
|
1064
|
+
*/
|
|
1065
|
+
/**
|
|
1066
|
+
* §20.1.8.23 `a:duotone` — the picture recoloured into two tones: its dark
|
|
1067
|
+
* end becomes the first colour, its light end the second. An Office theme
|
|
1068
|
+
* that ships a photograph tints it this way, so a deck whose background is a
|
|
1069
|
+
* brown ridged texture is stored as a grey one (corpus: themes.pptx).
|
|
1070
|
+
*/
|
|
1071
|
+
readonly duotone?: {
|
|
1072
|
+
readonly shadowHex: string;
|
|
1073
|
+
readonly highlightHex: string;
|
|
1074
|
+
};
|
|
1075
|
+
readonly imageFillRect?: {
|
|
1076
|
+
readonly left: number;
|
|
1077
|
+
readonly top: number;
|
|
1078
|
+
readonly right: number;
|
|
1079
|
+
readonly bottom: number;
|
|
1080
|
+
};
|
|
1012
1081
|
/**
|
|
1013
1082
|
* §20.1.2.3.1 `a:alpha` / §14.1.2.5 `@opacity` — how opaque the fill is,
|
|
1014
1083
|
* `0..1`. Absent is opaque. The colour above is the fill's own, NOT composited
|
|
@@ -1315,6 +1384,15 @@ export interface Chart {
|
|
|
1315
1384
|
* creates, and both references draw them.
|
|
1316
1385
|
*/
|
|
1317
1386
|
readonly frameFillHex?: string;
|
|
1387
|
+
/**
|
|
1388
|
+
* §20.1.8.14 `a:blipFill` — the PICTURE the frame is filled with, when it is
|
|
1389
|
+
* filled with one rather than a colour. chart-texture-bg.pptx papers its
|
|
1390
|
+
* whole chart with a woven cloth, and a chart on white is a different chart.
|
|
1391
|
+
*/
|
|
1392
|
+
readonly frameFillImage?: {
|
|
1393
|
+
readonly resource: ResourceId;
|
|
1394
|
+
readonly tiled?: boolean;
|
|
1395
|
+
};
|
|
1318
1396
|
readonly frameLineHex?: string;
|
|
1319
1397
|
/** The frame rule's width and dash, when it states them. */
|
|
1320
1398
|
readonly frameLineWidthPt?: number;
|
|
@@ -46,7 +46,7 @@ function niceScale(dataMin, dataMax, maxTicks = 6) {
|
|
|
46
46
|
const lo = Math.min(dataMin, dataMax);
|
|
47
47
|
let hi = Math.max(dataMin, dataMax);
|
|
48
48
|
if (lo === hi) hi = lo + 1;
|
|
49
|
-
const step = niceNum(
|
|
49
|
+
const step = niceNum((hi - lo) / Math.max(1, maxTicks - 1), true);
|
|
50
50
|
const headroom = hi > 0 ? hi * 1.05 : hi;
|
|
51
51
|
return {
|
|
52
52
|
min: Math.floor(lo / step) * step,
|
|
@@ -712,11 +712,17 @@ function autoRange(vals) {
|
|
|
712
712
|
return [lo > 0 && lo < 5 / 6 * hi ? 0 : lo, hi];
|
|
713
713
|
}
|
|
714
714
|
/**
|
|
715
|
-
*
|
|
716
|
-
*
|
|
717
|
-
*
|
|
715
|
+
* How many ticks an axis `extentPt` long carries (mirrors {@link axisScale}).
|
|
716
|
+
*
|
|
717
|
+
* A tall axis takes more of them — a fixed six drew 0/100/200/300 down a plot
|
|
718
|
+
* where both references fit 0/50/…/300 — but the appetite is milder than it
|
|
719
|
+
* looks: asked for one every 32pt, a 427pt chart wanted ten, and Excel labels
|
|
720
|
+
* that chart's 0…5 data 0/1/…/6 where we drew half-steps (chart-texture-bg
|
|
721
|
+
* .pptx). One per ~48pt and never more than eight satisfies both, now that
|
|
722
|
+
* {@link niceScale} measures its step against the range the data spans rather
|
|
723
|
+
* than against Heckbert's rounded-up one.
|
|
718
724
|
*/
|
|
719
|
-
var tickBudget = (extentPt) => Math.min(
|
|
725
|
+
var tickBudget = (extentPt) => Math.min(8, Math.max(4, Math.round(extentPt / 48)));
|
|
720
726
|
/** Side (points) of the square stamped for a series that names no symbol. */
|
|
721
727
|
var DEFAULT_MARKER_PT = 4;
|
|
722
728
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Chart } from '../document-model/index.js';
|
|
2
|
+
import { ResourceId } from '../ir/index.js';
|
|
2
3
|
import { OpcPackage } from '../opc/index.js';
|
|
3
4
|
import { ColorResolver } from './colors.js';
|
|
4
5
|
/**
|
|
@@ -14,7 +15,7 @@ import { ColorResolver } from './colors.js';
|
|
|
14
15
|
* @param resolveColor Maps a DrawingML colour reference to a 6-hex string.
|
|
15
16
|
* @returns The parsed chart, or `null` when there is no `c:chart` / `c:plotArea`.
|
|
16
17
|
*/
|
|
17
|
-
export declare function parseChart(chartXml: Uint8Array, resolveColor: ColorResolver): Chart | null;
|
|
18
|
+
export declare function parseChart(chartXml: Uint8Array, resolveColor: ColorResolver, resolveImage?: (relId: string) => ResourceId | undefined): Chart | null;
|
|
18
19
|
/**
|
|
19
20
|
* MS-ODRAWXML chartColorStyle (charts/colorsN.xml): the top-level colour list is
|
|
20
21
|
* the series cycle (`meth="cycle"` — the common case; variations are luminance
|
|
@@ -37,7 +37,7 @@ var TYPE_OF_TAG = {
|
|
|
37
37
|
* @param resolveColor Maps a DrawingML colour reference to a 6-hex string.
|
|
38
38
|
* @returns The parsed chart, or `null` when there is no `c:chart` / `c:plotArea`.
|
|
39
39
|
*/
|
|
40
|
-
function parseChart(chartXml, resolveColor) {
|
|
40
|
+
function parseChart(chartXml, resolveColor, resolveImage) {
|
|
41
41
|
const tree = parser.parse(decoder.decode(chartXml));
|
|
42
42
|
const chart = poFindByPath(tree, ["c:chartSpace", "c:chart"]);
|
|
43
43
|
if (!chart) return null;
|
|
@@ -105,6 +105,7 @@ function parseChart(chartXml, resolveColor) {
|
|
|
105
105
|
const frameLine = spaceSpPr ? poChildren(spaceSpPr).find((c) => poIs(c, "a:ln")) : void 0;
|
|
106
106
|
const frameStyle = lineStyleOf(chartSpace, resolveColor);
|
|
107
107
|
const frameFillHex = spaceSpPr ? frameFillOf(spaceSpPr, resolveColor) : "FFFFFF";
|
|
108
|
+
const frameFillImage = spaceSpPr ? blipFillOf(spaceSpPr, resolveImage) : void 0;
|
|
108
109
|
const plotSpPr = poChildren(plotArea).find((c) => poIs(c, "c:spPr"));
|
|
109
110
|
const plotFillHex = plotSpPr ? frameFillOf(plotSpPr, resolveColor) : void 0;
|
|
110
111
|
const plotLine = lineStyleOf(plotArea, resolveColor);
|
|
@@ -142,6 +143,7 @@ function parseChart(chartXml, resolveColor) {
|
|
|
142
143
|
...valAxisMin !== void 0 ? { valAxisMin } : {},
|
|
143
144
|
...valAxisMax !== void 0 ? { valAxisMax } : {},
|
|
144
145
|
...frameFillHex ? { frameFillHex } : {},
|
|
146
|
+
...frameFillImage ? { frameFillImage } : {},
|
|
145
147
|
...frameLineHex ? { frameLineHex } : {},
|
|
146
148
|
...frameStyle?.widthPt !== void 0 ? { frameLineWidthPt: frameStyle.widthPt } : {},
|
|
147
149
|
...frameStyle?.dash ? { frameLineDash: frameStyle.dash } : {},
|
|
@@ -248,6 +250,26 @@ function dataPointColors(ser, resolveColor) {
|
|
|
248
250
|
return out;
|
|
249
251
|
}
|
|
250
252
|
/**
|
|
253
|
+
* §20.1.8.14 `a:blipFill` — the picture a chart element is filled with, and
|
|
254
|
+
* whether it TILES at its own size rather than stretching over the box.
|
|
255
|
+
*
|
|
256
|
+
* @param spPr The element's `c:spPr`.
|
|
257
|
+
* @param resolveImage The chart part's own blip resolver, when the caller has one.
|
|
258
|
+
* @returns The stored picture, or `undefined` when the fill is not one.
|
|
259
|
+
*/
|
|
260
|
+
function blipFillOf(spPr, resolveImage) {
|
|
261
|
+
const blipFill = poChildren(spPr).find((c) => poIs(c, "a:blipFill"));
|
|
262
|
+
const blip = blipFill ? poChildren(blipFill).find((c) => poIs(c, "a:blip")) : void 0;
|
|
263
|
+
const relId = blip ? poAttr(blip, "embed") : void 0;
|
|
264
|
+
const resource = relId !== void 0 ? resolveImage?.(relId) : void 0;
|
|
265
|
+
if (resource === void 0 || !blipFill) return void 0;
|
|
266
|
+
const tiled = poChildren(blipFill).some((c) => poIs(c, "a:tile"));
|
|
267
|
+
return {
|
|
268
|
+
resource,
|
|
269
|
+
...tiled ? { tiled } : {}
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
251
273
|
* The BACKGROUND fill of a frame (the chart space, the plot rectangle): its own
|
|
252
274
|
* `a:solidFill` and nothing else. Unlike a series, a frame that states
|
|
253
275
|
* `<a:noFill/>` is not filled in the colour of its own rule —
|
|
@@ -3,10 +3,12 @@ import { PoNode } from '../po-helpers.js';
|
|
|
3
3
|
* A colour transform child (§20.1.2.3): `lumMod`/`lumOff` modulate luminance,
|
|
4
4
|
* `shade` darkens toward black, `tint` lightens toward white. `val` is normalised
|
|
5
5
|
* to 0..1 (the XML stores thousandths of a percent). `alpha` composites over white
|
|
6
|
-
* (solid fills emit no transparency).
|
|
6
|
+
* (solid fills emit no transparency). `gamma`/`invGamma` carry no value: they
|
|
7
|
+
* shift the colour into the other light and back, which changes what the
|
|
8
|
+
* transforms between them mean.
|
|
7
9
|
*/
|
|
8
10
|
export interface ColorMod {
|
|
9
|
-
readonly kind: 'lumMod' | 'lumOff' | 'shade' | 'tint' | 'alpha' | 'satMod' | 'hueOff' | 'satOff';
|
|
11
|
+
readonly kind: 'lumMod' | 'lumOff' | 'shade' | 'tint' | 'alpha' | 'satMod' | 'hueMod' | 'hueOff' | 'satOff' | 'gamma' | 'invGamma';
|
|
10
12
|
readonly val: number;
|
|
11
13
|
}
|
|
12
14
|
/**
|
|
@@ -38,20 +40,44 @@ export declare function applyColorMods(hex: string, mods: ReadonlyArray<ColorMod
|
|
|
38
40
|
* scheme slots when a document carries no custom theme part.
|
|
39
41
|
*/
|
|
40
42
|
export declare const DEFAULT_THEME_PALETTE: ReadonlyMap<string, string>;
|
|
43
|
+
/**
|
|
44
|
+
* Which theme slot each `schemeClr` name stands for. Only the text/background
|
|
45
|
+
* aliases are ever remapped; anything absent resolves under its own name.
|
|
46
|
+
*/
|
|
47
|
+
export type SchemeAliases = Readonly<Record<string, string>>;
|
|
48
|
+
export declare const DEFAULT_SCHEME_ALIAS: SchemeAliases;
|
|
41
49
|
/**
|
|
42
50
|
* Resolve a `schemeClr` text/background alias (`tx1`/`bg1`/`tx2`/`bg2`,
|
|
43
51
|
* §20.1.2.3.29) to its underlying `dk`/`lt` slot name; other names pass through.
|
|
52
|
+
*
|
|
53
|
+
* @param name The `schemeClr` value.
|
|
54
|
+
* @param alias The mapping to read it under — a presentation states its own in
|
|
55
|
+
* the master's `p:clrMap` (§19.3.1.6), where `bg1` may well mean `dk2`.
|
|
56
|
+
* @returns The theme slot to look up.
|
|
44
57
|
*/
|
|
45
|
-
export declare function resolveSchemeName(name: string): string;
|
|
58
|
+
export declare function resolveSchemeName(name: string, alias?: SchemeAliases): string;
|
|
46
59
|
/**
|
|
47
60
|
* Build a {@link ColorResolver} over a scheme-name → hex `palette`. sRGB
|
|
48
61
|
* references pass through verbatim (upper-cased); scheme references are aliased
|
|
49
62
|
* (via {@link resolveSchemeName}) then looked up; colour transforms are applied.
|
|
50
63
|
*
|
|
51
64
|
* @param palette The scheme-name → RRGGBB map (e.g. {@link DEFAULT_THEME_PALETTE}).
|
|
65
|
+
* @param alias How the bg/tx aliases map onto the theme's slots; the default
|
|
66
|
+
* is the fixed DrawingML one, which is what a document without a colour map of
|
|
67
|
+
* its own (docx, xlsx) uses.
|
|
52
68
|
* @returns A resolver that maps a {@link RawColor} to a hex string or `undefined`.
|
|
53
69
|
*/
|
|
54
|
-
export declare function makeColorResolver(palette: ReadonlyMap<string, string
|
|
70
|
+
export declare function makeColorResolver(palette: ReadonlyMap<string, string>, alias?: SchemeAliases): ColorResolver;
|
|
71
|
+
/**
|
|
72
|
+
* §20.1.4.2.10 `phClr` — inside a theme's style list the colours are written as
|
|
73
|
+
* "the placeholder", and the reference that reaches the style says which colour
|
|
74
|
+
* that is. Everything else resolves as it always did.
|
|
75
|
+
*
|
|
76
|
+
* @param base The document's own resolver.
|
|
77
|
+
* @param phHex The colour the reference carries (`a:fillRef`, `p:bgRef`, …).
|
|
78
|
+
* @returns A resolver that answers `phClr` with that colour, transforms and all.
|
|
79
|
+
*/
|
|
80
|
+
export declare function placeholderColors(base: ColorResolver, phHex: string): ColorResolver;
|
|
55
81
|
/** A {@link ColorResolver} backed by the {@link DEFAULT_THEME_PALETTE}. */
|
|
56
82
|
export declare const defaultColorResolver: ColorResolver;
|
|
57
83
|
/**
|
|
@@ -99,10 +99,20 @@ function applyColorMods(hex, mods) {
|
|
|
99
99
|
r = toSrgb(toLinear(r) * m.val + (1 - m.val));
|
|
100
100
|
g = toSrgb(toLinear(g) * m.val + (1 - m.val));
|
|
101
101
|
b = toSrgb(toLinear(b) * m.val + (1 - m.val));
|
|
102
|
+
} else if (m.kind === "gamma" || m.kind === "invGamma") {
|
|
103
|
+
const shift = m.kind === "gamma" ? toSrgb : toLinear;
|
|
104
|
+
[r, g, b] = [
|
|
105
|
+
shift(r),
|
|
106
|
+
shift(g),
|
|
107
|
+
shift(b)
|
|
108
|
+
];
|
|
102
109
|
} else if (m.kind === "lumMod" || m.kind === "lumOff") {
|
|
103
110
|
const [h, s, l] = rgbToHsl(r, g, b);
|
|
104
111
|
const l2 = m.kind === "lumMod" ? l * m.val : clamp01(l + m.val);
|
|
105
112
|
[r, g, b] = hslToRgb(h, s, l2);
|
|
113
|
+
} else if (m.kind === "hueMod") {
|
|
114
|
+
const [h, sat, l] = rgbToHsl(r, g, b);
|
|
115
|
+
[r, g, b] = hslToRgb((h * m.val % 360 + 360) % 360, sat, l);
|
|
106
116
|
} else if (m.kind === "hueOff") {
|
|
107
117
|
const [h, sat, l] = rgbToHsl(r, g, b);
|
|
108
118
|
[r, g, b] = hslToRgb(((h + m.val) % 360 + 360) % 360, sat, l);
|
|
@@ -138,7 +148,7 @@ var DEFAULT_THEME_PALETTE = new Map([
|
|
|
138
148
|
["hlink", "0563C1"],
|
|
139
149
|
["folHlink", "954F72"]
|
|
140
150
|
]);
|
|
141
|
-
var
|
|
151
|
+
var DEFAULT_SCHEME_ALIAS = {
|
|
142
152
|
tx1: "dk1",
|
|
143
153
|
bg1: "lt1",
|
|
144
154
|
tx2: "dk2",
|
|
@@ -147,9 +157,14 @@ var SCHEME_ALIAS = {
|
|
|
147
157
|
/**
|
|
148
158
|
* Resolve a `schemeClr` text/background alias (`tx1`/`bg1`/`tx2`/`bg2`,
|
|
149
159
|
* §20.1.2.3.29) to its underlying `dk`/`lt` slot name; other names pass through.
|
|
160
|
+
*
|
|
161
|
+
* @param name The `schemeClr` value.
|
|
162
|
+
* @param alias The mapping to read it under — a presentation states its own in
|
|
163
|
+
* the master's `p:clrMap` (§19.3.1.6), where `bg1` may well mean `dk2`.
|
|
164
|
+
* @returns The theme slot to look up.
|
|
150
165
|
*/
|
|
151
|
-
function resolveSchemeName(name) {
|
|
152
|
-
return
|
|
166
|
+
function resolveSchemeName(name, alias = DEFAULT_SCHEME_ALIAS) {
|
|
167
|
+
return alias[name] ?? name;
|
|
153
168
|
}
|
|
154
169
|
/**
|
|
155
170
|
* Build a {@link ColorResolver} over a scheme-name → hex `palette`. sRGB
|
|
@@ -157,15 +172,30 @@ function resolveSchemeName(name) {
|
|
|
157
172
|
* (via {@link resolveSchemeName}) then looked up; colour transforms are applied.
|
|
158
173
|
*
|
|
159
174
|
* @param palette The scheme-name → RRGGBB map (e.g. {@link DEFAULT_THEME_PALETTE}).
|
|
175
|
+
* @param alias How the bg/tx aliases map onto the theme's slots; the default
|
|
176
|
+
* is the fixed DrawingML one, which is what a document without a colour map of
|
|
177
|
+
* its own (docx, xlsx) uses.
|
|
160
178
|
* @returns A resolver that maps a {@link RawColor} to a hex string or `undefined`.
|
|
161
179
|
*/
|
|
162
|
-
function makeColorResolver(palette) {
|
|
180
|
+
function makeColorResolver(palette, alias = DEFAULT_SCHEME_ALIAS) {
|
|
163
181
|
return (raw) => {
|
|
164
|
-
const base = "srgb" in raw ? raw.srgb.toUpperCase() : palette.get(resolveSchemeName(raw.scheme));
|
|
182
|
+
const base = "srgb" in raw ? raw.srgb.toUpperCase() : palette.get(resolveSchemeName(raw.scheme, alias));
|
|
165
183
|
if (base === void 0) return void 0;
|
|
166
184
|
return raw.mods && raw.mods.length > 0 ? applyColorMods(base, raw.mods) : base;
|
|
167
185
|
};
|
|
168
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* §20.1.4.2.10 `phClr` — inside a theme's style list the colours are written as
|
|
189
|
+
* "the placeholder", and the reference that reaches the style says which colour
|
|
190
|
+
* that is. Everything else resolves as it always did.
|
|
191
|
+
*
|
|
192
|
+
* @param base The document's own resolver.
|
|
193
|
+
* @param phHex The colour the reference carries (`a:fillRef`, `p:bgRef`, …).
|
|
194
|
+
* @returns A resolver that answers `phClr` with that colour, transforms and all.
|
|
195
|
+
*/
|
|
196
|
+
function placeholderColors(base, phHex) {
|
|
197
|
+
return (raw) => "scheme" in raw && raw.scheme === "phClr" ? applyColorMods(phHex, raw.mods ?? []) : base(raw);
|
|
198
|
+
}
|
|
169
199
|
/** A {@link ColorResolver} backed by the {@link DEFAULT_THEME_PALETTE}. */
|
|
170
200
|
var defaultColorResolver = makeColorResolver(DEFAULT_THEME_PALETTE);
|
|
171
201
|
var PRESET_COLORS = new Map([
|
|
@@ -198,6 +228,7 @@ function readColorMods(colorNode) {
|
|
|
198
228
|
"tint",
|
|
199
229
|
"alpha",
|
|
200
230
|
"satMod",
|
|
231
|
+
"hueMod",
|
|
201
232
|
"satOff"
|
|
202
233
|
]) if (poIs(c, `a:${kind}`)) {
|
|
203
234
|
const v = poIntAttr(c, "val");
|
|
@@ -206,6 +237,14 @@ function readColorMods(colorNode) {
|
|
|
206
237
|
val: v / 1e5
|
|
207
238
|
});
|
|
208
239
|
}
|
|
240
|
+
if (poIs(c, "a:gamma")) mods.push({
|
|
241
|
+
kind: "gamma",
|
|
242
|
+
val: 0
|
|
243
|
+
});
|
|
244
|
+
if (poIs(c, "a:invGamma")) mods.push({
|
|
245
|
+
kind: "invGamma",
|
|
246
|
+
val: 0
|
|
247
|
+
});
|
|
209
248
|
if (poIs(c, "a:hueOff")) {
|
|
210
249
|
const v = poIntAttr(c, "val");
|
|
211
250
|
if (v !== void 0) mods.push({
|
|
@@ -266,4 +305,4 @@ function resolveColorNode(c, resolveColor) {
|
|
|
266
305
|
} : raw);
|
|
267
306
|
}
|
|
268
307
|
//#endregion
|
|
269
|
-
export { DEFAULT_THEME_PALETTE, applyColorMods, defaultColorResolver, makeColorResolver, readColorMods, resolveColorNode };
|
|
308
|
+
export { DEFAULT_SCHEME_ALIAS, DEFAULT_THEME_PALETTE, applyColorMods, defaultColorResolver, makeColorResolver, placeholderColors, readColorMods, resolveColorNode };
|