doc-codec 2.2.4 → 2.3.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/README.md CHANGED
@@ -16,7 +16,7 @@ Built and shipped, on the read side:
16
16
  - **The piece table** — `parseClx` resolves a `Clx` (skipping any leading `Prc` array) into the pieces the logical text stream is assembled from, including the compressed 8-bit spelling and its halved byte offset.
17
17
  - **Text reconstruction** — `readTextRange` turns a range of character positions into real characters through [MS-DOC] 2.4.1's own Retrieving Text algorithm, applying the specification's byte-to-code-point mapping for compressed pieces, and returns each character's byte offset alongside it.
18
18
  - **Character and paragraph formatting** — the `PlcBteChpx`/`PlcBtePapx` bin tables and the `ChpxFkp`/`PapxFkp` pages behind them, the `Sprm`/`Prl` operand-sizing rules, and the subset of the character- and paragraph-property tables listed under [What is converted](#what-is-converted), now including `sprmCRgFtc0`'s font-table lookup (see [The font table](#the-font-table)).
19
- - **The style sheet** — `parseStsh` reads each style's index, name, kind and parent, and `headingLevelFromIstd` applies `sprmPIstd`'s own rule that an `istd` of 1 through 9 states an outline level.
19
+ - **The style sheet** — `parseStsh` reads each style's index, name, kind, parent, and (for a paragraph or character style) its own `grLPUpxSw` formatting sets; `resolveStyleFormatting` walks the `istdBase` inheritance chain and folds each style's own paragraph/character properties, most-specific style winning, beneath a paragraph's or run's own direct exceptions ([ExaDev/documents.js#1005](https://github.com/ExaDev/documents.js/issues/1005)). `headingLevelFromIstd` applies `sprmPIstd`'s own rule that an `istd` of 1 through 9 states an outline level.
20
20
  - **Tables** — `table/read.ts`'s `assembleBlocks` folds a contiguous run of table-depth-1 paragraphs into a real `ContentTable`: cell boundaries at each cell-mark (`0x07`) character, a cell holding more than one paragraph where only its last ends in a cell mark, and each row's own trailing mark (`sprmPFTtp`) resolved through `table/tap.ts`'s `applyTableSprms` for its TAP — column boundaries and every physical cell's own horizontal/vertical merge state, from `sprmTDefTable`'s `TDefTableOperand` (and a `sprmTMerge` range or `sprmTVertMerge` per-cell flag where a real producer states a merge that way instead — see [Tables](#tables) below for why both are read). A table nested inside a table cell (table depth greater than 1, detected via `sprmPItap`/`sprmPFInnerTableCell`/`sprmPFInnerTtp`) is refused with `DocUnsupportedError` rather than mis-read; a row whose own TAP this reader cannot resolve at all — no direct `sprmTDefTable` anywhere in its grpprl, or a cell-mark count that disagrees with it — degrades the whole run back to flat paragraphs instead, since that is a legal producer choice this reader does not yet follow rather than corruption (see [Tables](#tables)).
21
21
  - **Table cell decoration** — `ContentTableCell.background` and `.borders`, from every encoding [MS-DOC] states them in: each cell's own four `Brc80` borders inside `TC80`, the exact-colour `sprmTSetBrc` layer a real producer writes beside them, the row-level shading arrays (`sprmTDefTableShd`/`2nd`/`3rd`, their `Raw` counterparts, the Word 97-era `sprmTDefTableShd80`, and `sprmTSetShd`/`sprmTSetShdOdd`), and, cascaded onto whichever cells and sides those leave unstated, the row/table-level `sprmTTableBorders`/`sprmTTableBorders80` border set and `sprmTSetShdTable`'s own per-row background. See [Cell decoration](#cell-decoration).
22
22
  - **`readDocContent`** — the whole chain, producing a `'wordprocessing'` `ContentDocument` of paragraphs, runs and tables.
@@ -32,18 +32,19 @@ Built and shipped, on the write side — see [Writing](#writing) for the full sc
32
32
 
33
33
  **Not built, and not approximated, on either side.** Each of these is a genuine layer of [MS-DOC] that this package does not implement; none is silently faked, and a document using one reads (or fails to write) as though it did not:
34
34
 
35
- | Absent | Consequence |
36
- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
37
- | **Nested tables** | A table inside a table cell (table depth greater than 1) is a genuinely different [MS-DOC] structure — `sprmPFInnerTableCell`/`sprmPFInnerTtp` mark its cell/row ends rather than `sprmPFInTable`/`sprmPFTtp`, and `sprmPItap`/`sprmPDtap` state the depth. Neither side of this package descends into one: `readDocContent` refuses with `DocUnsupportedError` the moment it detects a table depth greater than 1, and `writeDocContent` refuses a `ContentTable` block found inside a table cell's own blocks the same way. See [Tables](#tables) for the full scope of what a depth-1 table does resolve. |
38
- | **Images and drawn objects** | The anchor characters (`U+0001`, `U+0008`) are dropped rather than emitted as control characters. No picture data is read. `writeDocContent` refuses an image block. |
39
- | **Style-inherited formatting** | A style's own property sets live in the `STD`'s `grLPUpxSw` and are not read, so a paragraph's formatting is the document defaults plus its own direct exceptions. A `Heading 1` paragraph reports its `styleId` and `headingLevel` but not the boldness or size its style would supply. `writeDocContent` writes no paragraph styles at all (every paragraph is `istd` 0) and does not round-trip `styleId`/`headingLevel`. Tracked as its own, genuinely separate piece of work in [ExaDev/documents.js#1005](https://github.com/ExaDev/documents.js/issues/1005). |
40
- | **Subdocuments** | Only the main document (character positions 0 to `ccpText`) is converted. Footnotes, endnotes, headers, footers, comments and text boxes are not, in either direction. |
41
- | **Section boundaries** | Section boundaries themselves are not read — the whole document is always treated as one section, spanning the entire main document so a multi-section `.doc`'s later sections' own page size and margins are never consulted, only the first's (see the read-side page-size/margins bullet above for what is now read of that one section). `writeDocContent` refuses a `ContentDocument` with more than one section, rather than silently merging their content into what would read back as one. |
42
- | **Extended and user-defined document properties** | `title`/`subject`/`author`/`keywords`/`createdIso`/`modifiedIso` are read from and written to a `"\x05SummaryInformation"` stream when present (see [Metadata](#metadata)); the sibling `"\x05DocumentSummaryInformation"` stream (company, manager, and custom user-defined properties) is not read or written at all. |
43
- | **Encryption** | An encrypted or XOR-obfuscated document is refused with a `DocUnsupportedError` rather than read as plaintext. `writeDocContent` never encrypts. |
44
- | **`sprmPHugePapx` / `sprmPTableProps`** | Paragraph properties stored indirectly in the Data stream are not followed, so such a paragraph reads with fewer properties than it states. [MS-DOC] 2.4.3's own Overview of Tables text names `sprmPTableProps` as a real, legal alternative to `sprmTDefTable` some applications process — but a real producer's row mark is not shown to prefer it: a genuine LibreOffice-authored `.doc` table's own row mark states its TAP through the identical direct `sprmTDefTable` this package's reader and writer already use (confirmed by parsing a LibreOffice 26.2.5.2-authored table's raw `PapxFkp` bytes; see [ExaDev/documents.js#892](https://github.com/ExaDev/documents.js/issues/892)), matching 2.4.3's own compatibility guidance ("An application SHOULD use sprmTDefTable to define table cells for applications that do not process sprmPTableProps"). `writeDocContent` never writes an indirect Papx. |
45
- | **Hyperlinks and fields** | `ContentRun.hyperlink`, footnote/comment/annotation references, and every other field or anchor character are read as plain text or dropped (see [What is converted](#what-is-converted)) and are not written. |
46
- | **Every FIB field beyond what this package's own reader needs** | `writeDocContent` populates only the fc/lcb pairs its own reader consults (the style sheet, the two property bin tables, the Clx, the font table). Roughly 140 other `FibRgFcLcb97` pairs `SttbfAssoc`, `Dop`, the printer-driver structures among them are left zero, which is the format's own "undefined, MUST be ignored" contract for most of them, but not a certification that every third-party [MS-DOC] reader accepts the result; see `fib/write.ts`'s own note. |
35
+ | Absent | Consequence |
36
+ | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
37
+ | **Nested tables** | A table inside a table cell (table depth greater than 1) is a genuinely different [MS-DOC] structure — `sprmPFInnerTableCell`/`sprmPFInnerTtp` mark its cell/row ends rather than `sprmPFInTable`/`sprmPFTtp`, and `sprmPItap`/`sprmPDtap` state the depth. Neither side of this package descends into one: `readDocContent` refuses with `DocUnsupportedError` the moment it detects a table depth greater than 1, and `writeDocContent` refuses a `ContentTable` block found inside a table cell's own blocks the same way. See [Tables](#tables) for the full scope of what a depth-1 table does resolve. |
38
+ | **Images and drawn objects** | The anchor characters (`U+0001`, `U+0008`) are dropped rather than emitted as control characters. No picture data is read. `writeDocContent` refuses an image block. |
39
+ | **A style's own formatting on write** | A style's own property sets (`STD.grLPUpxSw`) are resolved and folded on read ([ExaDev/documents.js#1005](https://github.com/ExaDev/documents.js/issues/1005)): a paragraph's formatting is its style's own grpprlPapx/grpprlChpx (walked up the full `istdBase` inheritance chain, most-specific style winning) plus its own direct exceptions on top, and a run's own referenced character style (`sprmCIstd`) folds in the same way. `writeDocContent` mints a real STSH entry for every distinct `styleId`/`headingLevel` a document's paragraphs use ([ExaDev/documents.js#1059](https://github.com/ExaDev/documents.js/issues/1059)), so style IDENTITY round-trips -- but every minted entry carries an empty `grLPUpxSw` (no formatting of its own), since doc-codec's flat `ContentDocument` has no style-vs-direct-formatting split to draw a real one from: every property this writer emits is already, unconditionally, a direct exception. A style's own inherited formatting therefore never round-trips through a write -- only its name and istd position do. |
40
+ | **Table and numbering style formatting** | `STD.grLPUpxSw` is resolved only for paragraph and character styles (`stk` 1/2, see the row above) -- a table style's `StkTableGRLPUPX` (its own `TAPX` plus `CNFC`-conditional per-region formatting, [MS-DOC] 2.4.6.6's own table-specific steps 6-9) and a numbering style's `StkListGRLPUPX` are neither read nor written. A table applying a named table style, or a paragraph using a numbering style rather than direct list formatting, reports none of the formatting either would supply. |
41
+ | **Subdocuments** | Only the main document (character positions 0 to `ccpText`) is converted. Footnotes, endnotes, headers, footers, comments and text boxes are not, in either direction. |
42
+ | **Section boundaries** | Section boundaries themselves are not read the whole document is always treated as one section, spanning the entire main document — so a multi-section `.doc`'s later sections' own page size and margins are never consulted, only the first's (see the read-side page-size/margins bullet above for what is now read of that one section). `writeDocContent` refuses a `ContentDocument` with more than one section, rather than silently merging their content into what would read back as one. |
43
+ | **Extended and user-defined document properties** | `title`/`subject`/`author`/`keywords`/`createdIso`/`modifiedIso` are read from and written to a `"\x05SummaryInformation"` stream when present (see [Metadata](#metadata)); the sibling `"\x05DocumentSummaryInformation"` stream (company, manager, and custom user-defined properties) is not read or written at all. |
44
+ | **Encryption** | An encrypted or XOR-obfuscated document is refused with a `DocUnsupportedError` rather than read as plaintext. `writeDocContent` never encrypts. |
45
+ | **`sprmPHugePapx` / `sprmPTableProps`** | Paragraph properties stored indirectly in the Data stream are not followed, so such a paragraph reads with fewer properties than it states. [MS-DOC] 2.4.3's own Overview of Tables text names `sprmPTableProps` as a real, legal alternative to `sprmTDefTable` some applications process — but a real producer's row mark is not shown to prefer it: a genuine LibreOffice-authored `.doc` table's own row mark states its TAP through the identical direct `sprmTDefTable` this package's reader and writer already use (confirmed by parsing a LibreOffice 26.2.5.2-authored table's raw `PapxFkp` bytes; see [ExaDev/documents.js#892](https://github.com/ExaDev/documents.js/issues/892)), matching 2.4.3's own compatibility guidance ("An application SHOULD use sprmTDefTable to define table cells for applications that do not process sprmPTableProps"). `writeDocContent` never writes an indirect Papx. |
46
+ | **Hyperlinks and fields** | `ContentRun.hyperlink`, footnote/comment/annotation references, and every other field or anchor character are read as plain text or dropped (see [What is converted](#what-is-converted)) and are not written. |
47
+ | **Every FIB field beyond what this package's own reader needs** | `writeDocContent` populates only the fc/lcb pairs its own reader consults (the style sheet, the two property bin tables, the Clx, the font table). Roughly 140 other `FibRgFcLcb97` pairs — `SttbfAssoc`, `Dop`, the printer-driver structures among them — are left zero, which is the format's own "undefined, MUST be ignored" contract for most of them, but not a certification that every third-party [MS-DOC] reader accepts the result; see `fib/write.ts`'s own note. |
47
48
 
48
49
  One construct is refused rather than mis-read: a `sprmPChgTabs` whose `cb` is the `255` sentinel encodes its own length as a formula over tab-stop counts this package does not parse, and its length is needed to find the next `Prl`. Rather than guess and silently mis-read every property after it, `operandSize` throws.
49
50
 
@@ -51,15 +52,15 @@ One construct is refused rather than mis-read: a `sprmPChgTabs` whose `cb` is th
51
52
 
52
53
  Character properties, from `Chpx` grpprls:
53
54
 
54
- | Sprm | Becomes |
55
- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
56
- | `sprmCFBold` (0x0835), `sprmCFItalic` (0x0836), `sprmCFStrike` (0x0837) | `bold` / `italic` / `strike`, honouring `ToggleOperand`'s inherit (0x80) and invert (0x81) values |
57
- | `sprmCKul` (0x2A3E) | `underline` (any non-zero `Kul` style) |
58
- | `sprmCHps` (0x4A43) | `sizePt`, the operand being half-points |
59
- | `sprmCIco` (0x2A42) | `color`, through [MS-DOC] 2.9.119's fixed palette |
60
- | `sprmCCv` (0x6870) | `color`, from a `COLORREF` |
61
- | `sprmCIstd` (0x4A30) | the character style index, carried for a caller to resolve |
62
- | `sprmCRgFtc0` (0x4A4F) | `fontFamily`, looked up by index in the document's own font table (see [The font table](#the-font-table)) |
55
+ | Sprm | Becomes |
56
+ | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
57
+ | `sprmCFBold` (0x0835), `sprmCFItalic` (0x0836), `sprmCFStrike` (0x0837) | `bold` / `italic` / `strike`, honouring `ToggleOperand`'s inherit (0x80) and invert (0x81) values |
58
+ | `sprmCKul` (0x2A3E) | `underline` (any non-zero `Kul` style) |
59
+ | `sprmCHps` (0x4A43) | `sizePt`, the operand being half-points |
60
+ | `sprmCIco` (0x2A42) | `color`, through [MS-DOC] 2.9.119's fixed palette |
61
+ | `sprmCCv` (0x6870) | `color`, from a `COLORREF` |
62
+ | `sprmCIstd` (0x4A30) | resolves the named character style's own formatting and folds it in ([ExaDev/documents.js#1005](https://github.com/ExaDev/documents.js/issues/1005)), between the paragraph style's own defaults and this run's remaining direct exceptions |
63
+ | `sprmCRgFtc0` (0x4A4F) | `fontFamily`, looked up by index in the document's own font table (see [The font table](#the-font-table)) |
63
64
 
64
65
  Paragraph properties, from `PapxInFkp` grpprls:
65
66
 
@@ -171,7 +172,7 @@ Only the fixed SummaryInformation property set is read or written — the siblin
171
172
 
172
173
  ## Writing
173
174
 
174
- `writeDocContent` takes a `'wordprocessing'` `ContentDocument` with exactly one section, an optional `WriteDocContentOptions`, and produces real [MS-DOC] bytes wrapped in a real [MS-CFB] compound file, inverting every read-side structure listed above: a real piece table (`text/piece-table-write.ts`, always one uncompressed 16-bit piece — see [Why always uncompressed](#why-the-writer-always-writes-uncompressed-text)), `Sprm`-encoded grpprls for each run's and paragraph's own direct formatting (`prop/chp-write.ts`, `prop/pap-write.ts`), `ChpxFkp`/`PapxFkp` pages packed and split across as many 512-byte pages as the content needs (`prop/fkp-write.ts`), a spec-conformant style sheet carrying zero styles (`style/stsh.ts`'s `buildEmptyStsh` — `FibRgFcLcb97.lcbStshf` "MUST be a nonzero value", so a document is never written without one, even though this package's own reader tolerates a missing one), and a font table when at least one run names a font (`style/fonts.ts`). `WriteDocContentOptions.onWarning`, when given, is called for a non-fatal write-time degradation this writer chooses over throwing — today, only the lost-boundary fallback's own per-row budget check (see [Tables](#tables)'s own note on [ExaDev/documents.js#1013](https://github.com/ExaDev/documents.js/issues/1013)) — but that is not a guarantee the write itself goes on to succeed: a row whose own assigned lost boundaries cannot be trimmed down to a split that fits at all still reports one warning, describing its boundaries as unrecoverable and its fully-unsplit encoding as the fallback being attempted — and, should that unsplit encoding also overflow the row's own byte budget once `buildPapxPages` actually packs it, `writeDocContent` can still throw further down the same pipeline, after any rows still to come have had their own chance to report a warning: a caller can genuinely see this warning followed by a hard failure, but not necessarily right away, and not necessarily for the row whose warning it just read, since `buildPapxPages` packs paragraphs in document order and can fail first on an earlier row that also overflowed. Every genuine refusal this writer makes outright — the kinds named in the table below — still throws `DocFormatError`/`DocUnsupportedError` directly, with no warning first.
175
+ `writeDocContent` takes a `'wordprocessing'` `ContentDocument` with exactly one section, an optional `WriteDocContentOptions`, and produces real [MS-DOC] bytes wrapped in a real [MS-CFB] compound file, inverting every read-side structure listed above: a real piece table (`text/piece-table-write.ts`, always one uncompressed 16-bit piece — see [Why always uncompressed](#why-the-writer-always-writes-uncompressed-text)), `Sprm`-encoded grpprls for each run's and paragraph's own direct formatting (`prop/chp-write.ts`, `prop/pap-write.ts`), `ChpxFkp`/`PapxFkp` pages packed and split across as many 512-byte pages as the content needs (`prop/fkp-write.ts`), a real style sheet minting one entry per distinct `styleId`/`headingLevel` a document's paragraphs actually use (`style/stsh.ts`'s `buildStshForStyles`, [ExaDev/documents.js#1059](https://github.com/ExaDev/documents.js/issues/1059) identity only, no formatting of a style's own; `FibRgFcLcb97.lcbStshf` "MUST be a nonzero value", so a document is never written without one, even one carrying zero styles, though this package's own reader tolerates a missing one), and a font table when at least one run names a font (`style/fonts.ts`). `WriteDocContentOptions.onWarning`, when given, is called for a non-fatal write-time degradation this writer chooses over throwing — today, only the lost-boundary fallback's own per-row budget check (see [Tables](#tables)'s own note on [ExaDev/documents.js#1013](https://github.com/ExaDev/documents.js/issues/1013)) — but that is not a guarantee the write itself goes on to succeed: a row whose own assigned lost boundaries cannot be trimmed down to a split that fits at all still reports one warning, describing its boundaries as unrecoverable and its fully-unsplit encoding as the fallback being attempted — and, should that unsplit encoding also overflow the row's own byte budget once `buildPapxPages` actually packs it, `writeDocContent` can still throw further down the same pipeline, after any rows still to come have had their own chance to report a warning: a caller can genuinely see this warning followed by a hard failure, but not necessarily right away, and not necessarily for the row whose warning it just read, since `buildPapxPages` packs paragraphs in document order and can fail first on an earlier row that also overflowed. Every genuine refusal this writer makes outright — the kinds named in the table below — still throws `DocFormatError`/`DocUnsupportedError` directly, with no warning first.
175
176
 
176
177
  Character properties this writer converts, the exact inverse of [What is converted](#what-is-converted)'s character table above: `bold`, `italic`, `strike`, `underline` (as `kulSingle`, the only style a plain boolean can express), `sizePt`, `color` (via `sprmCCv`'s exact `COLORREF`, never the lossy 17-entry `sprmCIco` palette), and `fontFamily`. Paragraph properties: `alignment` (the four `ST_Jc`-aligned values this package's reader itself maps — `left`/`center`/`right`/`justify`), `indentLeftPt`, `indentRightPt`, `indentFirstLinePt`, `spacingBeforePt`, `spacingAfterPt`, `lineSpacing` (only `LSPD`'s multiplier form, matching the reader), `pageBreakBefore`, and `list` membership (`sprmPIlfo`/`sprmPIlvl` — see [Numbering definitions](#numbering-definitions) for the numbering tables this depends on).
177
178
 
@@ -219,7 +220,7 @@ The modules layer in the order [MS-DOC]'s own algorithms chain:
219
220
  | `src/prop/fkp.ts` | The formatted disk pages and the bin tables that address them. |
220
221
  | `src/prop/chp.ts`, `src/prop/pap.ts` | Folding a grpprl into character and paragraph properties. |
221
222
  | `src/list/numbering.ts` | Resolving `PlfLst`/`PlfLfo` into `NumberingDefinitions` (see [Numbering definitions](#numbering-definitions)). |
222
- | `src/style/stsh.ts` | The style sheet. |
223
+ | `src/style/stsh.ts` | The style sheet, plus resolving a style's own inherited formatting up its `istdBase` chain. |
223
224
  | `src/style/fonts.ts` | The font table (`SttbfFfn`/`FFN`) — read and write together, since both directions share one small, self-contained field layout. |
224
225
  | `src/metadata.ts` | Wraps `archive-codec`'s own `SummaryInformationProperties` <-> `LayoutMetadata` mapping with this package's `createdIso`/`modifiedIso` date validation, throwing `DocFormatError` for a malformed one rather than letting an opaque `RangeError` escape the FILETIME conversion (see [Metadata](#metadata)). |
225
226
  | `src/table/decoration.ts` | A cell's border and background-shading encodings -- `Brc80`, `Brc`, `Shd`, `Shd80`, and the `BrcType`/`Ipat` vocabularies -- read and written in one place, so neither direction can drift from the other (see [Cell decoration](#cell-decoration)). |
package/dist/index.cjs CHANGED
@@ -66,14 +66,15 @@ exports.applyCharacterSprms = require_prop_chp.applyCharacterSprms;
66
66
  exports.applyParagraphSprms = require_prop_pap.applyParagraphSprms;
67
67
  exports.applySectionSprms = require_prop_sep.applySectionSprms;
68
68
  exports.buildChpxPages = require_prop_fkp_write.buildChpxPages;
69
- exports.buildEmptyStsh = require_style_stsh.buildEmptyStsh;
70
69
  exports.buildFib = require_fib_write.buildFib;
71
70
  exports.buildFontTable = require_style_fonts.buildFontTable;
72
71
  exports.buildPapxPages = require_prop_fkp_write.buildPapxPages;
73
72
  exports.buildPlcfSed = require_prop_sep_write.buildPlcfSed;
74
73
  exports.buildPropertyBinTable = require_prop_fkp_write.buildPropertyBinTable;
75
74
  exports.buildSepx = require_prop_sep_write.buildSepx;
75
+ exports.buildStshForStyles = require_style_stsh.buildStshForStyles;
76
76
  exports.buildTextClx = require_text_piece_table_write.buildTextClx;
77
+ exports.characterIstdFromGrpprl = require_prop_chp.characterIstdFromGrpprl;
77
78
  exports.characterOffset = require_text_piece_table.characterOffset;
78
79
  exports.characterSize = require_text_piece_table.characterSize;
79
80
  exports.decodeSprm = require_prop_sprm.decodeSprm;
@@ -107,6 +108,7 @@ exports.readTextRange = require_text_characters.readTextRange;
107
108
  exports.readUint16LE = require_bytes.readUint16LE;
108
109
  exports.readUint32LE = require_bytes.readUint32LE;
109
110
  exports.readUint8 = require_bytes.readUint8;
111
+ exports.resolveStyleFormatting = require_style_stsh.resolveStyleFormatting;
110
112
  exports.slice = require_bytes.slice;
111
113
  exports.tableStreamName = require_fib_fib.tableStreamName;
112
114
  exports.writeDocContent = require_write.writeDocContent;
package/dist/index.d.cts CHANGED
@@ -13,15 +13,15 @@ import { ANNOTATION_REFERENCE, CELL_MARK, DRAWN_OBJECT, FIELD_BEGIN, FIELD_END,
13
13
  import { a as operandSize, i as decodeSprm, n as SGC, o as readGrpprl, r as Sprm, t as Prl } from "./sprm-DEyvdOo0.cjs";
14
14
  import { ChpxFkp, FKP_PAGE_SIZE, PapxFkp, PapxLookup, PapxRecord, PropertyBinTable, parseChpxFkp, parsePapxFkp } from "./prop/fkp.cjs";
15
15
  import { ChpxRunToWrite, PapxParagraphToWrite, buildChpxPages, buildPapxPages, buildPropertyBinTable, firstFcOfPage, fitsAloneOnPapxPage } from "./prop/fkp-write.cjs";
16
- import { CharacterProperties, applyCharacterSprms } from "./prop/chp.cjs";
16
+ import { CharacterProperties, applyCharacterSprms, characterIstdFromGrpprl } from "./prop/chp.cjs";
17
17
  import { encodeCharacterGrpprl } from "./prop/chp-write.cjs";
18
18
  import { n as applyParagraphSprms, t as ParagraphProperties } from "./pap-BT1p0uzu.cjs";
19
19
  import { encodeParagraphGrpprl } from "./prop/pap-write.cjs";
20
20
  import { SectionProperties, applySectionSprms, readSectionProperties } from "./prop/sep.cjs";
21
21
  import { buildPlcfSed, buildSepx, encodeSectionGrpprl } from "./prop/sep-write.cjs";
22
- import { STI_USER_DEFINED, STK, Style, StyleSheet, buildEmptyStsh, headingLevelFromIstd, parseStsh } from "./style/stsh.cjs";
22
+ import { ResolvedStyleFormatting, STI_USER_DEFINED, STK, Style, StyleSheet, buildStshForStyles, headingLevelFromIstd, parseStsh, resolveStyleFormatting } from "./style/stsh.cjs";
23
23
  import { buildFontTable, parseFontTable } from "./style/fonts.cjs";
24
24
  import { a as readNumberingDefinitions, i as NumberingLevel, n as NumberingDefinition, r as NumberingDefinitions, t as NUMBER_FORMAT_BY_NFC } from "./numbering-Bivayss4.cjs";
25
25
  import { DocContent, DocStreams, ParagraphEntry, readDocContent, readDocStreams } from "./read.cjs";
26
26
  import { WriteDocContentOptions, writeDocContent } from "./write.cjs";
27
- export { ANNOTATION_REFERENCE, CELL_MARK, COMPRESSED_CHARACTER_MAP, CharacterProperties, ChpxFkp, ChpxRunToWrite, DRAWN_OBJECT, DocContent, DocFormatError, DocStreams, DocUnsupportedError, FC_LCB_VALUE_INDEX, FIB_BASE_FLAG, FIB_BASE_SIZE, FIB_CB_RG_FC_LCB_OFFSET, FIB_CSLW_OFFSET, FIB_CSLW_REQUIRED, FIB_CSW_REQUIRED, FIB_FC_LCB_BLOB_OFFSET, FIB_RG_LW_OFFSET, FIB_RG_LW_SIZE, FIB_RG_W_OFFSET, FIB_RG_W_SIZE, FIB_W_IDENT, FIELD_BEGIN, FIELD_END, FIELD_SEPARATOR, FKP_PAGE_SIZE, FOOTNOTE_REFERENCE, Fib, FibWriteSpec, INLINE_PICTURE, LINE_BREAK, LW_OFFSET, NUMBER_FORMAT_BY_NFC, NumberingDefinition, NumberingDefinitions, NumberingLevel, PARAGRAPH_MARK, PapxFkp, PapxLookup, PapxParagraphToWrite, PapxRecord, ParagraphEntry, ParagraphProperties, Piece, PieceTable, Plc, Prl, PropertyBinTable, SECTION_MARK, SGC, STI_USER_DEFINED, STK, SUMMARY_INFORMATION_STREAM, SYMBOL_ANCHOR, SectionProperties, Sprm, Style, StyleSheet, TextRange, WORD_DOCUMENT_STREAM, WriteDocContentOptions, applyCharacterSprms, applyParagraphSprms, applySectionSprms, buildChpxPages, buildEmptyStsh, buildFib, buildFontTable, buildPapxPages, buildPlcfSed, buildPropertyBinTable, buildSepx, buildTextClx, characterOffset, characterSize, decodeSprm, encodeCharacterGrpprl, encodeParagraphGrpprl, encodeSectionGrpprl, endsParagraph, findLargestAtMost, firstFcOfPage, fitsAloneOnPapxPage, headingLevelFromIstd, isAnchorOnly, isDocBytes, layoutMetadataToSummaryInformation, operandSize, parseChpxFkp, parseClx, parseFib, parseFontTable, parsePapxFkp, parsePlc, parseStsh, readDocContent, readDocStreams, readGrpprl, readInt16LE, readInt32LE, readNumberingDefinitions, readSectionProperties, readTextRange, readUint16LE, readUint32LE, readUint8, slice, tableStreamName, writeDocContent };
27
+ export { ANNOTATION_REFERENCE, CELL_MARK, COMPRESSED_CHARACTER_MAP, CharacterProperties, ChpxFkp, ChpxRunToWrite, DRAWN_OBJECT, DocContent, DocFormatError, DocStreams, DocUnsupportedError, FC_LCB_VALUE_INDEX, FIB_BASE_FLAG, FIB_BASE_SIZE, FIB_CB_RG_FC_LCB_OFFSET, FIB_CSLW_OFFSET, FIB_CSLW_REQUIRED, FIB_CSW_REQUIRED, FIB_FC_LCB_BLOB_OFFSET, FIB_RG_LW_OFFSET, FIB_RG_LW_SIZE, FIB_RG_W_OFFSET, FIB_RG_W_SIZE, FIB_W_IDENT, FIELD_BEGIN, FIELD_END, FIELD_SEPARATOR, FKP_PAGE_SIZE, FOOTNOTE_REFERENCE, Fib, FibWriteSpec, INLINE_PICTURE, LINE_BREAK, LW_OFFSET, NUMBER_FORMAT_BY_NFC, NumberingDefinition, NumberingDefinitions, NumberingLevel, PARAGRAPH_MARK, PapxFkp, PapxLookup, PapxParagraphToWrite, PapxRecord, ParagraphEntry, ParagraphProperties, Piece, PieceTable, Plc, Prl, PropertyBinTable, ResolvedStyleFormatting, SECTION_MARK, SGC, STI_USER_DEFINED, STK, SUMMARY_INFORMATION_STREAM, SYMBOL_ANCHOR, SectionProperties, Sprm, Style, StyleSheet, TextRange, WORD_DOCUMENT_STREAM, WriteDocContentOptions, applyCharacterSprms, applyParagraphSprms, applySectionSprms, buildChpxPages, buildFib, buildFontTable, buildPapxPages, buildPlcfSed, buildPropertyBinTable, buildSepx, buildStshForStyles, buildTextClx, characterIstdFromGrpprl, characterOffset, characterSize, decodeSprm, encodeCharacterGrpprl, encodeParagraphGrpprl, encodeSectionGrpprl, endsParagraph, findLargestAtMost, firstFcOfPage, fitsAloneOnPapxPage, headingLevelFromIstd, isAnchorOnly, isDocBytes, layoutMetadataToSummaryInformation, operandSize, parseChpxFkp, parseClx, parseFib, parseFontTable, parsePapxFkp, parsePlc, parseStsh, readDocContent, readDocStreams, readGrpprl, readInt16LE, readInt32LE, readNumberingDefinitions, readSectionProperties, readTextRange, readUint16LE, readUint32LE, readUint8, resolveStyleFormatting, slice, tableStreamName, writeDocContent };
package/dist/index.d.ts CHANGED
@@ -13,15 +13,15 @@ import { ANNOTATION_REFERENCE, CELL_MARK, DRAWN_OBJECT, FIELD_BEGIN, FIELD_END,
13
13
  import { a as operandSize, i as decodeSprm, n as SGC, o as readGrpprl, r as Sprm, t as Prl } from "./sprm-DEyvdOo0.js";
14
14
  import { ChpxFkp, FKP_PAGE_SIZE, PapxFkp, PapxLookup, PapxRecord, PropertyBinTable, parseChpxFkp, parsePapxFkp } from "./prop/fkp.js";
15
15
  import { ChpxRunToWrite, PapxParagraphToWrite, buildChpxPages, buildPapxPages, buildPropertyBinTable, firstFcOfPage, fitsAloneOnPapxPage } from "./prop/fkp-write.js";
16
- import { CharacterProperties, applyCharacterSprms } from "./prop/chp.js";
16
+ import { CharacterProperties, applyCharacterSprms, characterIstdFromGrpprl } from "./prop/chp.js";
17
17
  import { encodeCharacterGrpprl } from "./prop/chp-write.js";
18
18
  import { n as applyParagraphSprms, t as ParagraphProperties } from "./pap-DOFLMWcG.js";
19
19
  import { encodeParagraphGrpprl } from "./prop/pap-write.js";
20
20
  import { SectionProperties, applySectionSprms, readSectionProperties } from "./prop/sep.js";
21
21
  import { buildPlcfSed, buildSepx, encodeSectionGrpprl } from "./prop/sep-write.js";
22
- import { STI_USER_DEFINED, STK, Style, StyleSheet, buildEmptyStsh, headingLevelFromIstd, parseStsh } from "./style/stsh.js";
22
+ import { ResolvedStyleFormatting, STI_USER_DEFINED, STK, Style, StyleSheet, buildStshForStyles, headingLevelFromIstd, parseStsh, resolveStyleFormatting } from "./style/stsh.js";
23
23
  import { buildFontTable, parseFontTable } from "./style/fonts.js";
24
24
  import { a as readNumberingDefinitions, i as NumberingLevel, n as NumberingDefinition, r as NumberingDefinitions, t as NUMBER_FORMAT_BY_NFC } from "./numbering-Co4jssbG.js";
25
25
  import { DocContent, DocStreams, ParagraphEntry, readDocContent, readDocStreams } from "./read.js";
26
26
  import { WriteDocContentOptions, writeDocContent } from "./write.js";
27
- export { ANNOTATION_REFERENCE, CELL_MARK, COMPRESSED_CHARACTER_MAP, CharacterProperties, ChpxFkp, ChpxRunToWrite, DRAWN_OBJECT, DocContent, DocFormatError, DocStreams, DocUnsupportedError, FC_LCB_VALUE_INDEX, FIB_BASE_FLAG, FIB_BASE_SIZE, FIB_CB_RG_FC_LCB_OFFSET, FIB_CSLW_OFFSET, FIB_CSLW_REQUIRED, FIB_CSW_REQUIRED, FIB_FC_LCB_BLOB_OFFSET, FIB_RG_LW_OFFSET, FIB_RG_LW_SIZE, FIB_RG_W_OFFSET, FIB_RG_W_SIZE, FIB_W_IDENT, FIELD_BEGIN, FIELD_END, FIELD_SEPARATOR, FKP_PAGE_SIZE, FOOTNOTE_REFERENCE, Fib, FibWriteSpec, INLINE_PICTURE, LINE_BREAK, LW_OFFSET, NUMBER_FORMAT_BY_NFC, NumberingDefinition, NumberingDefinitions, NumberingLevel, PARAGRAPH_MARK, PapxFkp, PapxLookup, PapxParagraphToWrite, PapxRecord, ParagraphEntry, ParagraphProperties, Piece, PieceTable, Plc, Prl, PropertyBinTable, SECTION_MARK, SGC, STI_USER_DEFINED, STK, SUMMARY_INFORMATION_STREAM, SYMBOL_ANCHOR, SectionProperties, Sprm, Style, StyleSheet, TextRange, WORD_DOCUMENT_STREAM, WriteDocContentOptions, applyCharacterSprms, applyParagraphSprms, applySectionSprms, buildChpxPages, buildEmptyStsh, buildFib, buildFontTable, buildPapxPages, buildPlcfSed, buildPropertyBinTable, buildSepx, buildTextClx, characterOffset, characterSize, decodeSprm, encodeCharacterGrpprl, encodeParagraphGrpprl, encodeSectionGrpprl, endsParagraph, findLargestAtMost, firstFcOfPage, fitsAloneOnPapxPage, headingLevelFromIstd, isAnchorOnly, isDocBytes, layoutMetadataToSummaryInformation, operandSize, parseChpxFkp, parseClx, parseFib, parseFontTable, parsePapxFkp, parsePlc, parseStsh, readDocContent, readDocStreams, readGrpprl, readInt16LE, readInt32LE, readNumberingDefinitions, readSectionProperties, readTextRange, readUint16LE, readUint32LE, readUint8, slice, tableStreamName, writeDocContent };
27
+ export { ANNOTATION_REFERENCE, CELL_MARK, COMPRESSED_CHARACTER_MAP, CharacterProperties, ChpxFkp, ChpxRunToWrite, DRAWN_OBJECT, DocContent, DocFormatError, DocStreams, DocUnsupportedError, FC_LCB_VALUE_INDEX, FIB_BASE_FLAG, FIB_BASE_SIZE, FIB_CB_RG_FC_LCB_OFFSET, FIB_CSLW_OFFSET, FIB_CSLW_REQUIRED, FIB_CSW_REQUIRED, FIB_FC_LCB_BLOB_OFFSET, FIB_RG_LW_OFFSET, FIB_RG_LW_SIZE, FIB_RG_W_OFFSET, FIB_RG_W_SIZE, FIB_W_IDENT, FIELD_BEGIN, FIELD_END, FIELD_SEPARATOR, FKP_PAGE_SIZE, FOOTNOTE_REFERENCE, Fib, FibWriteSpec, INLINE_PICTURE, LINE_BREAK, LW_OFFSET, NUMBER_FORMAT_BY_NFC, NumberingDefinition, NumberingDefinitions, NumberingLevel, PARAGRAPH_MARK, PapxFkp, PapxLookup, PapxParagraphToWrite, PapxRecord, ParagraphEntry, ParagraphProperties, Piece, PieceTable, Plc, Prl, PropertyBinTable, ResolvedStyleFormatting, SECTION_MARK, SGC, STI_USER_DEFINED, STK, SUMMARY_INFORMATION_STREAM, SYMBOL_ANCHOR, SectionProperties, Sprm, Style, StyleSheet, TextRange, WORD_DOCUMENT_STREAM, WriteDocContentOptions, applyCharacterSprms, applyParagraphSprms, applySectionSprms, buildChpxPages, buildFib, buildFontTable, buildPapxPages, buildPlcfSed, buildPropertyBinTable, buildSepx, buildStshForStyles, buildTextClx, characterIstdFromGrpprl, characterOffset, characterSize, decodeSprm, encodeCharacterGrpprl, encodeParagraphGrpprl, encodeSectionGrpprl, endsParagraph, findLargestAtMost, firstFcOfPage, fitsAloneOnPapxPage, headingLevelFromIstd, isAnchorOnly, isDocBytes, layoutMetadataToSummaryInformation, operandSize, parseChpxFkp, parseClx, parseFib, parseFontTable, parsePapxFkp, parsePlc, parseStsh, readDocContent, readDocStreams, readGrpprl, readInt16LE, readInt32LE, readNumberingDefinitions, readSectionProperties, readTextRange, readUint16LE, readUint32LE, readUint8, resolveStyleFormatting, slice, tableStreamName, writeDocContent };
package/dist/index.js CHANGED
@@ -13,15 +13,15 @@ import { ANNOTATION_REFERENCE, CELL_MARK, DRAWN_OBJECT, FIELD_BEGIN, FIELD_END,
13
13
  import { SGC, decodeSprm, operandSize, readGrpprl } from "./prop/sprm.js";
14
14
  import { FKP_PAGE_SIZE, PropertyBinTable, parseChpxFkp, parsePapxFkp } from "./prop/fkp.js";
15
15
  import { buildChpxPages, buildPapxPages, buildPropertyBinTable, firstFcOfPage, fitsAloneOnPapxPage } from "./prop/fkp-write.js";
16
- import { applyCharacterSprms } from "./prop/chp.js";
16
+ import { applyCharacterSprms, characterIstdFromGrpprl } from "./prop/chp.js";
17
17
  import { encodeCharacterGrpprl } from "./prop/chp-write.js";
18
18
  import { applyParagraphSprms } from "./prop/pap.js";
19
19
  import { encodeParagraphGrpprl } from "./prop/pap-write.js";
20
20
  import { applySectionSprms, readSectionProperties } from "./prop/sep.js";
21
21
  import { buildPlcfSed, buildSepx, encodeSectionGrpprl } from "./prop/sep-write.js";
22
- import { STI_USER_DEFINED, STK, buildEmptyStsh, headingLevelFromIstd, parseStsh } from "./style/stsh.js";
22
+ import { STI_USER_DEFINED, STK, buildStshForStyles, headingLevelFromIstd, parseStsh, resolveStyleFormatting } from "./style/stsh.js";
23
23
  import { buildFontTable, parseFontTable } from "./style/fonts.js";
24
24
  import { NUMBER_FORMAT_BY_NFC, readNumberingDefinitions } from "./list/numbering.js";
25
25
  import { readDocContent, readDocStreams } from "./read.js";
26
26
  import { writeDocContent } from "./write.js";
27
- export { ANNOTATION_REFERENCE, CELL_MARK, COMPRESSED_CHARACTER_MAP, DRAWN_OBJECT, DocFormatError, DocUnsupportedError, FC_LCB_VALUE_INDEX, FIB_BASE_FLAG, FIB_BASE_SIZE, FIB_CB_RG_FC_LCB_OFFSET, FIB_CSLW_OFFSET, FIB_CSLW_REQUIRED, FIB_CSW_REQUIRED, FIB_FC_LCB_BLOB_OFFSET, FIB_RG_LW_OFFSET, FIB_RG_LW_SIZE, FIB_RG_W_OFFSET, FIB_RG_W_SIZE, FIB_W_IDENT, FIELD_BEGIN, FIELD_END, FIELD_SEPARATOR, FKP_PAGE_SIZE, FOOTNOTE_REFERENCE, INLINE_PICTURE, LINE_BREAK, LW_OFFSET, NUMBER_FORMAT_BY_NFC, PARAGRAPH_MARK, PropertyBinTable, SECTION_MARK, SGC, STI_USER_DEFINED, STK, SUMMARY_INFORMATION_STREAM, SYMBOL_ANCHOR, WORD_DOCUMENT_STREAM, applyCharacterSprms, applyParagraphSprms, applySectionSprms, buildChpxPages, buildEmptyStsh, buildFib, buildFontTable, buildPapxPages, buildPlcfSed, buildPropertyBinTable, buildSepx, buildTextClx, characterOffset, characterSize, decodeSprm, encodeCharacterGrpprl, encodeParagraphGrpprl, encodeSectionGrpprl, endsParagraph, findLargestAtMost, firstFcOfPage, fitsAloneOnPapxPage, headingLevelFromIstd, isAnchorOnly, isDocBytes, layoutMetadataToSummaryInformation, operandSize, parseChpxFkp, parseClx, parseFib, parseFontTable, parsePapxFkp, parsePlc, parseStsh, readDocContent, readDocStreams, readGrpprl, readInt16LE, readInt32LE, readNumberingDefinitions, readSectionProperties, readTextRange, readUint16LE, readUint32LE, readUint8, slice, tableStreamName, writeDocContent };
27
+ export { ANNOTATION_REFERENCE, CELL_MARK, COMPRESSED_CHARACTER_MAP, DRAWN_OBJECT, DocFormatError, DocUnsupportedError, FC_LCB_VALUE_INDEX, FIB_BASE_FLAG, FIB_BASE_SIZE, FIB_CB_RG_FC_LCB_OFFSET, FIB_CSLW_OFFSET, FIB_CSLW_REQUIRED, FIB_CSW_REQUIRED, FIB_FC_LCB_BLOB_OFFSET, FIB_RG_LW_OFFSET, FIB_RG_LW_SIZE, FIB_RG_W_OFFSET, FIB_RG_W_SIZE, FIB_W_IDENT, FIELD_BEGIN, FIELD_END, FIELD_SEPARATOR, FKP_PAGE_SIZE, FOOTNOTE_REFERENCE, INLINE_PICTURE, LINE_BREAK, LW_OFFSET, NUMBER_FORMAT_BY_NFC, PARAGRAPH_MARK, PropertyBinTable, SECTION_MARK, SGC, STI_USER_DEFINED, STK, SUMMARY_INFORMATION_STREAM, SYMBOL_ANCHOR, WORD_DOCUMENT_STREAM, applyCharacterSprms, applyParagraphSprms, applySectionSprms, buildChpxPages, buildFib, buildFontTable, buildPapxPages, buildPlcfSed, buildPropertyBinTable, buildSepx, buildStshForStyles, buildTextClx, characterIstdFromGrpprl, characterOffset, characterSize, decodeSprm, encodeCharacterGrpprl, encodeParagraphGrpprl, encodeSectionGrpprl, endsParagraph, findLargestAtMost, firstFcOfPage, fitsAloneOnPapxPage, headingLevelFromIstd, isAnchorOnly, isDocBytes, layoutMetadataToSummaryInformation, operandSize, parseChpxFkp, parseClx, parseFib, parseFontTable, parsePapxFkp, parsePlc, parseStsh, readDocContent, readDocStreams, readGrpprl, readInt16LE, readInt32LE, readNumberingDefinitions, readSectionProperties, readTextRange, readUint16LE, readUint32LE, readUint8, resolveStyleFormatting, slice, tableStreamName, writeDocContent };
package/dist/prop/chp.cjs CHANGED
@@ -76,5 +76,11 @@ function applyCharacterSprms(prls, into, fonts) {
76
76
  }
77
77
  return into;
78
78
  }
79
+ function characterIstdFromGrpprl(prls) {
80
+ let istd;
81
+ for (const prl of prls) if (prl.sprm.sgc === require_prop_sprm.SGC.character && prl.sprm.value === SPRM_C_ISTD) istd = require_bytes.readUint16LE(prl.operand, 0);
82
+ return istd;
83
+ }
79
84
  //#endregion
80
85
  exports.applyCharacterSprms = applyCharacterSprms;
86
+ exports.characterIstdFromGrpprl = characterIstdFromGrpprl;
@@ -13,5 +13,6 @@ interface CharacterProperties {
13
13
  istd?: number;
14
14
  }
15
15
  declare function applyCharacterSprms(prls: readonly Prl[], into: CharacterProperties, fonts?: readonly string[]): CharacterProperties;
16
+ declare function characterIstdFromGrpprl(prls: readonly Prl[]): number | undefined;
16
17
  //#endregion
17
- export { CharacterProperties, applyCharacterSprms };
18
+ export { CharacterProperties, applyCharacterSprms, characterIstdFromGrpprl };
@@ -13,5 +13,6 @@ interface CharacterProperties {
13
13
  istd?: number;
14
14
  }
15
15
  declare function applyCharacterSprms(prls: readonly Prl[], into: CharacterProperties, fonts?: readonly string[]): CharacterProperties;
16
+ declare function characterIstdFromGrpprl(prls: readonly Prl[]): number | undefined;
16
17
  //#endregion
17
- export { CharacterProperties, applyCharacterSprms };
18
+ export { CharacterProperties, applyCharacterSprms, characterIstdFromGrpprl };
package/dist/prop/chp.js CHANGED
@@ -75,5 +75,10 @@ function applyCharacterSprms(prls, into, fonts) {
75
75
  }
76
76
  return into;
77
77
  }
78
+ function characterIstdFromGrpprl(prls) {
79
+ let istd;
80
+ for (const prl of prls) if (prl.sprm.sgc === SGC.character && prl.sprm.value === SPRM_C_ISTD) istd = readUint16LE(prl.operand, 0);
81
+ return istd;
82
+ }
78
83
  //#endregion
79
- export { applyCharacterSprms };
84
+ export { applyCharacterSprms, characterIstdFromGrpprl };
package/dist/read.cjs CHANGED
@@ -105,12 +105,13 @@ function buildParagraph(text, fcs, propertyFc, terminator, context) {
105
105
  const grpprl = papx !== void 0 ? require_prop_sprm.readGrpprl(papx.grpprl) : [];
106
106
  if (papx !== void 0) {
107
107
  properties.istd = papx.istd;
108
+ if (context.styles !== void 0) require_prop_pap.applyParagraphSprms(require_style_stsh.resolveStyleFormatting(context.styles, papx.istd).paragraphPrls, properties);
108
109
  require_prop_pap.applyParagraphSprms(grpprl, properties);
109
110
  }
110
111
  return {
111
112
  paragraph: {
112
113
  kind: "paragraph",
113
- runs: buildRuns(text, fcs, context),
114
+ runs: buildRuns(text, fcs, context, papx?.istd),
114
115
  ...paragraphAttributes(properties, context)
115
116
  },
116
117
  properties,
@@ -142,11 +143,12 @@ function paragraphAttributes(properties, context) {
142
143
  };
143
144
  return attributes;
144
145
  }
145
- function buildRuns(text, fcs, context) {
146
+ function buildRuns(text, fcs, context, paragraphIstd) {
146
147
  const runs = [];
147
148
  let currentKey;
148
149
  let currentText = "";
149
150
  let currentProperties = {};
151
+ const paragraphStyleCharacterPrls = context.styles !== void 0 && paragraphIstd !== void 0 ? require_style_stsh.resolveStyleFormatting(context.styles, paragraphIstd).characterPrls : [];
150
152
  const enclosingInstruction = [];
151
153
  let inInstruction = false;
152
154
  const flush = () => {
@@ -176,14 +178,21 @@ function buildRuns(text, fcs, context) {
176
178
  const fc = fcs[index];
177
179
  if (fc === void 0) throw new require_errors.DocFormatError(`character ${index} of a paragraph has no byte offset, so its formatting cannot be located`);
178
180
  const grpprl = context.chpxTable.chpxGrpprl(fc);
179
- const key = grpprl === void 0 ? "none" : `${grpprl.byteOffset}:${grpprl.byteLength}`;
181
+ const chpxKey = grpprl === void 0 ? "none" : `${grpprl.byteOffset}:${grpprl.byteLength}`;
182
+ const key = `${paragraphIstd ?? "none"}:${chpxKey}`;
180
183
  if (key !== currentKey) {
181
184
  flush();
182
185
  currentKey = key;
183
186
  let properties = context.characterProperties.get(key);
184
187
  if (properties === void 0) {
185
188
  properties = {};
186
- if (grpprl !== void 0) require_prop_chp.applyCharacterSprms(require_prop_sprm.readGrpprl(grpprl), properties, context.fonts);
189
+ require_prop_chp.applyCharacterSprms(paragraphStyleCharacterPrls, properties, context.fonts);
190
+ if (grpprl !== void 0) {
191
+ const runPrls = require_prop_sprm.readGrpprl(grpprl);
192
+ const characterIstd = require_prop_chp.characterIstdFromGrpprl(runPrls);
193
+ if (characterIstd !== void 0 && context.styles !== void 0) require_prop_chp.applyCharacterSprms(require_style_stsh.resolveStyleFormatting(context.styles, characterIstd).characterPrls, properties, context.fonts);
194
+ require_prop_chp.applyCharacterSprms(runPrls, properties, context.fonts);
195
+ }
187
196
  context.characterProperties.set(key, properties);
188
197
  }
189
198
  currentProperties = properties;
package/dist/read.js CHANGED
@@ -7,10 +7,10 @@ import { readTextRange } from "./text/characters.js";
7
7
  import { endsParagraph, isAnchorOnly } from "./text/special.js";
8
8
  import { readGrpprl } from "./prop/sprm.js";
9
9
  import { PropertyBinTable } from "./prop/fkp.js";
10
- import { applyCharacterSprms } from "./prop/chp.js";
10
+ import { applyCharacterSprms, characterIstdFromGrpprl } from "./prop/chp.js";
11
11
  import { applyParagraphSprms } from "./prop/pap.js";
12
12
  import { readSectionProperties } from "./prop/sep.js";
13
- import { headingLevelFromIstd, parseStsh } from "./style/stsh.js";
13
+ import { headingLevelFromIstd, parseStsh, resolveStyleFormatting } from "./style/stsh.js";
14
14
  import { parseFontTable } from "./style/fonts.js";
15
15
  import { readNumberingDefinitions } from "./list/numbering.js";
16
16
  import { assembleBlocks } from "./table/read.js";
@@ -104,12 +104,13 @@ function buildParagraph(text, fcs, propertyFc, terminator, context) {
104
104
  const grpprl = papx !== void 0 ? readGrpprl(papx.grpprl) : [];
105
105
  if (papx !== void 0) {
106
106
  properties.istd = papx.istd;
107
+ if (context.styles !== void 0) applyParagraphSprms(resolveStyleFormatting(context.styles, papx.istd).paragraphPrls, properties);
107
108
  applyParagraphSprms(grpprl, properties);
108
109
  }
109
110
  return {
110
111
  paragraph: {
111
112
  kind: "paragraph",
112
- runs: buildRuns(text, fcs, context),
113
+ runs: buildRuns(text, fcs, context, papx?.istd),
113
114
  ...paragraphAttributes(properties, context)
114
115
  },
115
116
  properties,
@@ -141,11 +142,12 @@ function paragraphAttributes(properties, context) {
141
142
  };
142
143
  return attributes;
143
144
  }
144
- function buildRuns(text, fcs, context) {
145
+ function buildRuns(text, fcs, context, paragraphIstd) {
145
146
  const runs = [];
146
147
  let currentKey;
147
148
  let currentText = "";
148
149
  let currentProperties = {};
150
+ const paragraphStyleCharacterPrls = context.styles !== void 0 && paragraphIstd !== void 0 ? resolveStyleFormatting(context.styles, paragraphIstd).characterPrls : [];
149
151
  const enclosingInstruction = [];
150
152
  let inInstruction = false;
151
153
  const flush = () => {
@@ -175,14 +177,21 @@ function buildRuns(text, fcs, context) {
175
177
  const fc = fcs[index];
176
178
  if (fc === void 0) throw new DocFormatError(`character ${index} of a paragraph has no byte offset, so its formatting cannot be located`);
177
179
  const grpprl = context.chpxTable.chpxGrpprl(fc);
178
- const key = grpprl === void 0 ? "none" : `${grpprl.byteOffset}:${grpprl.byteLength}`;
180
+ const chpxKey = grpprl === void 0 ? "none" : `${grpprl.byteOffset}:${grpprl.byteLength}`;
181
+ const key = `${paragraphIstd ?? "none"}:${chpxKey}`;
179
182
  if (key !== currentKey) {
180
183
  flush();
181
184
  currentKey = key;
182
185
  let properties = context.characterProperties.get(key);
183
186
  if (properties === void 0) {
184
187
  properties = {};
185
- if (grpprl !== void 0) applyCharacterSprms(readGrpprl(grpprl), properties, context.fonts);
188
+ applyCharacterSprms(paragraphStyleCharacterPrls, properties, context.fonts);
189
+ if (grpprl !== void 0) {
190
+ const runPrls = readGrpprl(grpprl);
191
+ const characterIstd = characterIstdFromGrpprl(runPrls);
192
+ if (characterIstd !== void 0 && context.styles !== void 0) applyCharacterSprms(resolveStyleFormatting(context.styles, characterIstd).characterPrls, properties, context.fonts);
193
+ applyCharacterSprms(runPrls, properties, context.fonts);
194
+ }
186
195
  context.characterProperties.set(key, properties);
187
196
  }
188
197
  currentProperties = properties;
@@ -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_prop_sprm = require("../prop/sprm.cjs");
4
5
  //#region src/style/stsh.ts
5
6
  /** Stshif is a fixed 18 bytes: cstd, cbSTDBaseInFile, a bit field, stiMaxWhenSaved, istdMaxFixedWhenSaved, nVerBuiltInNamesWhenSaved, and the three default font indexes. */
6
7
  const STSHIF_SIZE = 18;
@@ -40,12 +41,17 @@ function parseStd(std, istd, cbStdBaseInFile) {
40
41
  const word0 = require_bytes.readUint16LE(std, 0);
41
42
  const word1 = require_bytes.readUint16LE(std, 2);
42
43
  const istdBase = word1 >> 4 & 4095;
44
+ const stk = word1 & 15;
45
+ const name = readXstz(std, cbStdBaseInFile, `name of the style at istd ${istd}`);
46
+ const { grpprlPapx, grpprlChpx } = parseGrLPUpxSw(std, cbStdBaseInFile + xstzByteLength(std, cbStdBaseInFile), stk, istd);
43
47
  return {
44
48
  istd,
45
49
  sti: word0 & 4095,
46
- stk: word1 & 15,
50
+ stk,
47
51
  istdBase: istdBase === ISTD_BASE_NONE ? void 0 : istdBase,
48
- name: readXstz(std, cbStdBaseInFile, `name of the style at istd ${istd}`)
52
+ name,
53
+ grpprlPapx,
54
+ grpprlChpx
49
55
  };
50
56
  }
51
57
  function readXstz(bytes, offset, what) {
@@ -55,34 +61,120 @@ function readXstz(bytes, offset, what) {
55
61
  for (let index = 0; index < cch; index += 1) out += String.fromCharCode(require_bytes.readUint16LE(chars, index * 2));
56
62
  return out;
57
63
  }
64
+ function xstzByteLength(bytes, offset) {
65
+ return 2 + require_bytes.readUint16LE(bytes, offset) * 2 + 2;
66
+ }
67
+ function readLpUpx(std, offset, what) {
68
+ const cbUpx = require_bytes.readUint16LE(std, offset);
69
+ return {
70
+ upx: require_bytes.slice(std, offset + 2, cbUpx, what),
71
+ next: offset + 2 + cbUpx + cbUpx % 2
72
+ };
73
+ }
74
+ function parseGrLPUpxSw(std, offset, stk, istd) {
75
+ if (stk === STK.paragraph) {
76
+ const papx = readLpUpx(std, offset, `UpxPapx for the paragraph style at istd ${istd}`);
77
+ const chpx = readLpUpx(std, papx.next, `UpxChpx for the paragraph style at istd ${istd}`);
78
+ const grpprlPapxBytes = require_bytes.slice(papx.upx, 2, papx.upx.length - 2, `grpprlPapx for the paragraph style at istd ${istd}`);
79
+ return {
80
+ grpprlPapx: require_prop_sprm.readGrpprl(grpprlPapxBytes),
81
+ grpprlChpx: require_prop_sprm.readGrpprl(chpx.upx)
82
+ };
83
+ }
84
+ if (stk === STK.character) {
85
+ const chpx = readLpUpx(std, offset, `UpxChpx for the character style at istd ${istd}`);
86
+ return {
87
+ grpprlPapx: void 0,
88
+ grpprlChpx: require_prop_sprm.readGrpprl(chpx.upx)
89
+ };
90
+ }
91
+ return {
92
+ grpprlPapx: void 0,
93
+ grpprlChpx: void 0
94
+ };
95
+ }
96
+ function resolveStyleFormatting(styleSheet, istd) {
97
+ const chain = [];
98
+ const seen = /* @__PURE__ */ new Set();
99
+ let current = styleSheet.styles[istd];
100
+ while (current !== void 0) {
101
+ if (seen.has(current.istd)) throw new require_errors.DocFormatError(`style inheritance chain starting at istd ${istd} loops back to istd ${current.istd}, which [MS-DOC] 2.9.260's own istdBase rule forbids`);
102
+ seen.add(current.istd);
103
+ chain.push(current);
104
+ current = current.istdBase === void 0 ? void 0 : styleSheet.styles[current.istdBase];
105
+ }
106
+ const paragraphPrls = [];
107
+ const characterPrls = [];
108
+ for (let index = chain.length - 1; index >= 0; index -= 1) {
109
+ const style = chain[index];
110
+ if (style === void 0) continue;
111
+ if (style.grpprlPapx !== void 0) paragraphPrls.push(...style.grpprlPapx);
112
+ if (style.grpprlChpx !== void 0) characterPrls.push(...style.grpprlChpx);
113
+ }
114
+ return {
115
+ paragraphPrls,
116
+ characterPrls
117
+ };
118
+ }
58
119
  function headingLevelFromIstd(istd) {
59
120
  return istd >= 1 && istd <= 9 ? istd : void 0;
60
121
  }
61
- function buildEmptyStsh() {
122
+ function buildStshForStyles(names) {
123
+ const cstd = names.size === 0 ? 0 : Math.max(...names.keys()) + 1;
62
124
  const stshi = [];
63
- const push16 = (value) => {
64
- stshi.push(value & 255, value >> 8 & 255);
125
+ const push16 = (target, value) => {
126
+ target.push(value & 255, value >> 8 & 255);
65
127
  };
66
- push16(0);
67
- push16(STDF_SIZE_WITHOUT_POST_2000);
68
- push16(1);
69
- push16(0);
70
- push16(15);
71
- push16(0);
72
- push16(0);
73
- push16(0);
74
- push16(0);
75
- push16(0);
76
- push16(4);
77
- return new Uint8Array([
128
+ push16(stshi, cstd);
129
+ push16(stshi, STDF_SIZE_WITHOUT_POST_2000);
130
+ push16(stshi, 1);
131
+ push16(stshi, 0);
132
+ push16(stshi, 15);
133
+ push16(stshi, 0);
134
+ push16(stshi, 0);
135
+ push16(stshi, 0);
136
+ push16(stshi, 0);
137
+ push16(stshi, 0);
138
+ push16(stshi, 4);
139
+ const out = [
78
140
  stshi.length & 255,
79
141
  stshi.length >> 8 & 255,
80
142
  ...stshi
81
- ]);
143
+ ];
144
+ const pushLpUpx = (target, payload) => {
145
+ push16(target, payload.length);
146
+ target.push(...payload);
147
+ if (payload.length % 2 === 1) target.push(0);
148
+ };
149
+ for (let istd = 0; istd < cstd; istd += 1) {
150
+ const name = names.get(istd);
151
+ if (name === void 0) {
152
+ out.push(0, 0);
153
+ continue;
154
+ }
155
+ const std = [];
156
+ const word0 = 4094;
157
+ const word1 = STK.paragraph & 15 | 65520;
158
+ push16(std, word0);
159
+ push16(std, word1);
160
+ push16(std, 0);
161
+ push16(std, 0);
162
+ push16(std, 0);
163
+ push16(std, name.length);
164
+ for (const character of name) push16(std, character.charCodeAt(0));
165
+ push16(std, 0);
166
+ pushLpUpx(std, [istd & 255, istd >> 8 & 255]);
167
+ pushLpUpx(std, []);
168
+ push16(out, std.length);
169
+ out.push(...std);
170
+ if (std.length % 2 === 1) out.push(0);
171
+ }
172
+ return new Uint8Array(out);
82
173
  }
83
174
  //#endregion
84
175
  exports.STI_USER_DEFINED = STI_USER_DEFINED;
85
176
  exports.STK = STK;
86
- exports.buildEmptyStsh = buildEmptyStsh;
177
+ exports.buildStshForStyles = buildStshForStyles;
87
178
  exports.headingLevelFromIstd = headingLevelFromIstd;
88
179
  exports.parseStsh = parseStsh;
180
+ exports.resolveStyleFormatting = resolveStyleFormatting;
@@ -1,3 +1,4 @@
1
+ import { t as Prl } from "../sprm-DEyvdOo0.cjs";
1
2
  //#region src/style/stsh.d.ts
2
3
  /** StdfBase.sti's "0x0FFE for user-defined styles"; anything else is an application-defined style whose sti identifies it. */
3
4
  declare const STI_USER_DEFINED = 4094;
@@ -18,13 +19,22 @@ interface Style {
18
19
  readonly istdBase: number | undefined;
19
20
  /** The style's primary name, from the STD's own Xstz. */
20
21
  readonly name: string;
22
+ /** The style's own paragraph formatting -- StkParaGRLPUPX's lpUpxPapx.PAPX.grpprlPapx -- present only for a paragraph style (STK.paragraph). Undefined for every other stk: table and numbering styles carry their own formatting shapes this package does not read (see the README's own scope note). */
23
+ readonly grpprlPapx: readonly Prl[] | undefined;
24
+ /** The style's own character formatting -- a paragraph style's StkParaGRLPUPX.lpUpxChpx.CHPX.grpprlChpx (the run-level defaults a heading's own text falls back to) or a character style's StkCharGRLPUPX.lpUpxChpx.CHPX.grpprlChpx -- present for STK.paragraph and STK.character, undefined otherwise. */
25
+ readonly grpprlChpx: readonly Prl[] | undefined;
21
26
  }
22
27
  interface StyleSheet {
23
28
  /** Indexed by istd; a hole is a slot [MS-DOC] permits to be empty ("A style definition can be empty, in which case cbStd MUST be 0"). */
24
29
  readonly styles: readonly (Style | undefined)[];
25
30
  }
26
31
  declare function parseStsh(stsh: Uint8Array): StyleSheet;
32
+ interface ResolvedStyleFormatting {
33
+ readonly paragraphPrls: readonly Prl[];
34
+ readonly characterPrls: readonly Prl[];
35
+ }
36
+ declare function resolveStyleFormatting(styleSheet: StyleSheet, istd: number): ResolvedStyleFormatting;
27
37
  declare function headingLevelFromIstd(istd: number): number | undefined;
28
- declare function buildEmptyStsh(): Uint8Array;
38
+ declare function buildStshForStyles(names: ReadonlyMap<number, string>): Uint8Array;
29
39
  //#endregion
30
- export { STI_USER_DEFINED, STK, Style, StyleSheet, buildEmptyStsh, headingLevelFromIstd, parseStsh };
40
+ export { ResolvedStyleFormatting, STI_USER_DEFINED, STK, Style, StyleSheet, buildStshForStyles, headingLevelFromIstd, parseStsh, resolveStyleFormatting };
@@ -1,3 +1,4 @@
1
+ import { t as Prl } from "../sprm-DEyvdOo0.js";
1
2
  //#region src/style/stsh.d.ts
2
3
  /** StdfBase.sti's "0x0FFE for user-defined styles"; anything else is an application-defined style whose sti identifies it. */
3
4
  declare const STI_USER_DEFINED = 4094;
@@ -18,13 +19,22 @@ interface Style {
18
19
  readonly istdBase: number | undefined;
19
20
  /** The style's primary name, from the STD's own Xstz. */
20
21
  readonly name: string;
22
+ /** The style's own paragraph formatting -- StkParaGRLPUPX's lpUpxPapx.PAPX.grpprlPapx -- present only for a paragraph style (STK.paragraph). Undefined for every other stk: table and numbering styles carry their own formatting shapes this package does not read (see the README's own scope note). */
23
+ readonly grpprlPapx: readonly Prl[] | undefined;
24
+ /** The style's own character formatting -- a paragraph style's StkParaGRLPUPX.lpUpxChpx.CHPX.grpprlChpx (the run-level defaults a heading's own text falls back to) or a character style's StkCharGRLPUPX.lpUpxChpx.CHPX.grpprlChpx -- present for STK.paragraph and STK.character, undefined otherwise. */
25
+ readonly grpprlChpx: readonly Prl[] | undefined;
21
26
  }
22
27
  interface StyleSheet {
23
28
  /** Indexed by istd; a hole is a slot [MS-DOC] permits to be empty ("A style definition can be empty, in which case cbStd MUST be 0"). */
24
29
  readonly styles: readonly (Style | undefined)[];
25
30
  }
26
31
  declare function parseStsh(stsh: Uint8Array): StyleSheet;
32
+ interface ResolvedStyleFormatting {
33
+ readonly paragraphPrls: readonly Prl[];
34
+ readonly characterPrls: readonly Prl[];
35
+ }
36
+ declare function resolveStyleFormatting(styleSheet: StyleSheet, istd: number): ResolvedStyleFormatting;
27
37
  declare function headingLevelFromIstd(istd: number): number | undefined;
28
- declare function buildEmptyStsh(): Uint8Array;
38
+ declare function buildStshForStyles(names: ReadonlyMap<number, string>): Uint8Array;
29
39
  //#endregion
30
- export { STI_USER_DEFINED, STK, Style, StyleSheet, buildEmptyStsh, headingLevelFromIstd, parseStsh };
40
+ export { ResolvedStyleFormatting, STI_USER_DEFINED, STK, Style, StyleSheet, buildStshForStyles, headingLevelFromIstd, parseStsh, resolveStyleFormatting };
@@ -1,5 +1,6 @@
1
1
  import { DocFormatError } from "../errors.js";
2
2
  import { readInt16LE, readUint16LE, slice } from "../bytes.js";
3
+ import { readGrpprl } from "../prop/sprm.js";
3
4
  //#region src/style/stsh.ts
4
5
  /** Stshif is a fixed 18 bytes: cstd, cbSTDBaseInFile, a bit field, stiMaxWhenSaved, istdMaxFixedWhenSaved, nVerBuiltInNamesWhenSaved, and the three default font indexes. */
5
6
  const STSHIF_SIZE = 18;
@@ -39,12 +40,17 @@ function parseStd(std, istd, cbStdBaseInFile) {
39
40
  const word0 = readUint16LE(std, 0);
40
41
  const word1 = readUint16LE(std, 2);
41
42
  const istdBase = word1 >> 4 & 4095;
43
+ const stk = word1 & 15;
44
+ const name = readXstz(std, cbStdBaseInFile, `name of the style at istd ${istd}`);
45
+ const { grpprlPapx, grpprlChpx } = parseGrLPUpxSw(std, cbStdBaseInFile + xstzByteLength(std, cbStdBaseInFile), stk, istd);
42
46
  return {
43
47
  istd,
44
48
  sti: word0 & 4095,
45
- stk: word1 & 15,
49
+ stk,
46
50
  istdBase: istdBase === ISTD_BASE_NONE ? void 0 : istdBase,
47
- name: readXstz(std, cbStdBaseInFile, `name of the style at istd ${istd}`)
51
+ name,
52
+ grpprlPapx,
53
+ grpprlChpx
48
54
  };
49
55
  }
50
56
  function readXstz(bytes, offset, what) {
@@ -54,30 +60,115 @@ function readXstz(bytes, offset, what) {
54
60
  for (let index = 0; index < cch; index += 1) out += String.fromCharCode(readUint16LE(chars, index * 2));
55
61
  return out;
56
62
  }
63
+ function xstzByteLength(bytes, offset) {
64
+ return 2 + readUint16LE(bytes, offset) * 2 + 2;
65
+ }
66
+ function readLpUpx(std, offset, what) {
67
+ const cbUpx = readUint16LE(std, offset);
68
+ return {
69
+ upx: slice(std, offset + 2, cbUpx, what),
70
+ next: offset + 2 + cbUpx + cbUpx % 2
71
+ };
72
+ }
73
+ function parseGrLPUpxSw(std, offset, stk, istd) {
74
+ if (stk === STK.paragraph) {
75
+ const papx = readLpUpx(std, offset, `UpxPapx for the paragraph style at istd ${istd}`);
76
+ const chpx = readLpUpx(std, papx.next, `UpxChpx for the paragraph style at istd ${istd}`);
77
+ const grpprlPapxBytes = slice(papx.upx, 2, papx.upx.length - 2, `grpprlPapx for the paragraph style at istd ${istd}`);
78
+ return {
79
+ grpprlPapx: readGrpprl(grpprlPapxBytes),
80
+ grpprlChpx: readGrpprl(chpx.upx)
81
+ };
82
+ }
83
+ if (stk === STK.character) {
84
+ const chpx = readLpUpx(std, offset, `UpxChpx for the character style at istd ${istd}`);
85
+ return {
86
+ grpprlPapx: void 0,
87
+ grpprlChpx: readGrpprl(chpx.upx)
88
+ };
89
+ }
90
+ return {
91
+ grpprlPapx: void 0,
92
+ grpprlChpx: void 0
93
+ };
94
+ }
95
+ function resolveStyleFormatting(styleSheet, istd) {
96
+ const chain = [];
97
+ const seen = /* @__PURE__ */ new Set();
98
+ let current = styleSheet.styles[istd];
99
+ while (current !== void 0) {
100
+ if (seen.has(current.istd)) throw new DocFormatError(`style inheritance chain starting at istd ${istd} loops back to istd ${current.istd}, which [MS-DOC] 2.9.260's own istdBase rule forbids`);
101
+ seen.add(current.istd);
102
+ chain.push(current);
103
+ current = current.istdBase === void 0 ? void 0 : styleSheet.styles[current.istdBase];
104
+ }
105
+ const paragraphPrls = [];
106
+ const characterPrls = [];
107
+ for (let index = chain.length - 1; index >= 0; index -= 1) {
108
+ const style = chain[index];
109
+ if (style === void 0) continue;
110
+ if (style.grpprlPapx !== void 0) paragraphPrls.push(...style.grpprlPapx);
111
+ if (style.grpprlChpx !== void 0) characterPrls.push(...style.grpprlChpx);
112
+ }
113
+ return {
114
+ paragraphPrls,
115
+ characterPrls
116
+ };
117
+ }
57
118
  function headingLevelFromIstd(istd) {
58
119
  return istd >= 1 && istd <= 9 ? istd : void 0;
59
120
  }
60
- function buildEmptyStsh() {
121
+ function buildStshForStyles(names) {
122
+ const cstd = names.size === 0 ? 0 : Math.max(...names.keys()) + 1;
61
123
  const stshi = [];
62
- const push16 = (value) => {
63
- stshi.push(value & 255, value >> 8 & 255);
124
+ const push16 = (target, value) => {
125
+ target.push(value & 255, value >> 8 & 255);
64
126
  };
65
- push16(0);
66
- push16(STDF_SIZE_WITHOUT_POST_2000);
67
- push16(1);
68
- push16(0);
69
- push16(15);
70
- push16(0);
71
- push16(0);
72
- push16(0);
73
- push16(0);
74
- push16(0);
75
- push16(4);
76
- return new Uint8Array([
127
+ push16(stshi, cstd);
128
+ push16(stshi, STDF_SIZE_WITHOUT_POST_2000);
129
+ push16(stshi, 1);
130
+ push16(stshi, 0);
131
+ push16(stshi, 15);
132
+ push16(stshi, 0);
133
+ push16(stshi, 0);
134
+ push16(stshi, 0);
135
+ push16(stshi, 0);
136
+ push16(stshi, 0);
137
+ push16(stshi, 4);
138
+ const out = [
77
139
  stshi.length & 255,
78
140
  stshi.length >> 8 & 255,
79
141
  ...stshi
80
- ]);
142
+ ];
143
+ const pushLpUpx = (target, payload) => {
144
+ push16(target, payload.length);
145
+ target.push(...payload);
146
+ if (payload.length % 2 === 1) target.push(0);
147
+ };
148
+ for (let istd = 0; istd < cstd; istd += 1) {
149
+ const name = names.get(istd);
150
+ if (name === void 0) {
151
+ out.push(0, 0);
152
+ continue;
153
+ }
154
+ const std = [];
155
+ const word0 = 4094;
156
+ const word1 = STK.paragraph & 15 | 65520;
157
+ push16(std, word0);
158
+ push16(std, word1);
159
+ push16(std, 0);
160
+ push16(std, 0);
161
+ push16(std, 0);
162
+ push16(std, name.length);
163
+ for (const character of name) push16(std, character.charCodeAt(0));
164
+ push16(std, 0);
165
+ pushLpUpx(std, [istd & 255, istd >> 8 & 255]);
166
+ pushLpUpx(std, []);
167
+ push16(out, std.length);
168
+ out.push(...std);
169
+ if (std.length % 2 === 1) out.push(0);
170
+ }
171
+ return new Uint8Array(out);
81
172
  }
82
173
  //#endregion
83
- export { STI_USER_DEFINED, STK, buildEmptyStsh, headingLevelFromIstd, parseStsh };
174
+ export { STI_USER_DEFINED, STK, buildStshForStyles, headingLevelFromIstd, parseStsh, resolveStyleFormatting };
@@ -1,2 +1,2 @@
1
- import { n as WriteWarning, r as flattenSectionBlocks, t as WriteParagraph } from "../write-C9XbykDf.cjs";
1
+ import { n as WriteWarning, r as flattenSectionBlocks, t as WriteParagraph } from "../write-SN_aIwyF.cjs";
2
2
  export { WriteParagraph, WriteWarning, flattenSectionBlocks };
@@ -1,2 +1,2 @@
1
- import { n as WriteWarning, r as flattenSectionBlocks, t as WriteParagraph } from "../write-C9XbykDf.js";
1
+ import { n as WriteWarning, r as flattenSectionBlocks, t as WriteParagraph } from "../write-SN_aIwyF.js";
2
2
  export { WriteParagraph, WriteWarning, flattenSectionBlocks };
@@ -4,7 +4,7 @@ import { ContentBlock, ContentParagraph, ContentRun } from "document-schema.js";
4
4
  type WriteWarning = (message: string) => void;
5
5
  interface WriteParagraph {
6
6
  readonly runs: readonly ContentRun[];
7
- readonly properties: Pick<ContentParagraph, "alignment" | "indentLeftPt" | "indentRightPt" | "indentFirstLinePt" | "spacingBeforePt" | "spacingAfterPt" | "lineSpacing" | "pageBreakBefore" | "list">;
7
+ readonly properties: Pick<ContentParagraph, "alignment" | "indentLeftPt" | "indentRightPt" | "indentFirstLinePt" | "spacingBeforePt" | "spacingAfterPt" | "lineSpacing" | "pageBreakBefore" | "list" | "styleId" | "headingLevel">;
8
8
  /** Extra grpprl bytes appended after encodeParagraphGrpprl's own output -- sprmPFInTable on every table paragraph, plus sprmPFTtp and the row's own TAP on a row's trailing mark. */
9
9
  readonly extraGrpprl: readonly number[];
10
10
  /** The character terminating this paragraph in the text stream: PARAGRAPH_MARK normally, CELL_MARK for a table cell or row mark. */
@@ -4,7 +4,7 @@ import { ContentBlock, ContentParagraph, ContentRun } from "document-schema.js";
4
4
  type WriteWarning = (message: string) => void;
5
5
  interface WriteParagraph {
6
6
  readonly runs: readonly ContentRun[];
7
- readonly properties: Pick<ContentParagraph, "alignment" | "indentLeftPt" | "indentRightPt" | "indentFirstLinePt" | "spacingBeforePt" | "spacingAfterPt" | "lineSpacing" | "pageBreakBefore" | "list">;
7
+ readonly properties: Pick<ContentParagraph, "alignment" | "indentLeftPt" | "indentRightPt" | "indentFirstLinePt" | "spacingBeforePt" | "spacingAfterPt" | "lineSpacing" | "pageBreakBefore" | "list" | "styleId" | "headingLevel">;
8
8
  /** Extra grpprl bytes appended after encodeParagraphGrpprl's own output -- sprmPFInTable on every table paragraph, plus sprmPFTtp and the row's own TAP on a row's trailing mark. */
9
9
  readonly extraGrpprl: readonly number[];
10
10
  /** The character terminating this paragraph in the text stream: PARAGRAPH_MARK normally, CELL_MARK for a table cell or row mark. */
package/dist/write.cjs CHANGED
@@ -32,6 +32,28 @@ function writeDocContent(document, options = {}) {
32
32
  extraGrpprl: [],
33
33
  terminator: 13
34
34
  });
35
+ const FIRST_NON_HEADING_ISTD = 10;
36
+ const MAX_HEADING_ISTD = 9;
37
+ const styleNames = /* @__PURE__ */ new Map();
38
+ const istdByStyleId = /* @__PURE__ */ new Map();
39
+ let nextNonHeadingIstd = FIRST_NON_HEADING_ISTD;
40
+ const istdOf = (properties) => {
41
+ const heading = properties.headingLevel;
42
+ if (heading !== void 0 && heading >= 1 && heading <= MAX_HEADING_ISTD) {
43
+ if (!styleNames.has(heading)) styleNames.set(heading, properties.styleId ?? `Heading ${String(heading)}`);
44
+ return heading;
45
+ }
46
+ const styleId = properties.styleId;
47
+ if (styleId === void 0) return 0;
48
+ const existing = istdByStyleId.get(styleId);
49
+ if (existing !== void 0) return existing;
50
+ const istd = nextNonHeadingIstd;
51
+ nextNonHeadingIstd += 1;
52
+ istdByStyleId.set(styleId, istd);
53
+ styleNames.set(istd, styleId);
54
+ return istd;
55
+ };
56
+ const istds = writeParagraphs.map((entry) => istdOf(entry.properties));
35
57
  const fontNames = [];
36
58
  const fontIndexByName = /* @__PURE__ */ new Map();
37
59
  const fontIndexOf = (name) => {
@@ -101,9 +123,11 @@ function writeDocContent(document, options = {}) {
101
123
  const papxParagraphSpecs = formatted.map((paragraph, index) => {
102
124
  const start = paragraphStarts[index];
103
125
  if (start === void 0) throw new require_errors.DocFormatError("internal defect: writeDocContent lost a paragraph's own start position");
126
+ const istd = istds[index];
127
+ if (istd === void 0) throw new require_errors.DocFormatError("internal defect: writeDocContent lost a paragraph's own minted istd");
104
128
  return {
105
129
  fc: characterFc(start),
106
- istd: 0,
130
+ istd,
107
131
  grpprl: paragraph.grpprl
108
132
  };
109
133
  });
@@ -123,7 +147,7 @@ function writeDocContent(document, options = {}) {
123
147
  const clx = require_text_piece_table_write.buildTextClx(text.length, TEXT_FC);
124
148
  const chpxBinTable = require_prop_fkp_write.buildPropertyBinTable([...chpxPages.map(require_prop_fkp_write.firstFcOfPage), textFcLim], chpxPages.map((_, index) => chpxPageStart + index));
125
149
  const papxBinTable = require_prop_fkp_write.buildPropertyBinTable([...papxPages.map(require_prop_fkp_write.firstFcOfPage), textFcLim], papxPages.map((_, index) => papxPageStart + index));
126
- const stsh = require_style_stsh.buildEmptyStsh();
150
+ const stsh = require_style_stsh.buildStshForStyles(styleNames);
127
151
  const fontTable = fontNames.length > 0 ? require_style_fonts.buildFontTable(fontNames) : void 0;
128
152
  const plcfSed = require_prop_sep_write.buildPlcfSed(text.length, fcSepx);
129
153
  let cursor = 0;
package/dist/write.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as WriteWarning } from "./write-C9XbykDf.cjs";
1
+ import { n as WriteWarning } from "./write-SN_aIwyF.cjs";
2
2
  import { ContentDocument } from "document-schema.js";
3
3
  //#region src/write.d.ts
4
4
  interface WriteDocContentOptions {
package/dist/write.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as WriteWarning } from "./write-C9XbykDf.js";
1
+ import { n as WriteWarning } from "./write-SN_aIwyF.js";
2
2
  import { ContentDocument } from "document-schema.js";
3
3
  //#region src/write.d.ts
4
4
  interface WriteDocContentOptions {
package/dist/write.js CHANGED
@@ -9,7 +9,7 @@ import { buildChpxPages, buildPapxPages, buildPropertyBinTable, firstFcOfPage }
9
9
  import { encodeCharacterGrpprl } from "./prop/chp-write.js";
10
10
  import { encodeParagraphGrpprl } from "./prop/pap-write.js";
11
11
  import { buildPlcfSed, buildSepx, encodeSectionGrpprl } from "./prop/sep-write.js";
12
- import { buildEmptyStsh } from "./style/stsh.js";
12
+ import { buildStshForStyles } from "./style/stsh.js";
13
13
  import { buildFontTable } from "./style/fonts.js";
14
14
  import { buildNumberingTables, gatherListUsage } from "./list/numbering-write.js";
15
15
  import { flattenSectionBlocks } from "./table/write.js";
@@ -31,6 +31,28 @@ function writeDocContent(document, options = {}) {
31
31
  extraGrpprl: [],
32
32
  terminator: 13
33
33
  });
34
+ const FIRST_NON_HEADING_ISTD = 10;
35
+ const MAX_HEADING_ISTD = 9;
36
+ const styleNames = /* @__PURE__ */ new Map();
37
+ const istdByStyleId = /* @__PURE__ */ new Map();
38
+ let nextNonHeadingIstd = FIRST_NON_HEADING_ISTD;
39
+ const istdOf = (properties) => {
40
+ const heading = properties.headingLevel;
41
+ if (heading !== void 0 && heading >= 1 && heading <= MAX_HEADING_ISTD) {
42
+ if (!styleNames.has(heading)) styleNames.set(heading, properties.styleId ?? `Heading ${String(heading)}`);
43
+ return heading;
44
+ }
45
+ const styleId = properties.styleId;
46
+ if (styleId === void 0) return 0;
47
+ const existing = istdByStyleId.get(styleId);
48
+ if (existing !== void 0) return existing;
49
+ const istd = nextNonHeadingIstd;
50
+ nextNonHeadingIstd += 1;
51
+ istdByStyleId.set(styleId, istd);
52
+ styleNames.set(istd, styleId);
53
+ return istd;
54
+ };
55
+ const istds = writeParagraphs.map((entry) => istdOf(entry.properties));
34
56
  const fontNames = [];
35
57
  const fontIndexByName = /* @__PURE__ */ new Map();
36
58
  const fontIndexOf = (name) => {
@@ -100,9 +122,11 @@ function writeDocContent(document, options = {}) {
100
122
  const papxParagraphSpecs = formatted.map((paragraph, index) => {
101
123
  const start = paragraphStarts[index];
102
124
  if (start === void 0) throw new DocFormatError("internal defect: writeDocContent lost a paragraph's own start position");
125
+ const istd = istds[index];
126
+ if (istd === void 0) throw new DocFormatError("internal defect: writeDocContent lost a paragraph's own minted istd");
103
127
  return {
104
128
  fc: characterFc(start),
105
- istd: 0,
129
+ istd,
106
130
  grpprl: paragraph.grpprl
107
131
  };
108
132
  });
@@ -122,7 +146,7 @@ function writeDocContent(document, options = {}) {
122
146
  const clx = buildTextClx(text.length, TEXT_FC);
123
147
  const chpxBinTable = buildPropertyBinTable([...chpxPages.map(firstFcOfPage), textFcLim], chpxPages.map((_, index) => chpxPageStart + index));
124
148
  const papxBinTable = buildPropertyBinTable([...papxPages.map(firstFcOfPage), textFcLim], papxPages.map((_, index) => papxPageStart + index));
125
- const stsh = buildEmptyStsh();
149
+ const stsh = buildStshForStyles(styleNames);
126
150
  const fontTable = fontNames.length > 0 ? buildFontTable(fontNames) : void 0;
127
151
  const plcfSed = buildPlcfSed(text.length, fcSepx);
128
152
  let cursor = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doc-codec",
3
- "version": "2.2.4",
3
+ "version": "2.3.0",
4
4
  "description": "A hand-written reader for the Word Binary File Format ([MS-DOC], .doc) against the shared document-schema.js content pivot: FIB parsing, piece-table text reconstruction, and CHPX/PAPX formatting exceptions.",
5
5
  "type": "module",
6
6
  "repository": {