doc-codec 1.0.2 → 1.1.1

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.
Files changed (112) hide show
  1. package/README.md +192 -50
  2. package/dist/color.cjs +166 -0
  3. package/dist/color.d.cts +20 -0
  4. package/dist/color.d.ts +20 -0
  5. package/dist/color.js +160 -0
  6. package/dist/detect.cjs +3 -0
  7. package/dist/detect.d.cts +3 -1
  8. package/dist/detect.d.ts +3 -1
  9. package/dist/detect.js +3 -1
  10. package/dist/fib/fib.cjs +9 -1
  11. package/dist/fib/fib.d.cts +1 -28
  12. package/dist/fib/fib.d.ts +1 -28
  13. package/dist/fib/fib.js +9 -1
  14. package/dist/fib/offsets.cjs +9 -1
  15. package/dist/fib/offsets.d.cts +8 -0
  16. package/dist/fib/offsets.d.ts +8 -0
  17. package/dist/fib/offsets.js +9 -1
  18. package/dist/fib/write.cjs +43 -0
  19. package/dist/fib/write.d.cts +21 -0
  20. package/dist/fib/write.d.ts +21 -0
  21. package/dist/fib/write.js +42 -0
  22. package/dist/fib-CtsLtF96.d.cts +37 -0
  23. package/dist/fib-CtsLtF96.d.ts +37 -0
  24. package/dist/index.cjs +31 -0
  25. package/dist/index.d.cts +18 -7
  26. package/dist/index.d.ts +18 -7
  27. package/dist/index.js +14 -3
  28. package/dist/list/numbering.cjs +206 -0
  29. package/dist/list/numbering.d.cts +2 -0
  30. package/dist/list/numbering.d.ts +2 -0
  31. package/dist/list/numbering.js +205 -0
  32. package/dist/metadata.cjs +14 -0
  33. package/dist/metadata.d.cts +6 -0
  34. package/dist/metadata.d.ts +6 -0
  35. package/dist/metadata.js +13 -0
  36. package/dist/numbering-Cir-uGdc.d.cts +22 -0
  37. package/dist/numbering-DF1z1PyG.d.ts +22 -0
  38. package/dist/pap-BkFo8dZO.d.ts +29 -0
  39. package/dist/pap-BmelEYEP.d.cts +29 -0
  40. package/dist/prop/chp-write.cjs +47 -0
  41. package/dist/prop/chp-write.d.cts +5 -0
  42. package/dist/prop/chp-write.d.ts +5 -0
  43. package/dist/prop/chp-write.js +46 -0
  44. package/dist/prop/chp.cjs +15 -107
  45. package/dist/prop/chp.d.cts +3 -2
  46. package/dist/prop/chp.d.ts +3 -2
  47. package/dist/prop/chp.js +15 -107
  48. package/dist/prop/fkp-write.cjs +139 -0
  49. package/dist/prop/fkp-write.d.cts +21 -0
  50. package/dist/prop/fkp-write.d.ts +21 -0
  51. package/dist/prop/fkp-write.js +135 -0
  52. package/dist/prop/pap-write.cjs +67 -0
  53. package/dist/prop/pap-write.d.cts +5 -0
  54. package/dist/prop/pap-write.d.ts +5 -0
  55. package/dist/prop/pap-write.js +66 -0
  56. package/dist/prop/pap.cjs +10 -0
  57. package/dist/prop/pap.d.cts +1 -24
  58. package/dist/prop/pap.d.ts +1 -24
  59. package/dist/prop/pap.js +11 -1
  60. package/dist/prop/sep-write.cjs +63 -0
  61. package/dist/prop/sep-write.d.cts +9 -0
  62. package/dist/prop/sep-write.d.ts +9 -0
  63. package/dist/prop/sep-write.js +60 -0
  64. package/dist/prop/sep.cjs +63 -0
  65. package/dist/prop/sep.d.cts +16 -0
  66. package/dist/prop/sep.d.ts +16 -0
  67. package/dist/prop/sep.js +61 -0
  68. package/dist/prop/sprm.d.cts +1 -25
  69. package/dist/prop/sprm.d.ts +1 -25
  70. package/dist/read.cjs +44 -18
  71. package/dist/read.d.cts +21 -4
  72. package/dist/read.d.ts +21 -4
  73. package/dist/read.js +46 -20
  74. package/dist/sprm-Djg5RNiq.d.cts +26 -0
  75. package/dist/sprm-Djg5RNiq.d.ts +26 -0
  76. package/dist/style/fonts.cjs +68 -0
  77. package/dist/style/fonts.d.cts +5 -0
  78. package/dist/style/fonts.d.ts +5 -0
  79. package/dist/style/fonts.js +66 -0
  80. package/dist/style/stsh.cjs +23 -0
  81. package/dist/style/stsh.d.cts +2 -1
  82. package/dist/style/stsh.d.ts +2 -1
  83. package/dist/style/stsh.js +23 -1
  84. package/dist/table/decoration.cjs +220 -0
  85. package/dist/table/decoration.d.cts +41 -0
  86. package/dist/table/decoration.d.ts +41 -0
  87. package/dist/table/decoration.js +205 -0
  88. package/dist/table/read.cjs +192 -0
  89. package/dist/table/read.d.cts +6 -0
  90. package/dist/table/read.d.ts +6 -0
  91. package/dist/table/read.js +191 -0
  92. package/dist/table/tap-write.cjs +125 -0
  93. package/dist/table/tap-write.d.cts +13 -0
  94. package/dist/table/tap-write.d.ts +13 -0
  95. package/dist/table/tap-write.js +124 -0
  96. package/dist/table/tap.cjs +217 -0
  97. package/dist/table/tap.d.cts +29 -0
  98. package/dist/table/tap.d.ts +29 -0
  99. package/dist/table/tap.js +213 -0
  100. package/dist/table/write.cjs +136 -0
  101. package/dist/table/write.d.cts +13 -0
  102. package/dist/table/write.d.ts +13 -0
  103. package/dist/table/write.js +135 -0
  104. package/dist/text/piece-table-write.cjs +24 -0
  105. package/dist/text/piece-table-write.d.cts +4 -0
  106. package/dist/text/piece-table-write.d.ts +4 -0
  107. package/dist/text/piece-table-write.js +23 -0
  108. package/dist/write.cjs +175 -0
  109. package/dist/write.d.cts +5 -0
  110. package/dist/write.d.ts +5 -0
  111. package/dist/write.js +174 -0
  112. package/package.json +3 -3
