rtf-codec 4.2.5 → 4.4.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 +7 -7
- package/dist/cell-format.cjs +11 -1
- package/dist/cell-format.d.cts +1 -0
- package/dist/cell-format.d.ts +1 -0
- package/dist/cell-format.js +11 -1
- package/dist/codec.d.cts +37 -0
- package/dist/codec.d.ts +37 -0
- package/dist/header.cjs +13 -1
- package/dist/header.js +13 -1
- package/dist/read.cjs +80 -26
- package/dist/read.js +80 -26
- package/dist/write.cjs +11 -1
- package/dist/write.js +11 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
**Status: under active development.** The read and write paths described below are implemented and tested, including against a real-producer corpus: `pnpm test:corpus` runs the gitignored `test/corpus/` suite against LibreOffice-produced RTF (flat-ODT sources spanning runs, colour, headings, lists, tables, and alignment, converted through Writer's own RTF filter by `scripts/generate-corpus.mjs`) -- the corpus validated the reader cleanly across all eight fixtures with no defects found. [Scope](#scope) states exactly what is handled and what is not; nothing in this README describes work that is planned rather than done.
|
|
8
8
|
|
|
9
|
-
Every construct that remains unhandled is either a gap in `document-schema.js` rather than in this codec (
|
|
9
|
+
Every construct that remains unhandled is either a gap in `document-schema.js` rather than in this codec (character scaling, kerning, and run background colour have no field to land in), or something RTF itself does not specify at all beyond its own form-field vocabulary (a docx-style rich-text SDT has no RTF spelling of any kind) — see [Deliberately not handled](#deliberately-not-handled), which says which of the two each row is.
|
|
10
10
|
|
|
11
|
-
RTF is the cleanest structural fit of any format this family did not already handle. It is a wordprocessing format through and through — paragraphs, runs, character properties, paragraph properties, tables, lists and pictures all have direct `ContentDocument` equivalents — and it can express more of the wordprocessing variant than markdown can, carrying colour, font family, font size and
|
|
11
|
+
RTF is the cleanest structural fit of any format this family did not already handle. It is a wordprocessing format through and through — paragraphs, runs, character properties, paragraph properties, tables, lists and pictures all have direct `ContentDocument` equivalents — and it can express more of the wordprocessing variant than markdown can, carrying colour, font family, font size, alignment, vertical position and text direction natively. No `document-schema.js` model change was needed for it.
|
|
12
12
|
|
|
13
13
|
What it is _not_ is another XML format. RTF is tokenised plain text with a brace-nested group and destination model, so none of the XML plumbing `ooxml.js` and `odf.js` share applies here: this package carries its own byte lexer, its own destination state machine, its own `\uN`/`\ucN` Unicode handling with code-page fallback, and its own parsers for the five header mini-formats. The closest relative in this workspace is `markdown-codec`, which is likewise a hand-written scanner and parser for a non-XML text format rather than a wrapper around a document library.
|
|
14
14
|
|
|
@@ -121,9 +121,10 @@ On the way out, **every non-ASCII character leaves as `\uN`** with a one-charact
|
|
|
121
121
|
| `\*\revtbl` | The revision authors `\revauthN` and its siblings index into |
|
|
122
122
|
| Sections | `\sect`, `\sectd`, the `\pgwsxnN`/`\marg*sxnN` geometry family, and the `\sbk*` break vocabulary |
|
|
123
123
|
| Paragraphs | `\par`, `\pard`, alignment, indents, spacing, `\slN`/`\slmultN`, `\pagebb` |
|
|
124
|
-
| Runs | `\b`, `\i`, `\ul` (every variant), `\strike`, `\fN`, `\fsN`, `\cfN`, `\v` (dropped as hidden)
|
|
124
|
+
| Runs | `\b`, `\i`, `\ul` (every variant), `\strike`, `\super`/`\sub` and `\upN`/`\dnN` onto `ContentRun.verticalAlign` (`\nosupersub` as the off-spelling), `\fN`, `\fsN`, `\cfN`, `\v` (dropped as hidden) |
|
|
125
|
+
| Text direction | The four scopes RTF states it at: `\rtlch`/`\ltrch` onto `ContentRun.direction`, `\rtlpar`/`\ltrpar` onto `ContentParagraph.direction`, `\rtlrow`/`\ltrrow` onto `ContentTableRow.direction`, and `\rtldoc`/`\ltrdoc` onto `LayoutMetadata.direction`. `\rtlsect`/`\ltrsect` stay unmapped: they state a section's own column-snaking direction, a page-layout fact `ContentSection` carries no field for, not the text-direction scope the four fields name |
|
|
125
126
|
| Tables | `\trowd`, `\cellxN`, `\trleftN`, `\cell`, `\row`, multi-paragraph cells |
|
|
126
|
-
| Table cells | `\clbrdrt`/`l`/`b`/`r` with the whole `<brdr>` production, `\clcbpatN`/`\clcfpatN`/`\clshdngN` shading (a real two-colour pattern fill, not just a flat colour -- see below), and both merge families (`\clvmgf`/`\clvmrg`, `\clmgf`/`\clmrg`)
|
|
127
|
+
| Table cells | `\clbrdrt`/`l`/`b`/`r` with the whole `<brdr>` production, `\clvertalc`/`\clvertalb` (and `\clvertalt`, whose stated default collapses into the absence `ContentTableCell.verticalAlign` already means) as the cell's vertical alignment, `\clcbpatN`/`\clcfpatN`/`\clshdngN` shading (a real two-colour pattern fill, not just a flat colour -- see below), and both merge families (`\clvmgf`/`\clvmrg`, `\clmgf`/`\clmrg`) |
|
|
127
128
|
| Bookmarks | `\*\bkmkstart`/`\*\bkmkend` as `anchor` constructs, with `\bkmkcolfN`/`\bkmkcollN` quarantined as residue |
|
|
128
129
|
| Revision marks | The whole `<chrev>` production as `provenance` constructs: `\revised`, `\deleted`, `\mvf`/`\mvt`, `\crauthN`, with authors and `\revdttmN` dates |
|
|
129
130
|
| Form fields | A `\field` whose `\*\fldinst` names FORMTEXT/FORMCHECKBOX/FORMDROPDOWN, plus whatever `\*\formfield` data it carries (`\*\ffname` as its tag, `\*\ffhelptext` as its alias when `\ffownhelp` says it is author-set rather than auto-generated, `\ffprot` as its lock, a checkbox's own `\ffres`/`\ffdefres` as its checked state, a dropdown's own `\ffres`/`\ffdefres` as its selected entry alongside its `\*\ffl` option list), as a `contentControl` construct (plainText/checkbox/dropDown). A plainText field's own `\*\ffdeftext` group is recognised but its content is skipped whole rather than captured, since `value` names the control's CURRENT value, which for a text field is the wrapped-run text already carried in the extent's own children, not `\ffdeftext`'s default/reset text (see Write below for the one direction `\ffdeftext` does feed `value`); the same applies to the four other `\*\formfield` destination strings RTF's own Form Fields table names alongside it (`\*\ffformat`, `\*\ffstattext`, `\*\ffentrymcr`, `\*\ffexitmcr`), each skipped whole for the identical reason -- no `ContentControlDescriptor` field exists to carry any of them |
|
|
@@ -160,9 +161,8 @@ Each of these is reported through a diagnostic rather than dropped silently —
|
|
|
160
161
|
| Nested tables (`\nestcell`/`\nestrow`) | Read as ordinary cell content; the inner table's own structure is not reconstructed. |
|
|
161
162
|
| Drawing objects (`\do`, `\shp`) | **A schema gap, not a container one.** These are Word's own native in-document vector-drawing layer, not an OLE embed -- there is no raw drawing-shape `ContentBlock` for a wordprocessing section's block flow to land in (only `ContentEmbeddedObjectBlock`, which names a whole embedded document, not a shape), so a `\do`/`\shp` construct is dropped regardless of the container work [Embedded objects](#embedded-objects) below did for `\object`. |
|
|
162
163
|
| A real, foreign `\object`'s OLE data | This package's own `\objdata` payload round-trips fully (see [Embedded objects](#embedded-objects)); a real Word-authored OLESaveToStream structure (an actual embedded `.xls`/`.doc`/OLE-control payload) has no decoder here and degrades with a diagnostic, recovering `\result`'s own fallback paragraphs when present instead of the real object. |
|
|
163
|
-
| Superscript/subscript (`\super`, `\sub`, `\upN`, `\dnN`), character scaling, kerning, background colour | **A schema gap, not an RTF one.** `ContentRun` carries no
|
|
164
|
-
|
|
|
165
|
-
| Cell vertical alignment (`\clvertalt`/`\clvertalc`/`\clvertalb`), diagonal cell borders (`\cldglu`/`\cldgll`) | `ContentTableCell.borders` has no diagonal member, so a diagonal rule is not a side; there is no vertical-alignment field to carry the other three into either. |
|
|
164
|
+
| Superscript/subscript (`\super`, `\sub`, `\upN`, `\dnN`), character scaling, kerning, background colour | Character scaling (`\charscalexN`), kerning (`\kerningN`), background colour (`\cbN`/`\highlightN`) **A schema gap, not an RTF one.** `ContentRun` carries no field for any of the three. (The vertical-position family that shared this row — `\super`/`\sub`/`\upN`/`\dnN` — now reads and writes through `ContentRun.verticalAlign`.) |
|
|
165
|
+
| Cell vertical alignment (`\clvertalt`/`\clvertalc`/`\clvertalb`), diagonal cell borders (`\cldglu`/`\cldgll`) | Diagonal cell borders (`\cldglu`/`\cldgll`) `ContentTableCell.borders` has no diagonal member, so a diagonal rule is not a side. (Cell vertical alignment, which shared this row, now reads and writes through `ContentTableCell.verticalAlign`.) |
|
|
166
166
|
| A bookmark whose two halves straddle a table cell wall | `document-schema.js` ratifies this as a drop rather than a shape to repair: each block list is its own bracket scope, and pairing across two of them would need the marker ids its contract deliberately refuses. |
|
|
167
167
|
| A contentControl extent that crosses another contentControl extent in the same paragraph | RTF's `\*\formfield` destination can only nest, never cross: a `{\field...}` group nests cleanly inside another one's own `\fldrslt`, but two extents that start-before/end-after each other have no valid brace sequence, since whichever closes second would close the other's own braces instead of its own. |
|
|
168
168
|
| Two block-scoped bookmarks whose real ranges are disjoint but whose halves both land in the same paragraph (one's `\bkmkend`, the other's `\bkmkstart`) | A paragraph is this reader's finest addressable block-extent unit, so the shared paragraph's own block index gets claimed by both bookmarks' extents even though their real text never overlapped -- a genuine crossing pair, not a nesting one, and `document-schema.js`'s own construct group has no shape for that (a tree would need two subtrees crossing, which no tree holds). The later-starting bookmark is dropped with a diagnostic; the earlier one keeps its extent intact. |
|
package/dist/cell-format.cjs
CHANGED
|
@@ -83,7 +83,8 @@ function newPendingCell() {
|
|
|
83
83
|
verticalMergeFirst: false,
|
|
84
84
|
verticalMergeContinuation: false,
|
|
85
85
|
horizontalMergeFirst: false,
|
|
86
|
-
horizontalMergeContinuation: false
|
|
86
|
+
horizontalMergeContinuation: false,
|
|
87
|
+
verticalAlign: void 0
|
|
87
88
|
};
|
|
88
89
|
}
|
|
89
90
|
function applyCellDefinitionControlWord(name, param, cell) {
|
|
@@ -120,6 +121,15 @@ function applyCellDefinitionControlWord(name, param, cell) {
|
|
|
120
121
|
case "clshdng":
|
|
121
122
|
cell.shadingPercent = param === void 0 ? void 0 : param / 100;
|
|
122
123
|
return true;
|
|
124
|
+
case "clvertalc":
|
|
125
|
+
cell.verticalAlign = "center";
|
|
126
|
+
return true;
|
|
127
|
+
case "clvertalb":
|
|
128
|
+
cell.verticalAlign = "bottom";
|
|
129
|
+
return true;
|
|
130
|
+
case "clvertalt":
|
|
131
|
+
cell.verticalAlign = void 0;
|
|
132
|
+
return true;
|
|
123
133
|
}
|
|
124
134
|
const pending = cell.side === void 0 ? void 0 : cell.borders[cell.side];
|
|
125
135
|
if (pending === void 0) return false;
|
package/dist/cell-format.d.cts
CHANGED
|
@@ -18,6 +18,7 @@ interface PendingCell {
|
|
|
18
18
|
verticalMergeContinuation: boolean;
|
|
19
19
|
horizontalMergeFirst: boolean;
|
|
20
20
|
horizontalMergeContinuation: boolean;
|
|
21
|
+
verticalAlign: "center" | "bottom" | undefined;
|
|
21
22
|
}
|
|
22
23
|
declare function newPendingCell(): PendingCell;
|
|
23
24
|
declare function applyCellDefinitionControlWord(name: string, param: number | undefined, cell: PendingCell): boolean;
|
package/dist/cell-format.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ interface PendingCell {
|
|
|
18
18
|
verticalMergeContinuation: boolean;
|
|
19
19
|
horizontalMergeFirst: boolean;
|
|
20
20
|
horizontalMergeContinuation: boolean;
|
|
21
|
+
verticalAlign: "center" | "bottom" | undefined;
|
|
21
22
|
}
|
|
22
23
|
declare function newPendingCell(): PendingCell;
|
|
23
24
|
declare function applyCellDefinitionControlWord(name: string, param: number | undefined, cell: PendingCell): boolean;
|
package/dist/cell-format.js
CHANGED
|
@@ -82,7 +82,8 @@ function newPendingCell() {
|
|
|
82
82
|
verticalMergeFirst: false,
|
|
83
83
|
verticalMergeContinuation: false,
|
|
84
84
|
horizontalMergeFirst: false,
|
|
85
|
-
horizontalMergeContinuation: false
|
|
85
|
+
horizontalMergeContinuation: false,
|
|
86
|
+
verticalAlign: void 0
|
|
86
87
|
};
|
|
87
88
|
}
|
|
88
89
|
function applyCellDefinitionControlWord(name, param, cell) {
|
|
@@ -119,6 +120,15 @@ function applyCellDefinitionControlWord(name, param, cell) {
|
|
|
119
120
|
case "clshdng":
|
|
120
121
|
cell.shadingPercent = param === void 0 ? void 0 : param / 100;
|
|
121
122
|
return true;
|
|
123
|
+
case "clvertalc":
|
|
124
|
+
cell.verticalAlign = "center";
|
|
125
|
+
return true;
|
|
126
|
+
case "clvertalb":
|
|
127
|
+
cell.verticalAlign = "bottom";
|
|
128
|
+
return true;
|
|
129
|
+
case "clvertalt":
|
|
130
|
+
cell.verticalAlign = void 0;
|
|
131
|
+
return true;
|
|
122
132
|
}
|
|
123
133
|
const pending = cell.side === void 0 ? void 0 : cell.borders[cell.side];
|
|
124
134
|
if (pending === void 0) return false;
|
package/dist/codec.d.cts
CHANGED
|
@@ -7,6 +7,12 @@ declare const rtfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
|
|
|
7
7
|
widthPt: z.ZodNumber;
|
|
8
8
|
heightPt: z.ZodNumber;
|
|
9
9
|
}, z.core.$strip>>>;
|
|
10
|
+
fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
11
|
+
family: z.ZodString;
|
|
12
|
+
bold: z.ZodBoolean;
|
|
13
|
+
italic: z.ZodBoolean;
|
|
14
|
+
base64: z.ZodString;
|
|
15
|
+
}, z.core.$strip>>>;
|
|
10
16
|
styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
11
17
|
paragraph: z.ZodOptional<z.ZodObject<{
|
|
12
18
|
alignment: z.ZodOptional<z.ZodEnum<{
|
|
@@ -156,6 +162,12 @@ declare const rtfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
|
|
|
156
162
|
widthPt: z.ZodNumber;
|
|
157
163
|
heightPt: z.ZodNumber;
|
|
158
164
|
}, z.core.$strip>>>;
|
|
165
|
+
fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
166
|
+
family: z.ZodString;
|
|
167
|
+
bold: z.ZodBoolean;
|
|
168
|
+
italic: z.ZodBoolean;
|
|
169
|
+
base64: z.ZodString;
|
|
170
|
+
}, z.core.$strip>>>;
|
|
159
171
|
styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
160
172
|
paragraph: z.ZodOptional<z.ZodObject<{
|
|
161
173
|
alignment: z.ZodOptional<z.ZodEnum<{
|
|
@@ -310,6 +322,12 @@ declare const rtfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
|
|
|
310
322
|
widthPt: z.ZodNumber;
|
|
311
323
|
heightPt: z.ZodNumber;
|
|
312
324
|
}, z.core.$strip>>>;
|
|
325
|
+
fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
326
|
+
family: z.ZodString;
|
|
327
|
+
bold: z.ZodBoolean;
|
|
328
|
+
italic: z.ZodBoolean;
|
|
329
|
+
base64: z.ZodString;
|
|
330
|
+
}, z.core.$strip>>>;
|
|
313
331
|
styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
314
332
|
paragraph: z.ZodOptional<z.ZodObject<{
|
|
315
333
|
alignment: z.ZodOptional<z.ZodEnum<{
|
|
@@ -459,6 +477,12 @@ declare const rtfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
|
|
|
459
477
|
widthPt: z.ZodNumber;
|
|
460
478
|
heightPt: z.ZodNumber;
|
|
461
479
|
}, z.core.$strip>>>;
|
|
480
|
+
fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
481
|
+
family: z.ZodString;
|
|
482
|
+
bold: z.ZodBoolean;
|
|
483
|
+
italic: z.ZodBoolean;
|
|
484
|
+
base64: z.ZodString;
|
|
485
|
+
}, z.core.$strip>>>;
|
|
462
486
|
styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
463
487
|
paragraph: z.ZodOptional<z.ZodObject<{
|
|
464
488
|
alignment: z.ZodOptional<z.ZodEnum<{
|
|
@@ -667,6 +691,12 @@ declare const rtfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
|
|
|
667
691
|
widthPt: z.ZodNumber;
|
|
668
692
|
heightPt: z.ZodNumber;
|
|
669
693
|
}, z.core.$strip>>>;
|
|
694
|
+
fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
695
|
+
family: z.ZodString;
|
|
696
|
+
bold: z.ZodBoolean;
|
|
697
|
+
italic: z.ZodBoolean;
|
|
698
|
+
base64: z.ZodString;
|
|
699
|
+
}, z.core.$strip>>>;
|
|
670
700
|
styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
671
701
|
paragraph: z.ZodOptional<z.ZodObject<{
|
|
672
702
|
alignment: z.ZodOptional<z.ZodEnum<{
|
|
@@ -867,6 +897,11 @@ declare const rtfContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, U
|
|
|
867
897
|
even: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
|
|
868
898
|
first: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
|
|
869
899
|
}, z.core.$strip>>;
|
|
900
|
+
watermarks: z.ZodOptional<z.ZodObject<{
|
|
901
|
+
default: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
|
|
902
|
+
even: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
|
|
903
|
+
first: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
|
|
904
|
+
}, z.core.$strip>>;
|
|
870
905
|
source: z.ZodOptional<z.ZodObject<{
|
|
871
906
|
format: z.ZodEnum<{
|
|
872
907
|
docx: "docx";
|
|
@@ -1032,6 +1067,7 @@ declare const rtfContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, U
|
|
|
1032
1067
|
fontScale: z.ZodOptional<z.ZodNumber>;
|
|
1033
1068
|
lineSpacingReduction: z.ZodOptional<z.ZodNumber>;
|
|
1034
1069
|
paintOrder: z.ZodOptional<z.ZodNumber>;
|
|
1070
|
+
readingOrder: z.ZodOptional<z.ZodNumber>;
|
|
1035
1071
|
sourcePath: z.ZodOptional<z.ZodString>;
|
|
1036
1072
|
source: z.ZodOptional<z.ZodObject<{
|
|
1037
1073
|
format: z.ZodEnum<{
|
|
@@ -2572,6 +2608,7 @@ declare const rtfContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, U
|
|
|
2572
2608
|
fontScale: z.ZodOptional<z.ZodNumber>;
|
|
2573
2609
|
lineSpacingReduction: z.ZodOptional<z.ZodNumber>;
|
|
2574
2610
|
paintOrder: z.ZodOptional<z.ZodNumber>;
|
|
2611
|
+
readingOrder: z.ZodOptional<z.ZodNumber>;
|
|
2575
2612
|
sourcePath: z.ZodOptional<z.ZodString>;
|
|
2576
2613
|
source: z.ZodOptional<z.ZodObject<{
|
|
2577
2614
|
format: z.ZodEnum<{
|
package/dist/codec.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ declare const rtfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
|
|
|
7
7
|
widthPt: z.ZodNumber;
|
|
8
8
|
heightPt: z.ZodNumber;
|
|
9
9
|
}, z.core.$strip>>>;
|
|
10
|
+
fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
11
|
+
family: z.ZodString;
|
|
12
|
+
bold: z.ZodBoolean;
|
|
13
|
+
italic: z.ZodBoolean;
|
|
14
|
+
base64: z.ZodString;
|
|
15
|
+
}, z.core.$strip>>>;
|
|
10
16
|
styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
11
17
|
paragraph: z.ZodOptional<z.ZodObject<{
|
|
12
18
|
alignment: z.ZodOptional<z.ZodEnum<{
|
|
@@ -156,6 +162,12 @@ declare const rtfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
|
|
|
156
162
|
widthPt: z.ZodNumber;
|
|
157
163
|
heightPt: z.ZodNumber;
|
|
158
164
|
}, z.core.$strip>>>;
|
|
165
|
+
fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
166
|
+
family: z.ZodString;
|
|
167
|
+
bold: z.ZodBoolean;
|
|
168
|
+
italic: z.ZodBoolean;
|
|
169
|
+
base64: z.ZodString;
|
|
170
|
+
}, z.core.$strip>>>;
|
|
159
171
|
styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
160
172
|
paragraph: z.ZodOptional<z.ZodObject<{
|
|
161
173
|
alignment: z.ZodOptional<z.ZodEnum<{
|
|
@@ -310,6 +322,12 @@ declare const rtfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
|
|
|
310
322
|
widthPt: z.ZodNumber;
|
|
311
323
|
heightPt: z.ZodNumber;
|
|
312
324
|
}, z.core.$strip>>>;
|
|
325
|
+
fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
326
|
+
family: z.ZodString;
|
|
327
|
+
bold: z.ZodBoolean;
|
|
328
|
+
italic: z.ZodBoolean;
|
|
329
|
+
base64: z.ZodString;
|
|
330
|
+
}, z.core.$strip>>>;
|
|
313
331
|
styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
314
332
|
paragraph: z.ZodOptional<z.ZodObject<{
|
|
315
333
|
alignment: z.ZodOptional<z.ZodEnum<{
|
|
@@ -459,6 +477,12 @@ declare const rtfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
|
|
|
459
477
|
widthPt: z.ZodNumber;
|
|
460
478
|
heightPt: z.ZodNumber;
|
|
461
479
|
}, z.core.$strip>>>;
|
|
480
|
+
fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
481
|
+
family: z.ZodString;
|
|
482
|
+
bold: z.ZodBoolean;
|
|
483
|
+
italic: z.ZodBoolean;
|
|
484
|
+
base64: z.ZodString;
|
|
485
|
+
}, z.core.$strip>>>;
|
|
462
486
|
styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
463
487
|
paragraph: z.ZodOptional<z.ZodObject<{
|
|
464
488
|
alignment: z.ZodOptional<z.ZodEnum<{
|
|
@@ -667,6 +691,12 @@ declare const rtfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
|
|
|
667
691
|
widthPt: z.ZodNumber;
|
|
668
692
|
heightPt: z.ZodNumber;
|
|
669
693
|
}, z.core.$strip>>>;
|
|
694
|
+
fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
695
|
+
family: z.ZodString;
|
|
696
|
+
bold: z.ZodBoolean;
|
|
697
|
+
italic: z.ZodBoolean;
|
|
698
|
+
base64: z.ZodString;
|
|
699
|
+
}, z.core.$strip>>>;
|
|
670
700
|
styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
671
701
|
paragraph: z.ZodOptional<z.ZodObject<{
|
|
672
702
|
alignment: z.ZodOptional<z.ZodEnum<{
|
|
@@ -867,6 +897,11 @@ declare const rtfContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, U
|
|
|
867
897
|
even: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
|
|
868
898
|
first: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
|
|
869
899
|
}, z.core.$strip>>;
|
|
900
|
+
watermarks: z.ZodOptional<z.ZodObject<{
|
|
901
|
+
default: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
|
|
902
|
+
even: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
|
|
903
|
+
first: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
|
|
904
|
+
}, z.core.$strip>>;
|
|
870
905
|
source: z.ZodOptional<z.ZodObject<{
|
|
871
906
|
format: z.ZodEnum<{
|
|
872
907
|
docx: "docx";
|
|
@@ -1032,6 +1067,7 @@ declare const rtfContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, U
|
|
|
1032
1067
|
fontScale: z.ZodOptional<z.ZodNumber>;
|
|
1033
1068
|
lineSpacingReduction: z.ZodOptional<z.ZodNumber>;
|
|
1034
1069
|
paintOrder: z.ZodOptional<z.ZodNumber>;
|
|
1070
|
+
readingOrder: z.ZodOptional<z.ZodNumber>;
|
|
1035
1071
|
sourcePath: z.ZodOptional<z.ZodString>;
|
|
1036
1072
|
source: z.ZodOptional<z.ZodObject<{
|
|
1037
1073
|
format: z.ZodEnum<{
|
|
@@ -2572,6 +2608,7 @@ declare const rtfContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, U
|
|
|
2572
2608
|
fontScale: z.ZodOptional<z.ZodNumber>;
|
|
2573
2609
|
lineSpacingReduction: z.ZodOptional<z.ZodNumber>;
|
|
2574
2610
|
paintOrder: z.ZodOptional<z.ZodNumber>;
|
|
2611
|
+
readingOrder: z.ZodOptional<z.ZodNumber>;
|
|
2575
2612
|
sourcePath: z.ZodOptional<z.ZodString>;
|
|
2576
2613
|
source: z.ZodOptional<z.ZodObject<{
|
|
2577
2614
|
format: z.ZodEnum<{
|
package/dist/header.cjs
CHANGED
|
@@ -340,6 +340,7 @@ function readRtfHeader(tokens, sink) {
|
|
|
340
340
|
marginBottomTwips: require_units.DEFAULT_MARGIN_BOTTOM_TWIPS
|
|
341
341
|
};
|
|
342
342
|
let metadata = {};
|
|
343
|
+
let direction;
|
|
343
344
|
let codepage = require_codepage.DEFAULT_CODEPAGE;
|
|
344
345
|
let defaultFontIndex;
|
|
345
346
|
let bodyStartIndex = 0;
|
|
@@ -356,6 +357,14 @@ function readRtfHeader(tokens, sink) {
|
|
|
356
357
|
codepage = charsetPage;
|
|
357
358
|
continue;
|
|
358
359
|
}
|
|
360
|
+
if (token.name === "rtldoc") {
|
|
361
|
+
direction = "rtl";
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
if (token.name === "ltrdoc") {
|
|
365
|
+
direction = "ltr";
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
359
368
|
if (token.param === void 0) continue;
|
|
360
369
|
switch (token.name) {
|
|
361
370
|
case "ansicpg":
|
|
@@ -424,7 +433,10 @@ function readRtfHeader(tokens, sink) {
|
|
|
424
433
|
lists,
|
|
425
434
|
revisionAuthors,
|
|
426
435
|
page,
|
|
427
|
-
metadata
|
|
436
|
+
metadata: {
|
|
437
|
+
...metadata,
|
|
438
|
+
...direction === void 0 ? {} : { direction }
|
|
439
|
+
},
|
|
428
440
|
bodyStartIndex
|
|
429
441
|
};
|
|
430
442
|
}
|
package/dist/header.js
CHANGED
|
@@ -339,6 +339,7 @@ function readRtfHeader(tokens, sink) {
|
|
|
339
339
|
marginBottomTwips: DEFAULT_MARGIN_BOTTOM_TWIPS
|
|
340
340
|
};
|
|
341
341
|
let metadata = {};
|
|
342
|
+
let direction;
|
|
342
343
|
let codepage = DEFAULT_CODEPAGE;
|
|
343
344
|
let defaultFontIndex;
|
|
344
345
|
let bodyStartIndex = 0;
|
|
@@ -355,6 +356,14 @@ function readRtfHeader(tokens, sink) {
|
|
|
355
356
|
codepage = charsetPage;
|
|
356
357
|
continue;
|
|
357
358
|
}
|
|
359
|
+
if (token.name === "rtldoc") {
|
|
360
|
+
direction = "rtl";
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
if (token.name === "ltrdoc") {
|
|
364
|
+
direction = "ltr";
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
358
367
|
if (token.param === void 0) continue;
|
|
359
368
|
switch (token.name) {
|
|
360
369
|
case "ansicpg":
|
|
@@ -423,7 +432,10 @@ function readRtfHeader(tokens, sink) {
|
|
|
423
432
|
lists,
|
|
424
433
|
revisionAuthors,
|
|
425
434
|
page,
|
|
426
|
-
metadata
|
|
435
|
+
metadata: {
|
|
436
|
+
...metadata,
|
|
437
|
+
...direction === void 0 ? {} : { direction }
|
|
438
|
+
},
|
|
427
439
|
bodyStartIndex
|
|
428
440
|
};
|
|
429
441
|
}
|
package/dist/read.cjs
CHANGED
|
@@ -186,12 +186,15 @@ function defaultCharacterState() {
|
|
|
186
186
|
fontIndex: void 0,
|
|
187
187
|
sizeHalfPoints: 24,
|
|
188
188
|
colorIndex: void 0,
|
|
189
|
+
verticalAlign: void 0,
|
|
190
|
+
direction: void 0,
|
|
189
191
|
revision: require_constructs.NO_REVISION
|
|
190
192
|
};
|
|
191
193
|
}
|
|
192
194
|
function defaultParagraphState() {
|
|
193
195
|
return {
|
|
194
196
|
alignment: void 0,
|
|
197
|
+
direction: void 0,
|
|
195
198
|
indentLeftTwips: 0,
|
|
196
199
|
indentFirstLineTwips: 0,
|
|
197
200
|
spaceBeforeTwips: 0,
|
|
@@ -235,6 +238,8 @@ function runKey(char, fontName, color, hyperlink) {
|
|
|
235
238
|
String(char.sizeHalfPoints),
|
|
236
239
|
color === void 0 ? "" : `${String(color.r)},${String(color.g)},${String(color.b)}`,
|
|
237
240
|
hyperlink ?? "",
|
|
241
|
+
char.verticalAlign ?? "",
|
|
242
|
+
char.direction ?? "",
|
|
238
243
|
JSON.stringify(char.revision)
|
|
239
244
|
].join("|");
|
|
240
245
|
}
|
|
@@ -329,6 +334,7 @@ function freshAccumulatorState() {
|
|
|
329
334
|
pendingCellDefinitions: [],
|
|
330
335
|
pendingCell: require_cell_format.newPendingCell(),
|
|
331
336
|
rowLeftTwips: 0,
|
|
337
|
+
rowDirection: void 0,
|
|
332
338
|
paragraphSerial: 0,
|
|
333
339
|
openBookmarks: /* @__PURE__ */ new Map(),
|
|
334
340
|
sectionBlockExtents: [],
|
|
@@ -356,6 +362,7 @@ var ContentBuilder = class {
|
|
|
356
362
|
pendingCellDefinitions = [];
|
|
357
363
|
pendingCell = require_cell_format.newPendingCell();
|
|
358
364
|
rowLeftTwips = 0;
|
|
365
|
+
rowDirection;
|
|
359
366
|
paragraphSerial = 0;
|
|
360
367
|
openBookmarks = /* @__PURE__ */ new Map();
|
|
361
368
|
sectionBlockExtents = [];
|
|
@@ -525,6 +532,7 @@ var ContentBuilder = class {
|
|
|
525
532
|
headingLevel
|
|
526
533
|
},
|
|
527
534
|
...para.alignment === void 0 ? {} : { alignment: para.alignment },
|
|
535
|
+
...para.direction === void 0 ? {} : { direction: para.direction },
|
|
528
536
|
...para.indentLeftTwips === 0 ? {} : { indentLeftPt: require_units.twipsToPoints(para.indentLeftTwips) },
|
|
529
537
|
...para.indentFirstLineTwips === 0 ? {} : { indentFirstLinePt: require_units.twipsToPoints(para.indentFirstLineTwips) },
|
|
530
538
|
...para.spaceBeforeTwips === 0 ? {} : { spacingBeforePt: require_units.twipsToPoints(para.spaceBeforeTwips) },
|
|
@@ -560,10 +568,14 @@ var ContentBuilder = class {
|
|
|
560
568
|
this.pendingCellDefinitions = [];
|
|
561
569
|
this.pendingCell = require_cell_format.newPendingCell();
|
|
562
570
|
this.rowLeftTwips = 0;
|
|
571
|
+
this.rowDirection = void 0;
|
|
563
572
|
}
|
|
564
573
|
setRowLeft(twips) {
|
|
565
574
|
this.rowLeftTwips = twips;
|
|
566
575
|
}
|
|
576
|
+
setRowDirection(direction) {
|
|
577
|
+
this.rowDirection = direction;
|
|
578
|
+
}
|
|
567
579
|
applyCellDefinition(name, param) {
|
|
568
580
|
return require_cell_format.applyCellDefinitionControlWord(name, param, this.pendingCell);
|
|
569
581
|
}
|
|
@@ -591,7 +603,8 @@ var ContentBuilder = class {
|
|
|
591
603
|
}
|
|
592
604
|
this.tableRows.push({
|
|
593
605
|
cells: this.rowCells,
|
|
594
|
-
definitions: this.pendingCellDefinitions
|
|
606
|
+
definitions: this.pendingCellDefinitions,
|
|
607
|
+
direction: this.rowDirection
|
|
595
608
|
});
|
|
596
609
|
if (this.tableColumnRights.length === 0) this.tableColumnRights = [...this.pendingCellRights];
|
|
597
610
|
this.rowCells = [];
|
|
@@ -619,30 +632,34 @@ var ContentBuilder = class {
|
|
|
619
632
|
}
|
|
620
633
|
return indices;
|
|
621
634
|
});
|
|
622
|
-
return rows.map((row, rowIndex) => ({
|
|
623
|
-
|
|
624
|
-
cellIndex
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
if (
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
635
|
+
return rows.map((row, rowIndex) => ({
|
|
636
|
+
...row.direction === void 0 ? {} : { direction: row.direction },
|
|
637
|
+
cells: row.cells.map((cell, cellIndex) => ({
|
|
638
|
+
cell,
|
|
639
|
+
cellIndex
|
|
640
|
+
})).filter(({ cellIndex }) => row.definitions[cellIndex]?.horizontalMergeContinuation !== true).map(({ cell, cellIndex }) => {
|
|
641
|
+
const definition = row.definitions[cellIndex];
|
|
642
|
+
if (definition?.verticalMergeContinuation === true) return { blocks: [] };
|
|
643
|
+
const colSpan = horizontalSpanAt(row.definitions, cellIndex);
|
|
644
|
+
const column = columnIndices[rowIndex]?.[cellIndex];
|
|
645
|
+
let rowSpan = 1;
|
|
646
|
+
if (definition?.verticalMergeFirst === true && column !== void 0) for (let next = rowIndex + 1; next < rows.length; next += 1) {
|
|
647
|
+
const matchIndex = columnIndices[next]?.indexOf(column) ?? -1;
|
|
648
|
+
if ((matchIndex === -1 ? void 0 : rows[next]?.definitions[matchIndex])?.verticalMergeContinuation !== true) break;
|
|
649
|
+
rowSpan += 1;
|
|
650
|
+
}
|
|
651
|
+
const borders = this.resolveBorders(definition);
|
|
652
|
+
const background = definition === void 0 ? void 0 : require_cell_format.resolveCellFill(definition, (index) => this.header.colors[index]);
|
|
653
|
+
return {
|
|
654
|
+
blocks: cell.blocks,
|
|
655
|
+
...colSpan > 1 ? { colSpan } : {},
|
|
656
|
+
...rowSpan > 1 ? { rowSpan } : {},
|
|
657
|
+
...background === void 0 ? {} : { background },
|
|
658
|
+
...borders === void 0 ? {} : { borders },
|
|
659
|
+
...definition?.verticalAlign === void 0 ? {} : { verticalAlign: definition.verticalAlign }
|
|
660
|
+
};
|
|
661
|
+
})
|
|
662
|
+
}));
|
|
646
663
|
}
|
|
647
664
|
resolveBorders(definition) {
|
|
648
665
|
if (definition === void 0) return;
|
|
@@ -699,6 +716,7 @@ var ContentBuilder = class {
|
|
|
699
716
|
pendingCellDefinitions: this.pendingCellDefinitions,
|
|
700
717
|
pendingCell: this.pendingCell,
|
|
701
718
|
rowLeftTwips: this.rowLeftTwips,
|
|
719
|
+
rowDirection: this.rowDirection,
|
|
702
720
|
paragraphSerial: this.paragraphSerial,
|
|
703
721
|
openBookmarks: this.openBookmarks,
|
|
704
722
|
sectionBlockExtents: this.sectionBlockExtents,
|
|
@@ -723,6 +741,7 @@ var ContentBuilder = class {
|
|
|
723
741
|
this.pendingCellDefinitions = saved.pendingCellDefinitions;
|
|
724
742
|
this.pendingCell = saved.pendingCell;
|
|
725
743
|
this.rowLeftTwips = saved.rowLeftTwips;
|
|
744
|
+
this.rowDirection = saved.rowDirection;
|
|
726
745
|
this.paragraphSerial = saved.paragraphSerial;
|
|
727
746
|
this.openBookmarks = saved.openBookmarks;
|
|
728
747
|
this.sectionBlockExtents = saved.sectionBlockExtents;
|
|
@@ -823,7 +842,9 @@ function buildRunFields(char, fontName, color, hyperlink) {
|
|
|
823
842
|
...fontName === void 0 || fontName.length === 0 ? {} : { fontFamily: fontName },
|
|
824
843
|
sizePt: require_units.halfPointsToPoints(char.sizeHalfPoints),
|
|
825
844
|
...color === void 0 ? {} : { color },
|
|
826
|
-
...hyperlink === void 0 ? {} : { hyperlink }
|
|
845
|
+
...hyperlink === void 0 ? {} : { hyperlink },
|
|
846
|
+
...char.verticalAlign === void 0 ? {} : { verticalAlign: char.verticalAlign },
|
|
847
|
+
...char.direction === void 0 ? {} : { direction: char.direction }
|
|
827
848
|
};
|
|
828
849
|
}
|
|
829
850
|
function buildPicture(picture, sink) {
|
|
@@ -1325,6 +1346,27 @@ function applyCharacterControlWord(name, param, state, header) {
|
|
|
1325
1346
|
case "uc":
|
|
1326
1347
|
if (param !== void 0 && param >= 0) state.uc = param;
|
|
1327
1348
|
return true;
|
|
1349
|
+
case "super":
|
|
1350
|
+
state.char.verticalAlign = "superscript";
|
|
1351
|
+
return true;
|
|
1352
|
+
case "sub":
|
|
1353
|
+
state.char.verticalAlign = "subscript";
|
|
1354
|
+
return true;
|
|
1355
|
+
case "up":
|
|
1356
|
+
state.char.verticalAlign = param === void 0 || param > 0 ? "superscript" : param < 0 ? "subscript" : void 0;
|
|
1357
|
+
return true;
|
|
1358
|
+
case "dn":
|
|
1359
|
+
state.char.verticalAlign = param === void 0 || param > 0 ? "subscript" : param < 0 ? "superscript" : void 0;
|
|
1360
|
+
return true;
|
|
1361
|
+
case "nosupersub":
|
|
1362
|
+
state.char.verticalAlign = void 0;
|
|
1363
|
+
return true;
|
|
1364
|
+
case "rtlch":
|
|
1365
|
+
state.char.direction = "rtl";
|
|
1366
|
+
return true;
|
|
1367
|
+
case "ltrch":
|
|
1368
|
+
state.char.direction = "ltr";
|
|
1369
|
+
return true;
|
|
1328
1370
|
case "revised":
|
|
1329
1371
|
state.char.revision = {
|
|
1330
1372
|
...state.char.revision,
|
|
@@ -1418,6 +1460,12 @@ function applyParagraphControlWord(name, param, state) {
|
|
|
1418
1460
|
case "s":
|
|
1419
1461
|
state.para.styleIndex = param;
|
|
1420
1462
|
return true;
|
|
1463
|
+
case "rtlpar":
|
|
1464
|
+
state.para.direction = "rtl";
|
|
1465
|
+
return true;
|
|
1466
|
+
case "ltrpar":
|
|
1467
|
+
state.para.direction = "ltr";
|
|
1468
|
+
return true;
|
|
1421
1469
|
case "outlinelevel":
|
|
1422
1470
|
state.para.outlineLevel = param === void 0 || param > 8 ? void 0 : param;
|
|
1423
1471
|
return true;
|
|
@@ -1508,6 +1556,12 @@ function applyStructureControlWord(name, param, state, builder, section, sink) {
|
|
|
1508
1556
|
case "trleft":
|
|
1509
1557
|
builder.setRowLeft(param ?? 0);
|
|
1510
1558
|
return true;
|
|
1559
|
+
case "rtlrow":
|
|
1560
|
+
builder.setRowDirection("rtl");
|
|
1561
|
+
return true;
|
|
1562
|
+
case "ltrrow":
|
|
1563
|
+
builder.setRowDirection("ltr");
|
|
1564
|
+
return true;
|
|
1511
1565
|
case "cellx":
|
|
1512
1566
|
if (param !== void 0) builder.addCellBoundary(param);
|
|
1513
1567
|
return true;
|
package/dist/read.js
CHANGED
|
@@ -185,12 +185,15 @@ function defaultCharacterState() {
|
|
|
185
185
|
fontIndex: void 0,
|
|
186
186
|
sizeHalfPoints: 24,
|
|
187
187
|
colorIndex: void 0,
|
|
188
|
+
verticalAlign: void 0,
|
|
189
|
+
direction: void 0,
|
|
188
190
|
revision: NO_REVISION
|
|
189
191
|
};
|
|
190
192
|
}
|
|
191
193
|
function defaultParagraphState() {
|
|
192
194
|
return {
|
|
193
195
|
alignment: void 0,
|
|
196
|
+
direction: void 0,
|
|
194
197
|
indentLeftTwips: 0,
|
|
195
198
|
indentFirstLineTwips: 0,
|
|
196
199
|
spaceBeforeTwips: 0,
|
|
@@ -234,6 +237,8 @@ function runKey(char, fontName, color, hyperlink) {
|
|
|
234
237
|
String(char.sizeHalfPoints),
|
|
235
238
|
color === void 0 ? "" : `${String(color.r)},${String(color.g)},${String(color.b)}`,
|
|
236
239
|
hyperlink ?? "",
|
|
240
|
+
char.verticalAlign ?? "",
|
|
241
|
+
char.direction ?? "",
|
|
237
242
|
JSON.stringify(char.revision)
|
|
238
243
|
].join("|");
|
|
239
244
|
}
|
|
@@ -328,6 +333,7 @@ function freshAccumulatorState() {
|
|
|
328
333
|
pendingCellDefinitions: [],
|
|
329
334
|
pendingCell: newPendingCell(),
|
|
330
335
|
rowLeftTwips: 0,
|
|
336
|
+
rowDirection: void 0,
|
|
331
337
|
paragraphSerial: 0,
|
|
332
338
|
openBookmarks: /* @__PURE__ */ new Map(),
|
|
333
339
|
sectionBlockExtents: [],
|
|
@@ -355,6 +361,7 @@ var ContentBuilder = class {
|
|
|
355
361
|
pendingCellDefinitions = [];
|
|
356
362
|
pendingCell = newPendingCell();
|
|
357
363
|
rowLeftTwips = 0;
|
|
364
|
+
rowDirection;
|
|
358
365
|
paragraphSerial = 0;
|
|
359
366
|
openBookmarks = /* @__PURE__ */ new Map();
|
|
360
367
|
sectionBlockExtents = [];
|
|
@@ -524,6 +531,7 @@ var ContentBuilder = class {
|
|
|
524
531
|
headingLevel
|
|
525
532
|
},
|
|
526
533
|
...para.alignment === void 0 ? {} : { alignment: para.alignment },
|
|
534
|
+
...para.direction === void 0 ? {} : { direction: para.direction },
|
|
527
535
|
...para.indentLeftTwips === 0 ? {} : { indentLeftPt: twipsToPoints(para.indentLeftTwips) },
|
|
528
536
|
...para.indentFirstLineTwips === 0 ? {} : { indentFirstLinePt: twipsToPoints(para.indentFirstLineTwips) },
|
|
529
537
|
...para.spaceBeforeTwips === 0 ? {} : { spacingBeforePt: twipsToPoints(para.spaceBeforeTwips) },
|
|
@@ -559,10 +567,14 @@ var ContentBuilder = class {
|
|
|
559
567
|
this.pendingCellDefinitions = [];
|
|
560
568
|
this.pendingCell = newPendingCell();
|
|
561
569
|
this.rowLeftTwips = 0;
|
|
570
|
+
this.rowDirection = void 0;
|
|
562
571
|
}
|
|
563
572
|
setRowLeft(twips) {
|
|
564
573
|
this.rowLeftTwips = twips;
|
|
565
574
|
}
|
|
575
|
+
setRowDirection(direction) {
|
|
576
|
+
this.rowDirection = direction;
|
|
577
|
+
}
|
|
566
578
|
applyCellDefinition(name, param) {
|
|
567
579
|
return applyCellDefinitionControlWord(name, param, this.pendingCell);
|
|
568
580
|
}
|
|
@@ -590,7 +602,8 @@ var ContentBuilder = class {
|
|
|
590
602
|
}
|
|
591
603
|
this.tableRows.push({
|
|
592
604
|
cells: this.rowCells,
|
|
593
|
-
definitions: this.pendingCellDefinitions
|
|
605
|
+
definitions: this.pendingCellDefinitions,
|
|
606
|
+
direction: this.rowDirection
|
|
594
607
|
});
|
|
595
608
|
if (this.tableColumnRights.length === 0) this.tableColumnRights = [...this.pendingCellRights];
|
|
596
609
|
this.rowCells = [];
|
|
@@ -618,30 +631,34 @@ var ContentBuilder = class {
|
|
|
618
631
|
}
|
|
619
632
|
return indices;
|
|
620
633
|
});
|
|
621
|
-
return rows.map((row, rowIndex) => ({
|
|
622
|
-
|
|
623
|
-
cellIndex
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
if (
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
634
|
+
return rows.map((row, rowIndex) => ({
|
|
635
|
+
...row.direction === void 0 ? {} : { direction: row.direction },
|
|
636
|
+
cells: row.cells.map((cell, cellIndex) => ({
|
|
637
|
+
cell,
|
|
638
|
+
cellIndex
|
|
639
|
+
})).filter(({ cellIndex }) => row.definitions[cellIndex]?.horizontalMergeContinuation !== true).map(({ cell, cellIndex }) => {
|
|
640
|
+
const definition = row.definitions[cellIndex];
|
|
641
|
+
if (definition?.verticalMergeContinuation === true) return { blocks: [] };
|
|
642
|
+
const colSpan = horizontalSpanAt(row.definitions, cellIndex);
|
|
643
|
+
const column = columnIndices[rowIndex]?.[cellIndex];
|
|
644
|
+
let rowSpan = 1;
|
|
645
|
+
if (definition?.verticalMergeFirst === true && column !== void 0) for (let next = rowIndex + 1; next < rows.length; next += 1) {
|
|
646
|
+
const matchIndex = columnIndices[next]?.indexOf(column) ?? -1;
|
|
647
|
+
if ((matchIndex === -1 ? void 0 : rows[next]?.definitions[matchIndex])?.verticalMergeContinuation !== true) break;
|
|
648
|
+
rowSpan += 1;
|
|
649
|
+
}
|
|
650
|
+
const borders = this.resolveBorders(definition);
|
|
651
|
+
const background = definition === void 0 ? void 0 : resolveCellFill(definition, (index) => this.header.colors[index]);
|
|
652
|
+
return {
|
|
653
|
+
blocks: cell.blocks,
|
|
654
|
+
...colSpan > 1 ? { colSpan } : {},
|
|
655
|
+
...rowSpan > 1 ? { rowSpan } : {},
|
|
656
|
+
...background === void 0 ? {} : { background },
|
|
657
|
+
...borders === void 0 ? {} : { borders },
|
|
658
|
+
...definition?.verticalAlign === void 0 ? {} : { verticalAlign: definition.verticalAlign }
|
|
659
|
+
};
|
|
660
|
+
})
|
|
661
|
+
}));
|
|
645
662
|
}
|
|
646
663
|
resolveBorders(definition) {
|
|
647
664
|
if (definition === void 0) return;
|
|
@@ -698,6 +715,7 @@ var ContentBuilder = class {
|
|
|
698
715
|
pendingCellDefinitions: this.pendingCellDefinitions,
|
|
699
716
|
pendingCell: this.pendingCell,
|
|
700
717
|
rowLeftTwips: this.rowLeftTwips,
|
|
718
|
+
rowDirection: this.rowDirection,
|
|
701
719
|
paragraphSerial: this.paragraphSerial,
|
|
702
720
|
openBookmarks: this.openBookmarks,
|
|
703
721
|
sectionBlockExtents: this.sectionBlockExtents,
|
|
@@ -722,6 +740,7 @@ var ContentBuilder = class {
|
|
|
722
740
|
this.pendingCellDefinitions = saved.pendingCellDefinitions;
|
|
723
741
|
this.pendingCell = saved.pendingCell;
|
|
724
742
|
this.rowLeftTwips = saved.rowLeftTwips;
|
|
743
|
+
this.rowDirection = saved.rowDirection;
|
|
725
744
|
this.paragraphSerial = saved.paragraphSerial;
|
|
726
745
|
this.openBookmarks = saved.openBookmarks;
|
|
727
746
|
this.sectionBlockExtents = saved.sectionBlockExtents;
|
|
@@ -822,7 +841,9 @@ function buildRunFields(char, fontName, color, hyperlink) {
|
|
|
822
841
|
...fontName === void 0 || fontName.length === 0 ? {} : { fontFamily: fontName },
|
|
823
842
|
sizePt: halfPointsToPoints(char.sizeHalfPoints),
|
|
824
843
|
...color === void 0 ? {} : { color },
|
|
825
|
-
...hyperlink === void 0 ? {} : { hyperlink }
|
|
844
|
+
...hyperlink === void 0 ? {} : { hyperlink },
|
|
845
|
+
...char.verticalAlign === void 0 ? {} : { verticalAlign: char.verticalAlign },
|
|
846
|
+
...char.direction === void 0 ? {} : { direction: char.direction }
|
|
826
847
|
};
|
|
827
848
|
}
|
|
828
849
|
function buildPicture(picture, sink) {
|
|
@@ -1324,6 +1345,27 @@ function applyCharacterControlWord(name, param, state, header) {
|
|
|
1324
1345
|
case "uc":
|
|
1325
1346
|
if (param !== void 0 && param >= 0) state.uc = param;
|
|
1326
1347
|
return true;
|
|
1348
|
+
case "super":
|
|
1349
|
+
state.char.verticalAlign = "superscript";
|
|
1350
|
+
return true;
|
|
1351
|
+
case "sub":
|
|
1352
|
+
state.char.verticalAlign = "subscript";
|
|
1353
|
+
return true;
|
|
1354
|
+
case "up":
|
|
1355
|
+
state.char.verticalAlign = param === void 0 || param > 0 ? "superscript" : param < 0 ? "subscript" : void 0;
|
|
1356
|
+
return true;
|
|
1357
|
+
case "dn":
|
|
1358
|
+
state.char.verticalAlign = param === void 0 || param > 0 ? "subscript" : param < 0 ? "superscript" : void 0;
|
|
1359
|
+
return true;
|
|
1360
|
+
case "nosupersub":
|
|
1361
|
+
state.char.verticalAlign = void 0;
|
|
1362
|
+
return true;
|
|
1363
|
+
case "rtlch":
|
|
1364
|
+
state.char.direction = "rtl";
|
|
1365
|
+
return true;
|
|
1366
|
+
case "ltrch":
|
|
1367
|
+
state.char.direction = "ltr";
|
|
1368
|
+
return true;
|
|
1327
1369
|
case "revised":
|
|
1328
1370
|
state.char.revision = {
|
|
1329
1371
|
...state.char.revision,
|
|
@@ -1417,6 +1459,12 @@ function applyParagraphControlWord(name, param, state) {
|
|
|
1417
1459
|
case "s":
|
|
1418
1460
|
state.para.styleIndex = param;
|
|
1419
1461
|
return true;
|
|
1462
|
+
case "rtlpar":
|
|
1463
|
+
state.para.direction = "rtl";
|
|
1464
|
+
return true;
|
|
1465
|
+
case "ltrpar":
|
|
1466
|
+
state.para.direction = "ltr";
|
|
1467
|
+
return true;
|
|
1420
1468
|
case "outlinelevel":
|
|
1421
1469
|
state.para.outlineLevel = param === void 0 || param > 8 ? void 0 : param;
|
|
1422
1470
|
return true;
|
|
@@ -1507,6 +1555,12 @@ function applyStructureControlWord(name, param, state, builder, section, sink) {
|
|
|
1507
1555
|
case "trleft":
|
|
1508
1556
|
builder.setRowLeft(param ?? 0);
|
|
1509
1557
|
return true;
|
|
1558
|
+
case "rtlrow":
|
|
1559
|
+
builder.setRowDirection("rtl");
|
|
1560
|
+
return true;
|
|
1561
|
+
case "ltrrow":
|
|
1562
|
+
builder.setRowDirection("ltr");
|
|
1563
|
+
return true;
|
|
1510
1564
|
case "cellx":
|
|
1511
1565
|
if (param !== void 0) builder.addCellBoundary(param);
|
|
1512
1566
|
return true;
|
package/dist/write.cjs
CHANGED
|
@@ -353,6 +353,8 @@ var RtfWriter = class {
|
|
|
353
353
|
writeHeader(document) {
|
|
354
354
|
this.raw(`{\\rtf1\\ansi\\ansicpg${String(OUTPUT_CODEPAGE)}\\deff0\\uc1`);
|
|
355
355
|
this.writeDocumentGeometry(document);
|
|
356
|
+
if (document.metadata.direction === "rtl") this.raw("\\rtldoc");
|
|
357
|
+
else if (document.metadata.direction === "ltr") this.raw("\\ltrdoc");
|
|
356
358
|
this.writeFontTable();
|
|
357
359
|
this.writeColorTable();
|
|
358
360
|
this.writeStyleSheet();
|
|
@@ -537,6 +539,8 @@ var RtfWriter = class {
|
|
|
537
539
|
if (styleHandle !== void 0 && level !== void 0) out += `\\s${String(styleHandle)}\\outlinelevel${String(level - 1)}`;
|
|
538
540
|
const alignment = paragraph.alignment === void 0 ? void 0 : ALIGNMENT_CONTROL_WORDS.get(paragraph.alignment);
|
|
539
541
|
if (alignment !== void 0) out += alignment;
|
|
542
|
+
if (paragraph.direction === "rtl") out += "\\rtlpar";
|
|
543
|
+
else if (paragraph.direction === "ltr") out += "\\ltrpar";
|
|
540
544
|
const list = paragraph.list;
|
|
541
545
|
if (list !== void 0) {
|
|
542
546
|
const numId = list.numId;
|
|
@@ -591,6 +595,10 @@ var RtfWriter = class {
|
|
|
591
595
|
if (run.italic === true) out += "\\i";
|
|
592
596
|
if (run.underline === true) out += "\\ul";
|
|
593
597
|
if (run.strike === true) out += "\\strike";
|
|
598
|
+
if (run.verticalAlign === "superscript") out += "\\super";
|
|
599
|
+
else if (run.verticalAlign === "subscript") out += "\\sub";
|
|
600
|
+
if (run.direction === "rtl") out += "\\rtlch";
|
|
601
|
+
else if (run.direction === "ltr") out += "\\ltrch";
|
|
594
602
|
const colorIndex = colorIndexOf(run.color, this.tables.colors);
|
|
595
603
|
if (colorIndex !== void 0) out += `\\cf${String(colorIndex)}`;
|
|
596
604
|
return out;
|
|
@@ -614,7 +622,7 @@ var RtfWriter = class {
|
|
|
614
622
|
});
|
|
615
623
|
}
|
|
616
624
|
}
|
|
617
|
-
const rowDefinition = `\\trowd\\trgaph108\\trleft0${definitions.join("")}`;
|
|
625
|
+
const rowDefinition = `\\trowd\\trgaph108\\trleft0${row.direction === "rtl" ? "\\rtlrow" : row.direction === "ltr" ? "\\ltrrow" : ""}${definitions.join("")}`;
|
|
618
626
|
this.line(rowDefinition);
|
|
619
627
|
for (const mark of marks) {
|
|
620
628
|
this.writeCellBlocks(mark.empty ? [] : mark.cell.blocks);
|
|
@@ -630,6 +638,8 @@ var RtfWriter = class {
|
|
|
630
638
|
else if ((cell.rowSpan ?? 1) > 1) out += "\\clvmgf";
|
|
631
639
|
if (horizontal === "mergeFirst") out += "\\clmgf";
|
|
632
640
|
else if (horizontal === "mergeContinuation") return `${out}\\clmrg\\cellx${String(rightTwips)}`;
|
|
641
|
+
if (cell.verticalAlign === "center") out += "\\clvertalc";
|
|
642
|
+
else if (cell.verticalAlign === "bottom") out += "\\clvertalb";
|
|
633
643
|
const borders = cell.borders;
|
|
634
644
|
if (borders !== void 0) for (const side of CELL_BORDER_ORDER) {
|
|
635
645
|
const border = borders[side];
|
package/dist/write.js
CHANGED
|
@@ -352,6 +352,8 @@ var RtfWriter = class {
|
|
|
352
352
|
writeHeader(document) {
|
|
353
353
|
this.raw(`{\\rtf1\\ansi\\ansicpg${String(OUTPUT_CODEPAGE)}\\deff0\\uc1`);
|
|
354
354
|
this.writeDocumentGeometry(document);
|
|
355
|
+
if (document.metadata.direction === "rtl") this.raw("\\rtldoc");
|
|
356
|
+
else if (document.metadata.direction === "ltr") this.raw("\\ltrdoc");
|
|
355
357
|
this.writeFontTable();
|
|
356
358
|
this.writeColorTable();
|
|
357
359
|
this.writeStyleSheet();
|
|
@@ -536,6 +538,8 @@ var RtfWriter = class {
|
|
|
536
538
|
if (styleHandle !== void 0 && level !== void 0) out += `\\s${String(styleHandle)}\\outlinelevel${String(level - 1)}`;
|
|
537
539
|
const alignment = paragraph.alignment === void 0 ? void 0 : ALIGNMENT_CONTROL_WORDS.get(paragraph.alignment);
|
|
538
540
|
if (alignment !== void 0) out += alignment;
|
|
541
|
+
if (paragraph.direction === "rtl") out += "\\rtlpar";
|
|
542
|
+
else if (paragraph.direction === "ltr") out += "\\ltrpar";
|
|
539
543
|
const list = paragraph.list;
|
|
540
544
|
if (list !== void 0) {
|
|
541
545
|
const numId = list.numId;
|
|
@@ -590,6 +594,10 @@ var RtfWriter = class {
|
|
|
590
594
|
if (run.italic === true) out += "\\i";
|
|
591
595
|
if (run.underline === true) out += "\\ul";
|
|
592
596
|
if (run.strike === true) out += "\\strike";
|
|
597
|
+
if (run.verticalAlign === "superscript") out += "\\super";
|
|
598
|
+
else if (run.verticalAlign === "subscript") out += "\\sub";
|
|
599
|
+
if (run.direction === "rtl") out += "\\rtlch";
|
|
600
|
+
else if (run.direction === "ltr") out += "\\ltrch";
|
|
593
601
|
const colorIndex = colorIndexOf(run.color, this.tables.colors);
|
|
594
602
|
if (colorIndex !== void 0) out += `\\cf${String(colorIndex)}`;
|
|
595
603
|
return out;
|
|
@@ -613,7 +621,7 @@ var RtfWriter = class {
|
|
|
613
621
|
});
|
|
614
622
|
}
|
|
615
623
|
}
|
|
616
|
-
const rowDefinition = `\\trowd\\trgaph108\\trleft0${definitions.join("")}`;
|
|
624
|
+
const rowDefinition = `\\trowd\\trgaph108\\trleft0${row.direction === "rtl" ? "\\rtlrow" : row.direction === "ltr" ? "\\ltrrow" : ""}${definitions.join("")}`;
|
|
617
625
|
this.line(rowDefinition);
|
|
618
626
|
for (const mark of marks) {
|
|
619
627
|
this.writeCellBlocks(mark.empty ? [] : mark.cell.blocks);
|
|
@@ -629,6 +637,8 @@ var RtfWriter = class {
|
|
|
629
637
|
else if ((cell.rowSpan ?? 1) > 1) out += "\\clvmgf";
|
|
630
638
|
if (horizontal === "mergeFirst") out += "\\clmgf";
|
|
631
639
|
else if (horizontal === "mergeContinuation") return `${out}\\clmrg\\cellx${String(rightTwips)}`;
|
|
640
|
+
if (cell.verticalAlign === "center") out += "\\clvertalc";
|
|
641
|
+
else if (cell.verticalAlign === "bottom") out += "\\clvertalb";
|
|
632
642
|
const borders = cell.borders;
|
|
633
643
|
if (borders !== void 0) for (const side of CELL_BORDER_ORDER) {
|
|
634
644
|
const border = borders[side];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rtf-codec",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "Hand-written Rich Text Format (RTF 1.9.1) reader and writer against the shared document-schema.js content pivot.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -82,8 +82,8 @@
|
|
|
82
82
|
"license": "MIT",
|
|
83
83
|
"packageManager": "pnpm@11.6.0",
|
|
84
84
|
"dependencies": {
|
|
85
|
-
"archive-codec": "1.
|
|
86
|
-
"document-schema.js": "7.
|
|
85
|
+
"archive-codec": "1.11.0",
|
|
86
|
+
"document-schema.js": "7.11.0",
|
|
87
87
|
"zod": "4.4.3"
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|