@@ -0,0 +1,205 @@
1
+ import { DocFormatError } from "../errors.js";
2
+ import { readInt16LE, readInt32LE, readUint16LE, readUint8, slice } from "../bytes.js";
3
+ //#region src/list/numbering.ts
4
+ const LSTF_SIZE = 28;
5
+ const LVLF_SIZE = 28;
6
+ const LFO_SIZE = 16;
7
+ /** LSTF's own flags byte ([MS-DOC] 2.9.191), bit 0: "this LSTF represents a simple (one-level) list that has one corresponding LVL. Otherwise... a multi-level list that has nine corresponding LVLs." */
8
+ const LSTF_FLAG_SIMPLE_LIST = 1;
9
+ /** MSONFC ([MS-OSHARED] 2.2.1.3), mapped to its own documented ST_NumberFormat equivalent -- the identical vocabulary ooxml.js's NumberingLevel.format carries verbatim from word/numbering.xml's own w:numFmt/@w:val. Every member through msonfcUCRus (0x3B) is a real numbered/lettered/ideograph format; 0x17 (msonfcBullet) is handled separately below since PlfLfo also treats it as the "no number sequence, but has bullets" case LVLF's own field text calls out by name. */
10
+ const NUMBER_FORMAT_BY_NFC = {
11
+ 0: "decimal",
12
+ 1: "upperRoman",
13
+ 2: "lowerRoman",
14
+ 3: "upperLetter",
15
+ 4: "lowerLetter",
16
+ 5: "ordinal",
17
+ 6: "cardinalText",
18
+ 7: "ordinalText",
19
+ 8: "hex",
20
+ 9: "chicago",
21
+ 10: "ideographDigital",
22
+ 11: "japaneseCounting",
23
+ 12: "Aiueo",
24
+ 13: "Iroha",
25
+ 14: "decimalFullWidth",
26
+ 15: "decimalHalfWidth",
27
+ 16: "japaneseLegal",
28
+ 17: "japaneseDigitalTenThousand",
29
+ 18: "decimalEnclosedCircle",
30
+ 19: "decimalFullWidth2",
31
+ 20: "aiueoFullWidth",
32
+ 21: "irohaFullWidth",
33
+ 22: "decimalZero",
34
+ 23: "bullet",
35
+ 24: "ganada",
36
+ 25: "chosung",
37
+ 26: "decimalEnclosedFullstop",
38
+ 27: "decimalEnclosedParen",
39
+ 28: "decimalEnclosedCircleChinese",
40
+ 29: "ideographEnclosedCircle",
41
+ 30: "ideographTraditional",
42
+ 31: "ideographZodiac",
43
+ 32: "ideographZodiacTraditional",
44
+ 33: "taiwaneseCounting",
45
+ 34: "ideographLegalTraditional",
46
+ 35: "taiwaneseCountingThousand",
47
+ 36: "taiwaneseDigital",
48
+ 37: "chineseCounting",
49
+ 38: "chineseLegalSimplified",
50
+ 39: "chineseCountingThousand",
51
+ 40: "decimal",
52
+ 41: "koreanDigital",
53
+ 42: "koreanCounting",
54
+ 43: "koreanLegal",
55
+ 44: "koreanDigital2",
56
+ 45: "hebrew1",
57
+ 46: "arabicAlpha",
58
+ 47: "hebrew2",
59
+ 48: "arabicAbjad",
60
+ 49: "hindiVowels",
61
+ 50: "hindiConsonants",
62
+ 51: "hindiNumbers",
63
+ 52: "hindiCounting",
64
+ 53: "thaiLetters",
65
+ 54: "thaiNumbers",
66
+ 55: "thaiCounting",
67
+ 56: "vietnameseCounting",
68
+ 57: "numberInDash",
69
+ 58: "russianLower",
70
+ 59: "russianUpper"
71
+ };
72
+ /** MSONFC's own "Specifies that the sequence will not display any numbering" sentinel -- not itself an ST_NumberFormat value, so this reader's own spelling for it ("none") is a deliberate literal rather than a value MSONFC's table states. */
73
+ const NFC_NONE = 255;
74
+ function numberFormatFor(nfc) {
75
+ if (nfc === NFC_NONE) return "none";
76
+ const format = NUMBER_FORMAT_BY_NFC[nfc];
77
+ if (format === void 0) throw new DocFormatError(`LVLF.nfc is 0x${nfc.toString(16).padStart(2, "0")}, not a recognised MSONFC value ([MS-OSHARED] 2.2.1.3)`);
78
+ return format;
79
+ }
80
+ /** LSTF ([MS-DOC] 2.9.191): lsid(4) + tplc(4, ignored -- UI-only) + rgistdPara(18, ignored -- this reader has no per-level style cascade to link into) + a flags byte (only fSimpleList, bit 0, acted on) + grfhic(1, ignored -- HTML-export-only incompatibility flags). Fixed 28 bytes. */
81
+ function readLstf(bytes, offset) {
82
+ return {
83
+ lsid: readInt32LE(bytes, offset),
84
+ fSimpleList: (readUint8(bytes, offset + 26) & LSTF_FLAG_SIMPLE_LIST) !== 0
85
+ };
86
+ }
87
+ /** Xst ([MS-DOC] 2.9.343): cch(2 bytes) then that many raw 16-bit code units, prefixed-length and not null-terminated. Decoded as a plain UTF-16 string -- readLevelText below re-inspects specific character positions afterward for placeholders, which round-trips exactly through String.fromCharCode/charCodeAt since every placeholder value (0-8) sits well within one UTF-16 code unit and never needs a surrogate pair. Returns the decoded text and the byte length consumed, since the caller must advance past it to reach grpprlPapx/grpprlChpx or the next LVL. */
88
+ function readXst(bytes, offset) {
89
+ const cch = readUint16LE(bytes, offset);
90
+ let text = "";
91
+ for (let index = 0; index < cch; index += 1) text += String.fromCharCode(readUint16LE(bytes, offset + 2 + index * 2));
92
+ return {
93
+ text,
94
+ byteLength: 2 + cch * 2
95
+ };
96
+ }
97
+ /** rgbxchNums ([MS-DOC] 2.9.148's own LVLF field): nine 8-bit one-based character offsets into the LVL's own xst.rgtchar, zero-terminated (a 0 entry, or the end of the fixed 9-byte array, ends the list). Each offset it names is a POSITION in the string, not a value -- readLevelText is what turns a position into the placeholder it names. */
98
+ function readRgbxchNums(bytes, offset) {
99
+ const positions = [];
100
+ for (let index = 0; index < 9; index += 1) {
101
+ const value = readUint8(bytes, offset + index);
102
+ if (value === 0) break;
103
+ positions.push(value);
104
+ }
105
+ return positions;
106
+ }
107
+ /** Turns an Xst's own decoded text plus its rgbxchNums positions into the '%1.'-style placeholder text NumberingLevel.text states -- the mirror of readXst/readRgbxchNums together. [MS-DOC]'s own Xst field text: "Each placeholder is an unsigned 2-byte integer that specifies the zero-based level that the placeholder is for" -- so the character AT a named position is not a literal code point at all, but a raw level index (0-8) String.fromCharCode/charCodeAt round-trips losslessly; every other position is decoded as ordinary text. A one-based placeholder ('%1' for level 0) matches ooxml.js's own w:lvlText convention, so a consumer already resolving '%1.'/'%2)' style docx templates resolves this reader's templates identically. */
108
+ function readLevelText(xstText, placeholderPositions) {
109
+ const placeholders = new Set(placeholderPositions);
110
+ let result = "";
111
+ for (let index = 0; index < xstText.length; index += 1) {
112
+ const oneBasedPosition = index + 1;
113
+ if (placeholders.has(oneBasedPosition)) {
114
+ const levelIndex = xstText.charCodeAt(index);
115
+ result += `%${levelIndex + 1}`;
116
+ } else result += xstText.charAt(index);
117
+ }
118
+ return result;
119
+ }
120
+ /** LVL ([MS-DOC] 2.9.196): a 28-byte LVLF, then grpprlPapx (cbGrpprlPapx bytes, skipped -- see this module's own top comment), grpprlChpx (cbGrpprlChpx bytes, skipped), then the level's own Xst. Every LVL is variable-length, so the caller must use byteLength to advance to the next one in the array -- there is no outer length field to skip by instead. */
121
+ function readLvl(bytes, offset) {
122
+ if (offset + LVLF_SIZE > bytes.length) throw new DocFormatError(`PlfLst's own appended LVL array runs past the end of its ${bytes.length}-byte buffer at offset ${offset}, ${LVLF_SIZE} bytes short of one LVLF`);
123
+ const iStartAt = readInt32LE(bytes, offset);
124
+ const nfc = readUint8(bytes, offset + 4);
125
+ const fNoRestart = (readUint8(bytes, offset + 5) & 2) !== 0;
126
+ const rgbxchNums = readRgbxchNums(bytes, offset + 6);
127
+ const cbGrpprlChpx = readUint8(bytes, offset + 24);
128
+ const cbGrpprlPapx = readUint8(bytes, offset + 25);
129
+ const ilvlRestartLim = readUint8(bytes, offset + 26);
130
+ const { text: xstText, byteLength: xstByteLength } = readXst(bytes, offset + LVLF_SIZE + cbGrpprlPapx + cbGrpprlChpx);
131
+ const level = {
132
+ format: numberFormatFor(nfc),
133
+ text: readLevelText(xstText, rgbxchNums),
134
+ startAt: iStartAt
135
+ };
136
+ return {
137
+ level: fNoRestart ? {
138
+ ...level,
139
+ restart: ilvlRestartLim
140
+ } : level,
141
+ byteLength: LVLF_SIZE + cbGrpprlPapx + cbGrpprlChpx + xstByteLength
142
+ };
143
+ }
144
+ /** PlfLst ([MS-DOC] 2.9.226): cLst(2 bytes, signed) then that many 28-byte LSTF entries -- followed IMMEDIATELY by the appended LVL array FibRgFcLcb97's own fcPlfLst field describes, which lcbPlfLst does not account for and which this function therefore reads past the declared PlfLst length to reach. */
145
+ function parsePlfLst(table, fc, lcb) {
146
+ const plfLst = slice(table, fc, lcb, "PlfLst");
147
+ const cLst = readInt16LE(plfLst, 0);
148
+ if (cLst < 0) throw new DocFormatError(`PlfLst.cLst is ${cLst}, a negative LSTF count [MS-DOC] 2.9.226 never permits`);
149
+ const lstfs = [];
150
+ for (let index = 0; index < cLst; index += 1) lstfs.push(readLstf(plfLst, 2 + index * LSTF_SIZE));
151
+ let cursor = fc + lcb;
152
+ const levelsByLstf = [];
153
+ for (const lstf of lstfs) {
154
+ const count = lstf.fSimpleList ? 1 : 9;
155
+ const levels = [];
156
+ for (let index = 0; index < count; index += 1) {
157
+ const { level, byteLength } = readLvl(table, cursor);
158
+ levels.push(level);
159
+ cursor += byteLength;
160
+ }
161
+ levelsByLstf.push(levels);
162
+ }
163
+ return {
164
+ lstfs,
165
+ levelsByLstf
166
+ };
167
+ }
168
+ /** PlfLfo ([MS-DOC] 2.9.225): lfoMac(4 bytes) then that many 16-byte LFO entries (rgLfo), then rgLfoData -- this reader's own scope stops at rgLfo, since resolving ilfo to a list needs only each LFO's own lsid (rgLfoData carries LFOLVL overrides this reader deliberately does not apply; see this module's own top comment). rgLfo sits entirely before rgLfoData in the stream, so not reading rgLfoData at all is a real, not merely partial, saving -- no cursor needs to walk past it. */
169
+ function parseLfoLsids(table, fc, lcb) {
170
+ const plfLfo = slice(table, fc, lcb, "PlfLfo");
171
+ const lfoMac = readInt32LE(plfLfo, 0);
172
+ if (lfoMac < 0) throw new DocFormatError(`PlfLfo.lfoMac is ${lfoMac}, a negative LFO count [MS-DOC] 2.9.225 never permits`);
173
+ const lsids = [];
174
+ for (let index = 0; index < lfoMac; index += 1) {
175
+ const offset = 4 + index * LFO_SIZE;
176
+ if (offset + LFO_SIZE > plfLfo.length) throw new DocFormatError(`PlfLfo declares lfoMac=${lfoMac} LFO entries, but its own ${plfLfo.length}-byte buffer has room for only ${Math.floor((plfLfo.length - 4) / LFO_SIZE)}`);
177
+ lsids.push(readInt32LE(plfLfo, offset));
178
+ }
179
+ return lsids;
180
+ }
181
+ /** Resolves PlfLst and PlfLfo into NumberingDefinitions, keyed by the one-based ilfo every listId already is (prop/pap.ts's own Math.abs(ilfo)) -- absent entirely when the file carries neither (fcPlfLst/fcPlfLfo both 0, a document with no lists at all, the common case this reader must not fail on). */
182
+ function readNumberingDefinitions(table, fib) {
183
+ if (fib.lcbPlfLst === 0 || fib.lcbPlfLfo === 0) return {};
184
+ const { lstfs, levelsByLstf } = parsePlfLst(table, fib.fcPlfLst, fib.lcbPlfLst);
185
+ const lsids = parseLfoLsids(table, fib.fcPlfLfo, fib.lcbPlfLfo);
186
+ const levelsByLsid = /* @__PURE__ */ new Map();
187
+ lstfs.forEach((lstf, index) => {
188
+ const levels = levelsByLstf[index];
189
+ if (levels !== void 0) levelsByLsid.set(lstf.lsid, levels);
190
+ });
191
+ const definitions = {};
192
+ lsids.forEach((lsid, index) => {
193
+ const levels = levelsByLsid.get(lsid);
194
+ if (levels === void 0) return;
195
+ const ilfo = index + 1;
196
+ const byLevel = {};
197
+ levels.forEach((level, levelIndex) => {
198
+ byLevel[String(levelIndex)] = level;
199
+ });
200
+ definitions[String(ilfo)] = { levels: byLevel };
201
+ });
202
+ return definitions;
203
+ }
204
+ //#endregion
205
+ export { readNumberingDefinitions };
@@ -0,0 +1,14 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_errors = require("./errors.cjs");
3
+ let archive_codec = require("archive-codec");
4
+ //#region src/metadata.ts
5
+ function requireValidIsoDate(value, field) {
6
+ if (value !== void 0 && Number.isNaN(new Date(value).getTime())) throw new require_errors.DocFormatError(`LayoutMetadata.${field} "${value}" is not a valid date string, so it cannot be written as a SummaryInformation FILETIME property`);
7
+ }
8
+ function layoutMetadataToSummaryInformation(metadata) {
9
+ requireValidIsoDate(metadata.createdIso, "createdIso");
10
+ requireValidIsoDate(metadata.modifiedIso, "modifiedIso");
11
+ return (0, archive_codec.layoutMetadataToSummaryInformation)(metadata);
12
+ }
13
+ //#endregion
14
+ exports.layoutMetadataToSummaryInformation = layoutMetadataToSummaryInformation;
@@ -0,0 +1,6 @@
1
+ import { LayoutMetadata } from "document-schema.js";
2
+ import { SummaryInformationProperties } from "archive-codec";
3
+ //#region src/metadata.d.ts
4
+ declare function layoutMetadataToSummaryInformation(metadata: LayoutMetadata): SummaryInformationProperties;
5
+ //#endregion
6
+ export { layoutMetadataToSummaryInformation };
@@ -0,0 +1,6 @@
1
+ import { SummaryInformationProperties } from "archive-codec";
2
+ import { LayoutMetadata } from "document-schema.js";
3
+ //#region src/metadata.d.ts
4
+ declare function layoutMetadataToSummaryInformation(metadata: LayoutMetadata): SummaryInformationProperties;
5
+ //#endregion
6
+ export { layoutMetadataToSummaryInformation };
@@ -0,0 +1,13 @@
1
+ import { DocFormatError } from "./errors.js";
2
+ import { layoutMetadataToSummaryInformation as layoutMetadataToSummaryInformation$1 } from "archive-codec";
3
+ //#region src/metadata.ts
4
+ function requireValidIsoDate(value, field) {
5
+ if (value !== void 0 && Number.isNaN(new Date(value).getTime())) throw new DocFormatError(`LayoutMetadata.${field} "${value}" is not a valid date string, so it cannot be written as a SummaryInformation FILETIME property`);
6
+ }
7
+ function layoutMetadataToSummaryInformation(metadata) {
8
+ requireValidIsoDate(metadata.createdIso, "createdIso");
9
+ requireValidIsoDate(metadata.modifiedIso, "modifiedIso");
10
+ return layoutMetadataToSummaryInformation$1(metadata);
11
+ }
12
+ //#endregion
13
+ export { layoutMetadataToSummaryInformation };
@@ -0,0 +1,22 @@
1
+ import { t as Fib } from "./fib-CtsLtF96.cjs";
2
+ //#region src/list/numbering.d.ts
3
+ interface NumberingLevel {
4
+ /** The ST_NumberFormat-equivalent string MSONFC's own value maps to ("decimal", "upperRoman", "bullet", ...), or "none" for a level with no number sequence at all ([MS-DOC] 2.9.148's own nfc field text: "If this is equal to 0xFF..., this level does not have a number sequence"). */
5
+ readonly format: string;
6
+ /** The level's own text template: a placeholder pattern like '%1.' or '%2)' for a numbered format (the digit names which zero-based level's own counter substitutes at that position, one-based in the placeholder itself) -- the identical convention ooxml.js's own NumberingLevel.text carries verbatim from w:lvlText/@w:val -- or a literal bullet glyph string for format 'bullet'. Decoded from the level's own Xst (a raw UTF-16 string) plus its rgbxchNums array, which names which character POSITIONS in that string are placeholders rather than literal text -- see readLevelText below. */
7
+ readonly text: string;
8
+ /** iStartAt: the value this level's counter begins from. Meaningless (and not read as anything but 1) for a level with no number sequence. */
9
+ readonly startAt: number;
10
+ /** ilvlRestartLim ([MS-DOC] 2.9.148), only when fNoRestart is set: the first (most-significant) zero-based level after which this level's own number sequence does NOT restart. Absent (undefined) is the spec's own default behaviour -- "restarts when a more significant level is encountered" -- not "never restarts". */
11
+ readonly restart?: number;
12
+ }
13
+ interface NumberingDefinition {
14
+ /** Keyed by the level's own zero-based ilvl, stringified -- the identical zero-based numbering ContentListMembership.level already uses, so `definitions[membership.numId]?.levels[String(membership.level)]` is the direct lookup path from a paragraph's own membership to its rendering definition. A record rather than a fixed-length array/tuple: a simple (fSimpleList) LSTF states only level 0. */
15
+ readonly levels: Readonly<Record<string, NumberingLevel>>;
16
+ }
17
+ /** Keyed by a paragraph's own listId (ContentListMembership.numId, stringified) -- prop/pap.ts's own sprmPIlfo, a one-based index into PlfLfo.rgLfo. */
18
+ type NumberingDefinitions = Readonly<Record<string, NumberingDefinition>>;
19
+ /** Resolves PlfLst and PlfLfo into NumberingDefinitions, keyed by the one-based ilfo every listId already is (prop/pap.ts's own Math.abs(ilfo)) -- absent entirely when the file carries neither (fcPlfLst/fcPlfLfo both 0, a document with no lists at all, the common case this reader must not fail on). */
20
+ declare function readNumberingDefinitions(table: Uint8Array, fib: Fib): NumberingDefinitions;
21
+ //#endregion
22
+ export { readNumberingDefinitions as i, NumberingDefinitions as n, NumberingLevel as r, NumberingDefinition as t };
@@ -0,0 +1,22 @@
1
+ import { t as Fib } from "./fib-CtsLtF96.js";
2
+ //#region src/list/numbering.d.ts
3
+ interface NumberingLevel {
4
+ /** The ST_NumberFormat-equivalent string MSONFC's own value maps to ("decimal", "upperRoman", "bullet", ...), or "none" for a level with no number sequence at all ([MS-DOC] 2.9.148's own nfc field text: "If this is equal to 0xFF..., this level does not have a number sequence"). */
5
+ readonly format: string;
6
+ /** The level's own text template: a placeholder pattern like '%1.' or '%2)' for a numbered format (the digit names which zero-based level's own counter substitutes at that position, one-based in the placeholder itself) -- the identical convention ooxml.js's own NumberingLevel.text carries verbatim from w:lvlText/@w:val -- or a literal bullet glyph string for format 'bullet'. Decoded from the level's own Xst (a raw UTF-16 string) plus its rgbxchNums array, which names which character POSITIONS in that string are placeholders rather than literal text -- see readLevelText below. */
7
+ readonly text: string;
8
+ /** iStartAt: the value this level's counter begins from. Meaningless (and not read as anything but 1) for a level with no number sequence. */
9
+ readonly startAt: number;
10
+ /** ilvlRestartLim ([MS-DOC] 2.9.148), only when fNoRestart is set: the first (most-significant) zero-based level after which this level's own number sequence does NOT restart. Absent (undefined) is the spec's own default behaviour -- "restarts when a more significant level is encountered" -- not "never restarts". */
11
+ readonly restart?: number;
12
+ }
13
+ interface NumberingDefinition {
14
+ /** Keyed by the level's own zero-based ilvl, stringified -- the identical zero-based numbering ContentListMembership.level already uses, so `definitions[membership.numId]?.levels[String(membership.level)]` is the direct lookup path from a paragraph's own membership to its rendering definition. A record rather than a fixed-length array/tuple: a simple (fSimpleList) LSTF states only level 0. */
15
+ readonly levels: Readonly<Record<string, NumberingLevel>>;
16
+ }
17
+ /** Keyed by a paragraph's own listId (ContentListMembership.numId, stringified) -- prop/pap.ts's own sprmPIlfo, a one-based index into PlfLfo.rgLfo. */
18
+ type NumberingDefinitions = Readonly<Record<string, NumberingDefinition>>;
19
+ /** Resolves PlfLst and PlfLfo into NumberingDefinitions, keyed by the one-based ilfo every listId already is (prop/pap.ts's own Math.abs(ilfo)) -- absent entirely when the file carries neither (fcPlfLst/fcPlfLfo both 0, a document with no lists at all, the common case this reader must not fail on). */
20
+ declare function readNumberingDefinitions(table: Uint8Array, fib: Fib): NumberingDefinitions;
21
+ //#endregion
22
+ export { readNumberingDefinitions as i, NumberingDefinitions as n, NumberingLevel as r, NumberingDefinition as t };
@@ -0,0 +1,29 @@
1
+ import { t as Prl } from "./sprm-Djg5RNiq.js";
2
+ import { Alignment } from "document-schema.js";
3
+ //#region src/prop/pap.d.ts
4
+ interface ParagraphProperties {
5
+ istd?: number;
6
+ alignment?: Alignment;
7
+ indentLeftPt?: number;
8
+ indentRightPt?: number;
9
+ indentFirstLinePt?: number;
10
+ spacingBeforePt?: number;
11
+ spacingAfterPt?: number;
12
+ lineSpacing?: number;
13
+ pageBreakBefore?: boolean;
14
+ /** sprmPOutLvl's zero-based level, present only when the paragraph is genuinely in an outline level rather than body text. */
15
+ outlineLevel?: number;
16
+ inTable?: boolean;
17
+ /** True on the cell mark that terminates a table row. */
18
+ tableRowEnd?: boolean;
19
+ listLevel?: number;
20
+ /** The list identifier (sprmPIlfo), present only when the paragraph is in a list at all. */
21
+ listId?: number;
22
+ /** sprmPItap's own table depth, present only when the sprm is; a value greater than 1 marks a table nested inside a table cell. */
23
+ tableDepth?: number;
24
+ /** True when sprmPFInnerTableCell or sprmPFInnerTtp is set -- a nested table's own cell/row-ending mark, carried purely as a refusal signal since this package's table support does not descend into a nested table. */
25
+ nestedTableMark?: boolean;
26
+ }
27
+ declare function applyParagraphSprms(prls: readonly Prl[], into: ParagraphProperties): ParagraphProperties;
28
+ //#endregion
29
+ export { applyParagraphSprms as n, ParagraphProperties as t };
@@ -0,0 +1,29 @@
1
+ import { t as Prl } from "./sprm-Djg5RNiq.cjs";
2
+ import { Alignment } from "document-schema.js";
3
+ //#region src/prop/pap.d.ts
4
+ interface ParagraphProperties {
5
+ istd?: number;
6
+ alignment?: Alignment;
7
+ indentLeftPt?: number;
8
+ indentRightPt?: number;
9
+ indentFirstLinePt?: number;
10
+ spacingBeforePt?: number;
11
+ spacingAfterPt?: number;
12
+ lineSpacing?: number;
13
+ pageBreakBefore?: boolean;
14
+ /** sprmPOutLvl's zero-based level, present only when the paragraph is genuinely in an outline level rather than body text. */
15
+ outlineLevel?: number;
16
+ inTable?: boolean;
17
+ /** True on the cell mark that terminates a table row. */
18
+ tableRowEnd?: boolean;
19
+ listLevel?: number;
20
+ /** The list identifier (sprmPIlfo), present only when the paragraph is in a list at all. */
21
+ listId?: number;
22
+ /** sprmPItap's own table depth, present only when the sprm is; a value greater than 1 marks a table nested inside a table cell. */
23
+ tableDepth?: number;
24
+ /** True when sprmPFInnerTableCell or sprmPFInnerTtp is set -- a nested table's own cell/row-ending mark, carried purely as a refusal signal since this package's table support does not descend into a nested table. */
25
+ nestedTableMark?: boolean;
26
+ }
27
+ declare function applyParagraphSprms(prls: readonly Prl[], into: ParagraphProperties): ParagraphProperties;
28
+ //#endregion
29
+ export { applyParagraphSprms as n, ParagraphProperties as t };
@@ -0,0 +1,47 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_errors = require("../errors.cjs");
3
+ const require_color = require("../color.cjs");
4
+ //#region src/prop/chp-write.ts
5
+ /** sprmCFBold, sprmCFItalic, sprmCFStrike: a 1-byte ToggleOperand, [MS-DOC] 2.9.336. 0x00 and 0x01 are the only values this writer emits -- 0x80/0x81 (inherit/invert relative to a style) have no meaning here, since this package writes no style sheet for a run's character properties to inherit from. */
6
+ const SPRM_C_F_BOLD = 2101;
7
+ const SPRM_C_F_ITALIC = 2102;
8
+ const SPRM_C_F_STRIKE = 2103;
9
+ /** sprmCKul: a 1-byte Kul value. 0x00 is "none"; 0x01 is kulSingle, the only underline style ContentRun.underline can express (a plain boolean, not a style enum). */
10
+ const SPRM_C_KUL = 10814;
11
+ const KUL_NONE = 0;
12
+ const KUL_SINGLE = 1;
13
+ /** sprmCHps: a 2-byte unsigned half-point size. */
14
+ const SPRM_C_HPS = 19011;
15
+ /** sprmCCv: a 4-byte COLORREF (r, g, b, fAuto). fAuto 0x00 means "use these components", the only form this writer emits. */
16
+ const SPRM_C_CV = 26736;
17
+ /** sprmCRgFtc0: a 2-byte signed index into the font table, [MS-DOC] 2.6.2 -- see style/fonts.ts. */
18
+ const SPRM_C_RG_FTC_0 = 19023;
19
+ const HALF_POINTS_PER_POINT = 2;
20
+ /** sprmCHps's own operand range: an unsigned 2-byte half-point value. */
21
+ const MAX_HPS = 65535;
22
+ function pushSprm(bytes, opcode, operand) {
23
+ bytes.push(opcode & 255, opcode >> 8 & 255, ...operand);
24
+ }
25
+ function toggle(value) {
26
+ return [value ? 1 : 0];
27
+ }
28
+ function uint16(value) {
29
+ return [value & 255, value >> 8 & 255];
30
+ }
31
+ function encodeCharacterGrpprl(run, fontIndexOf) {
32
+ const bytes = [];
33
+ if (run.bold !== void 0) pushSprm(bytes, SPRM_C_F_BOLD, toggle(run.bold));
34
+ if (run.italic !== void 0) pushSprm(bytes, SPRM_C_F_ITALIC, toggle(run.italic));
35
+ if (run.strike !== void 0) pushSprm(bytes, SPRM_C_F_STRIKE, toggle(run.strike));
36
+ if (run.underline !== void 0) pushSprm(bytes, SPRM_C_KUL, [run.underline ? KUL_SINGLE : KUL_NONE]);
37
+ if (run.sizePt !== void 0) {
38
+ const halfPoints = Math.round(run.sizePt * HALF_POINTS_PER_POINT);
39
+ if (halfPoints < 0 || halfPoints > MAX_HPS) throw new require_errors.DocFormatError(`run sizePt ${run.sizePt} is ${halfPoints} half-points, outside the 0..${MAX_HPS} range sprmCHps's unsigned 2-byte operand can hold`);
40
+ pushSprm(bytes, SPRM_C_HPS, uint16(halfPoints));
41
+ }
42
+ if (run.color !== void 0) pushSprm(bytes, SPRM_C_CV, require_color.colorRefBytes(run.color));
43
+ if (run.fontFamily !== void 0) pushSprm(bytes, SPRM_C_RG_FTC_0, uint16(fontIndexOf(run.fontFamily)));
44
+ return bytes;
45
+ }
46
+ //#endregion
47
+ exports.encodeCharacterGrpprl = encodeCharacterGrpprl;
@@ -0,0 +1,5 @@
1
+ import { ContentRun } from "document-schema.js";
2
+ //#region src/prop/chp-write.d.ts
3
+ declare function encodeCharacterGrpprl(run: Pick<ContentRun, "bold" | "italic" | "underline" | "strike" | "sizePt" | "color" | "fontFamily">, fontIndexOf: (name: string) => number): number[];
4
+ //#endregion
5
+ export { encodeCharacterGrpprl };
@@ -0,0 +1,5 @@
1
+ import { ContentRun } from "document-schema.js";
2
+ //#region src/prop/chp-write.d.ts
3
+ declare function encodeCharacterGrpprl(run: Pick<ContentRun, "bold" | "italic" | "underline" | "strike" | "sizePt" | "color" | "fontFamily">, fontIndexOf: (name: string) => number): number[];
4
+ //#endregion
5
+ export { encodeCharacterGrpprl };
@@ -0,0 +1,46 @@
1
+ import { DocFormatError } from "../errors.js";
2
+ import { colorRefBytes } from "../color.js";
3
+ //#region src/prop/chp-write.ts
4
+ /** sprmCFBold, sprmCFItalic, sprmCFStrike: a 1-byte ToggleOperand, [MS-DOC] 2.9.336. 0x00 and 0x01 are the only values this writer emits -- 0x80/0x81 (inherit/invert relative to a style) have no meaning here, since this package writes no style sheet for a run's character properties to inherit from. */
5
+ const SPRM_C_F_BOLD = 2101;
6
+ const SPRM_C_F_ITALIC = 2102;
7
+ const SPRM_C_F_STRIKE = 2103;
8
+ /** sprmCKul: a 1-byte Kul value. 0x00 is "none"; 0x01 is kulSingle, the only underline style ContentRun.underline can express (a plain boolean, not a style enum). */
9
+ const SPRM_C_KUL = 10814;
10
+ const KUL_NONE = 0;
11
+ const KUL_SINGLE = 1;
12
+ /** sprmCHps: a 2-byte unsigned half-point size. */
13
+ const SPRM_C_HPS = 19011;
14
+ /** sprmCCv: a 4-byte COLORREF (r, g, b, fAuto). fAuto 0x00 means "use these components", the only form this writer emits. */
15
+ const SPRM_C_CV = 26736;
16
+ /** sprmCRgFtc0: a 2-byte signed index into the font table, [MS-DOC] 2.6.2 -- see style/fonts.ts. */
17
+ const SPRM_C_RG_FTC_0 = 19023;
18
+ const HALF_POINTS_PER_POINT = 2;
19
+ /** sprmCHps's own operand range: an unsigned 2-byte half-point value. */
20
+ const MAX_HPS = 65535;
21
+ function pushSprm(bytes, opcode, operand) {
22
+ bytes.push(opcode & 255, opcode >> 8 & 255, ...operand);
23
+ }
24
+ function toggle(value) {
25
+ return [value ? 1 : 0];
26
+ }
27
+ function uint16(value) {
28
+ return [value & 255, value >> 8 & 255];
29
+ }
30
+ function encodeCharacterGrpprl(run, fontIndexOf) {
31
+ const bytes = [];
32
+ if (run.bold !== void 0) pushSprm(bytes, SPRM_C_F_BOLD, toggle(run.bold));
33
+ if (run.italic !== void 0) pushSprm(bytes, SPRM_C_F_ITALIC, toggle(run.italic));
34
+ if (run.strike !== void 0) pushSprm(bytes, SPRM_C_F_STRIKE, toggle(run.strike));
35
+ if (run.underline !== void 0) pushSprm(bytes, SPRM_C_KUL, [run.underline ? KUL_SINGLE : KUL_NONE]);
36
+ if (run.sizePt !== void 0) {
37
+ const halfPoints = Math.round(run.sizePt * HALF_POINTS_PER_POINT);
38
+ if (halfPoints < 0 || halfPoints > MAX_HPS) throw new DocFormatError(`run sizePt ${run.sizePt} is ${halfPoints} half-points, outside the 0..${MAX_HPS} range sprmCHps's unsigned 2-byte operand can hold`);
39
+ pushSprm(bytes, SPRM_C_HPS, uint16(halfPoints));
40
+ }
41
+ if (run.color !== void 0) pushSprm(bytes, SPRM_C_CV, colorRefBytes(run.color));
42
+ if (run.fontFamily !== void 0) pushSprm(bytes, SPRM_C_RG_FTC_0, uint16(fontIndexOf(run.fontFamily)));
43
+ return bytes;
44
+ }
45
+ //#endregion
46
+ export { encodeCharacterGrpprl };
package/dist/prop/chp.cjs CHANGED
@@ -1,6 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_errors = require("../errors.cjs");
3
3
  const require_bytes = require("../bytes.cjs");
4
+ const require_color = require("../color.cjs");
4
5
  const require_prop_sprm = require("./sprm.cjs");
5
6
  //#region src/prop/chp.ts
6
7
  /** sprmCFBold: a ToggleOperand switching bold. */
@@ -15,100 +16,18 @@ const SPRM_C_KUL = 10814;
15
16
  const SPRM_C_HPS = 19011;
16
17
  /** sprmCIstd: the istd of a character style to apply. */
17
18
  const SPRM_C_ISTD = 18992;
18
- /** sprmCIco: an Ico value, an index into [MS-DOC] 2.9.126's fixed 17-entry palette. */
19
+ /** sprmCIco: an Ico value, an index into [MS-DOC] 2.9.119's fixed 17-entry palette. */
19
20
  const SPRM_C_ICO = 10818;
20
21
  /** sprmCCv: a COLORREF, the richer colour sprm that supersedes sprmCIco where both appear. */
21
22
  const SPRM_C_CV = 26736;
23
+ /** sprmCRgFtc0: a 2-byte signed index into the font table (SttbfFfn) naming the font used "only if the conditions for using [sprmCRgFtc1/sprmCRgFtc2/sprmCFtcBi] do not apply" -- the default (non-East-Asian, non-complex-script) font, which is the only one this package reads or writes. */
24
+ const SPRM_C_RG_FTC_0 = 19023;
22
25
  /** ToggleOperand, [MS-DOC] 2.9.336. 0x80 and 0x81 are relative to the style's own value rather than absolute. */
23
26
  const TOGGLE_OFF = 0;
24
27
  const TOGGLE_ON = 1;
25
28
  const TOGGLE_INHERIT_FROM_STYLE = 128;
26
29
  const TOGGLE_INVERT_STYLE = 129;
27
30
  const HALF_POINTS_PER_POINT = 2;
28
- const COLOR_COMPONENT_MAX = 255;
29
- const ICO_PALETTE = [
30
- void 0,
31
- [
32
- 0,
33
- 0,
34
- 0
35
- ],
36
- [
37
- 0,
38
- 0,
39
- 255
40
- ],
41
- [
42
- 0,
43
- 255,
44
- 255
45
- ],
46
- [
47
- 0,
48
- 255,
49
- 0
50
- ],
51
- [
52
- 255,
53
- 0,
54
- 255
55
- ],
56
- [
57
- 255,
58
- 0,
59
- 0
60
- ],
61
- [
62
- 255,
63
- 255,
64
- 0
65
- ],
66
- [
67
- 255,
68
- 255,
69
- 255
70
- ],
71
- [
72
- 0,
73
- 0,
74
- 128
75
- ],
76
- [
77
- 0,
78
- 128,
79
- 128
80
- ],
81
- [
82
- 0,
83
- 128,
84
- 0
85
- ],
86
- [
87
- 128,
88
- 0,
89
- 128
90
- ],
91
- [
92
- 128,
93
- 0,
94
- 128
95
- ],
96
- [
97
- 128,
98
- 128,
99
- 0
100
- ],
101
- [
102
- 128,
103
- 128,
104
- 128
105
- ],
106
- [
107
- 192,
108
- 192,
109
- 192
110
- ]
111
- ];
112
31
  function toggle(operand, current) {
113
32
  const value = require_bytes.readUint8(operand, 0);
114
33
  switch (value) {
@@ -119,26 +38,7 @@ function toggle(operand, current) {
119
38
  default: throw new require_errors.DocFormatError(`ToggleOperand value 0x${value.toString(16)} is none of the four [MS-DOC] 2.9.336 defines (0x00, 0x01, 0x80, 0x81)`);
120
39
  }
121
40
  }
122
- function icoColor(value) {
123
- if (value >= ICO_PALETTE.length) throw new require_errors.DocFormatError(`Ico value 0x${value.toString(16)} is not less than 0x11, the bound [MS-DOC] 2.9.126 places on the palette`);
124
- const entry = ICO_PALETTE[value];
125
- if (entry === void 0) return void 0;
126
- const [r, g, b] = entry;
127
- return {
128
- r: r / COLOR_COMPONENT_MAX,
129
- g: g / COLOR_COMPONENT_MAX,
130
- b: b / COLOR_COMPONENT_MAX
131
- };
132
- }
133
- function colorRefColor(operand) {
134
- if (require_bytes.readUint8(operand, 3) !== 0) return void 0;
135
- return {
136
- r: require_bytes.readUint8(operand, 0) / COLOR_COMPONENT_MAX,
137
- g: require_bytes.readUint8(operand, 1) / COLOR_COMPONENT_MAX,
138
- b: require_bytes.readUint8(operand, 2) / COLOR_COMPONENT_MAX
139
- };
140
- }
141
- function applyCharacterSprms(prls, into) {
41
+ function applyCharacterSprms(prls, into, fonts) {
142
42
  for (const prl of prls) {
143
43
  if (prl.sprm.sgc !== require_prop_sprm.SGC.character) continue;
144
44
  switch (prl.sprm.value) {
@@ -161,9 +61,17 @@ function applyCharacterSprms(prls, into) {
161
61
  into.istd = require_bytes.readUint16LE(prl.operand, 0);
162
62
  break;
163
63
  case SPRM_C_ICO:
164
- into.color = icoColor(require_bytes.readUint8(prl.operand, 0));
64
+ into.color = require_color.icoColor(require_bytes.readUint8(prl.operand, 0));
65
+ break;
66
+ case SPRM_C_CV:
67
+ into.color = require_color.readColorRef(prl.operand, 0);
68
+ break;
69
+ case SPRM_C_RG_FTC_0: {
70
+ const index = require_bytes.readInt16LE(prl.operand, 0);
71
+ const name = fonts?.[index];
72
+ if (name !== void 0) into.fontFamily = name;
165
73
  break;
166
- case SPRM_C_CV: into.color = colorRefColor(prl.operand);
74
+ }
167
75
  }
168
76
  }
169
77
  return into;
@@ -1,4 +1,4 @@
1
- import { Prl } from "./sprm.cjs";
1
+ import { t as Prl } from "../sprm-Djg5RNiq.cjs";
2
2
  import { Color } from "document-schema.js";
3
3
  //#region src/prop/chp.d.ts
4
4
  interface CharacterProperties {
@@ -8,9 +8,10 @@ interface CharacterProperties {
8
8
  strike?: boolean;
9
9
  sizePt?: number;
10
10
  color?: Color;
11
+ fontFamily?: string;
11
12
  /** The istd of a character style applied by sprmCIstd, carried so a caller can resolve the style's own name. */
12
13
  istd?: number;
13
14
  }
14
- declare function applyCharacterSprms(prls: readonly Prl[], into: CharacterProperties): CharacterProperties;
15
+ declare function applyCharacterSprms(prls: readonly Prl[], into: CharacterProperties, fonts?: readonly string[]): CharacterProperties;
15
16
  //#endregion
16
17
  export { CharacterProperties, applyCharacterSprms };