@cj-tech-master/excelts 9.6.1 → 10.0.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 +18 -3
- package/README_zh.md +18 -3
- package/dist/browser/modules/excel/cell.d.ts +4 -0
- package/dist/browser/modules/excel/note.js +5 -1
- package/dist/browser/modules/excel/row.js +35 -2
- package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +8 -1
- package/dist/browser/modules/excel/stream/workbook-writer.browser.js +22 -2
- package/dist/browser/modules/excel/types.d.ts +81 -0
- package/dist/browser/modules/excel/utils/drawing-utils.d.ts +8 -0
- package/dist/browser/modules/excel/utils/drawing-utils.js +19 -2
- package/dist/browser/modules/excel/workbook.browser.d.ts +16 -0
- package/dist/browser/modules/excel/workbook.browser.js +32 -2
- package/dist/browser/modules/excel/worksheet.d.ts +31 -1
- package/dist/browser/modules/excel/worksheet.js +83 -0
- package/dist/browser/modules/excel/xlsx/xform/comment/vml-shape-xform.d.ts +7 -0
- package/dist/browser/modules/excel/xlsx/xform/comment/vml-shape-xform.js +42 -8
- package/dist/browser/modules/excel/xlsx/xform/core/content-types-xform.js +3 -1
- package/dist/browser/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +5 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +18 -1
- package/dist/browser/modules/excel/xlsx/xform/drawing/blip-xform.d.ts +6 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/blip-xform.js +38 -11
- package/dist/browser/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.d.ts +1 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +5 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/pic-xform.d.ts +2 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/pic-xform.js +2 -1
- package/dist/browser/modules/excel/xlsx/xform/drawing/shape-xform.d.ts +47 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/shape-xform.js +109 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +10 -1
- package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +64 -1
- package/dist/browser/modules/pdf/builder/document-builder.js +22 -49
- package/dist/browser/modules/pdf/builder/pdf-editor.js +1 -1
- package/dist/browser/modules/pdf/core/pdf-stream.d.ts +28 -1
- package/dist/browser/modules/pdf/core/pdf-stream.js +38 -2
- package/dist/browser/modules/pdf/font/font-manager.d.ts +26 -0
- package/dist/browser/modules/pdf/font/font-manager.js +35 -18
- package/dist/browser/modules/pdf/render/page-renderer.d.ts +51 -3
- package/dist/browser/modules/pdf/render/page-renderer.js +111 -18
- package/dist/browser/modules/word/advanced/field-engine.js +45 -20
- package/dist/browser/modules/word/advanced/glossary.d.ts +10 -36
- package/dist/browser/modules/word/advanced/glossary.js +8 -9
- package/dist/browser/modules/word/advanced/math-convert.js +94 -12
- package/dist/browser/modules/word/advanced/ole-objects.d.ts +28 -0
- package/dist/browser/modules/word/advanced/ole-objects.js +122 -19
- package/dist/browser/modules/word/advanced/style-map.js +31 -10
- package/dist/browser/modules/word/builder/run-builders.d.ts +7 -1
- package/dist/browser/modules/word/builder/run-builders.js +7 -1
- package/dist/browser/modules/word/constants.d.ts +4 -0
- package/dist/browser/modules/word/constants.js +5 -1
- package/dist/browser/modules/word/convert/docx-to-semantic.d.ts +2 -1
- package/dist/browser/modules/word/convert/docx-to-semantic.js +135 -1
- package/dist/browser/modules/word/convert/html/html-import.d.ts +32 -1
- package/dist/browser/modules/word/convert/html/html-import.js +167 -14
- package/dist/browser/modules/word/convert/html/html.d.ts +2 -2
- package/dist/browser/modules/word/convert/html/html.js +1 -1
- package/dist/browser/modules/word/convert/markdown/markdown-import.d.ts +48 -18
- package/dist/browser/modules/word/convert/markdown/markdown-import.js +279 -69
- package/dist/browser/modules/word/convert/markdown/markdown.d.ts +1 -1
- package/dist/browser/modules/word/convert/odt/odt.js +407 -56
- package/dist/browser/modules/word/html.d.ts +2 -2
- package/dist/browser/modules/word/html.js +1 -1
- package/dist/browser/modules/word/index.base.d.ts +3 -3
- package/dist/browser/modules/word/index.base.js +1 -1
- package/dist/browser/modules/word/layout/layout-full.js +326 -19
- package/dist/browser/modules/word/layout/render-page.js +35 -8
- package/dist/browser/modules/word/markdown.d.ts +1 -1
- package/dist/browser/modules/word/query/compat.d.ts +10 -2
- package/dist/browser/modules/word/query/compat.js +29 -21
- package/dist/browser/modules/word/reader/docx-reader.js +105 -2
- package/dist/browser/modules/word/reader/math-parser.js +8 -2
- package/dist/browser/modules/word/security/cfb-reader.js +5 -5
- package/dist/browser/modules/word/types.d.ts +96 -1
- package/dist/browser/modules/word/writer/docx-packager.js +108 -2
- package/dist/browser/modules/word/writer/glossary-writer.d.ts +28 -0
- package/dist/browser/modules/word/writer/glossary-writer.js +121 -0
- package/dist/browser/modules/word/writer/header-footer-writer.js +105 -20
- package/dist/browser/modules/word/writer/math-writer.js +7 -2
- package/dist/browser/utils/font-metrics.d.ts +8 -0
- package/dist/browser/utils/font-metrics.js +43 -0
- package/dist/browser/utils/theme-colors.js +4 -1
- package/dist/cjs/modules/excel/note.js +5 -1
- package/dist/cjs/modules/excel/row.js +35 -2
- package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +22 -2
- package/dist/cjs/modules/excel/utils/drawing-utils.js +19 -2
- package/dist/cjs/modules/excel/workbook.browser.js +31 -1
- package/dist/cjs/modules/excel/worksheet.js +83 -0
- package/dist/cjs/modules/excel/xlsx/xform/comment/vml-shape-xform.js +42 -8
- package/dist/cjs/modules/excel/xlsx/xform/core/content-types-xform.js +3 -1
- package/dist/cjs/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +5 -0
- package/dist/cjs/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +18 -1
- package/dist/cjs/modules/excel/xlsx/xform/drawing/blip-xform.js +38 -11
- package/dist/cjs/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +5 -0
- package/dist/cjs/modules/excel/xlsx/xform/drawing/pic-xform.js +2 -1
- package/dist/cjs/modules/excel/xlsx/xform/drawing/shape-xform.js +112 -0
- package/dist/cjs/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +10 -1
- package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +64 -1
- package/dist/cjs/modules/pdf/builder/document-builder.js +21 -48
- package/dist/cjs/modules/pdf/builder/pdf-editor.js +1 -1
- package/dist/cjs/modules/pdf/core/pdf-stream.js +38 -2
- package/dist/cjs/modules/pdf/font/font-manager.js +35 -18
- package/dist/cjs/modules/pdf/render/page-renderer.js +112 -18
- package/dist/cjs/modules/word/advanced/field-engine.js +45 -20
- package/dist/cjs/modules/word/advanced/glossary.js +8 -9
- package/dist/cjs/modules/word/advanced/math-convert.js +94 -12
- package/dist/cjs/modules/word/advanced/ole-objects.js +123 -19
- package/dist/cjs/modules/word/advanced/style-map.js +31 -10
- package/dist/cjs/modules/word/builder/run-builders.js +7 -1
- package/dist/cjs/modules/word/constants.js +5 -1
- package/dist/cjs/modules/word/convert/docx-to-semantic.js +135 -1
- package/dist/cjs/modules/word/convert/html/html-import.js +168 -14
- package/dist/cjs/modules/word/convert/html/html.js +2 -1
- package/dist/cjs/modules/word/convert/markdown/markdown-import.js +279 -69
- package/dist/cjs/modules/word/convert/odt/odt.js +407 -56
- package/dist/cjs/modules/word/html.js +2 -1
- package/dist/cjs/modules/word/index.base.js +4 -3
- package/dist/cjs/modules/word/layout/layout-full.js +325 -18
- package/dist/cjs/modules/word/layout/render-page.js +35 -8
- package/dist/cjs/modules/word/query/compat.js +29 -21
- package/dist/cjs/modules/word/reader/docx-reader.js +104 -1
- package/dist/cjs/modules/word/reader/math-parser.js +8 -2
- package/dist/cjs/modules/word/security/cfb-reader.js +5 -5
- package/dist/cjs/modules/word/writer/docx-packager.js +108 -2
- package/dist/cjs/modules/word/writer/glossary-writer.js +124 -0
- package/dist/cjs/modules/word/writer/header-footer-writer.js +105 -20
- package/dist/cjs/modules/word/writer/math-writer.js +7 -2
- package/dist/cjs/utils/font-metrics.js +44 -0
- package/dist/cjs/utils/theme-colors.js +4 -1
- package/dist/esm/modules/excel/note.js +5 -1
- package/dist/esm/modules/excel/row.js +35 -2
- package/dist/esm/modules/excel/stream/workbook-writer.browser.js +22 -2
- package/dist/esm/modules/excel/utils/drawing-utils.js +19 -2
- package/dist/esm/modules/excel/workbook.browser.js +32 -2
- package/dist/esm/modules/excel/worksheet.js +83 -0
- package/dist/esm/modules/excel/xlsx/xform/comment/vml-shape-xform.js +42 -8
- package/dist/esm/modules/excel/xlsx/xform/core/content-types-xform.js +3 -1
- package/dist/esm/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +5 -0
- package/dist/esm/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +18 -1
- package/dist/esm/modules/excel/xlsx/xform/drawing/blip-xform.js +38 -11
- package/dist/esm/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +5 -0
- package/dist/esm/modules/excel/xlsx/xform/drawing/pic-xform.js +2 -1
- package/dist/esm/modules/excel/xlsx/xform/drawing/shape-xform.js +109 -0
- package/dist/esm/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +10 -1
- package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +64 -1
- package/dist/esm/modules/pdf/builder/document-builder.js +22 -49
- package/dist/esm/modules/pdf/builder/pdf-editor.js +1 -1
- package/dist/esm/modules/pdf/core/pdf-stream.js +38 -2
- package/dist/esm/modules/pdf/font/font-manager.js +35 -18
- package/dist/esm/modules/pdf/render/page-renderer.js +111 -18
- package/dist/esm/modules/word/advanced/field-engine.js +45 -20
- package/dist/esm/modules/word/advanced/glossary.js +8 -9
- package/dist/esm/modules/word/advanced/math-convert.js +94 -12
- package/dist/esm/modules/word/advanced/ole-objects.js +122 -19
- package/dist/esm/modules/word/advanced/style-map.js +31 -10
- package/dist/esm/modules/word/builder/run-builders.js +7 -1
- package/dist/esm/modules/word/constants.js +5 -1
- package/dist/esm/modules/word/convert/docx-to-semantic.js +135 -1
- package/dist/esm/modules/word/convert/html/html-import.js +167 -14
- package/dist/esm/modules/word/convert/html/html.js +1 -1
- package/dist/esm/modules/word/convert/markdown/markdown-import.js +279 -69
- package/dist/esm/modules/word/convert/odt/odt.js +407 -56
- package/dist/esm/modules/word/html.js +1 -1
- package/dist/esm/modules/word/index.base.js +1 -1
- package/dist/esm/modules/word/layout/layout-full.js +326 -19
- package/dist/esm/modules/word/layout/render-page.js +35 -8
- package/dist/esm/modules/word/query/compat.js +29 -21
- package/dist/esm/modules/word/reader/docx-reader.js +105 -2
- package/dist/esm/modules/word/reader/math-parser.js +8 -2
- package/dist/esm/modules/word/security/cfb-reader.js +5 -5
- package/dist/esm/modules/word/writer/docx-packager.js +108 -2
- package/dist/esm/modules/word/writer/glossary-writer.js +121 -0
- package/dist/esm/modules/word/writer/header-footer-writer.js +105 -20
- package/dist/esm/modules/word/writer/math-writer.js +7 -2
- package/dist/esm/utils/font-metrics.js +43 -0
- package/dist/esm/utils/theme-colors.js +4 -1
- package/dist/iife/excelts.iife.js +496 -59
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +39 -39
- package/dist/types/modules/excel/cell.d.ts +4 -0
- package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +8 -1
- package/dist/types/modules/excel/types.d.ts +81 -0
- package/dist/types/modules/excel/utils/drawing-utils.d.ts +8 -0
- package/dist/types/modules/excel/workbook.browser.d.ts +16 -0
- package/dist/types/modules/excel/worksheet.d.ts +31 -1
- package/dist/types/modules/excel/xlsx/xform/comment/vml-shape-xform.d.ts +7 -0
- package/dist/types/modules/excel/xlsx/xform/drawing/blip-xform.d.ts +6 -0
- package/dist/types/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.d.ts +1 -0
- package/dist/types/modules/excel/xlsx/xform/drawing/pic-xform.d.ts +2 -0
- package/dist/types/modules/excel/xlsx/xform/drawing/shape-xform.d.ts +47 -0
- package/dist/types/modules/pdf/core/pdf-stream.d.ts +28 -1
- package/dist/types/modules/pdf/font/font-manager.d.ts +26 -0
- package/dist/types/modules/pdf/render/page-renderer.d.ts +51 -3
- package/dist/types/modules/word/advanced/glossary.d.ts +10 -36
- package/dist/types/modules/word/advanced/ole-objects.d.ts +28 -0
- package/dist/types/modules/word/builder/run-builders.d.ts +7 -1
- package/dist/types/modules/word/constants.d.ts +4 -0
- package/dist/types/modules/word/convert/docx-to-semantic.d.ts +2 -1
- package/dist/types/modules/word/convert/html/html-import.d.ts +32 -1
- package/dist/types/modules/word/convert/html/html.d.ts +2 -2
- package/dist/types/modules/word/convert/markdown/markdown-import.d.ts +48 -18
- package/dist/types/modules/word/convert/markdown/markdown.d.ts +1 -1
- package/dist/types/modules/word/html.d.ts +2 -2
- package/dist/types/modules/word/index.base.d.ts +3 -3
- package/dist/types/modules/word/markdown.d.ts +1 -1
- package/dist/types/modules/word/query/compat.d.ts +10 -2
- package/dist/types/modules/word/types.d.ts +96 -1
- package/dist/types/modules/word/writer/glossary-writer.d.ts +28 -0
- package/dist/types/utils/font-metrics.d.ts +8 -0
- package/package.json +3 -1
|
@@ -144,7 +144,7 @@ export class PdfEditorPage {
|
|
|
144
144
|
}
|
|
145
145
|
/** @internal */
|
|
146
146
|
_hasOverlay() {
|
|
147
|
-
return (this._overlay._stream.
|
|
147
|
+
return (this._overlay._stream.hasContent() ||
|
|
148
148
|
this._overlay._images.length > 0 ||
|
|
149
149
|
this._overlay._builderAnnotations.length > 0 ||
|
|
150
150
|
this._overlay._formFields.length > 0);
|
|
@@ -19,12 +19,30 @@ import type { PdfColor } from "../types.js";
|
|
|
19
19
|
* and non-stroking (fills/text). We provide methods for both.
|
|
20
20
|
*/
|
|
21
21
|
export declare class PdfContentStream {
|
|
22
|
+
/**
|
|
23
|
+
* Content stream fragments in draw order. Most entries are plain operator
|
|
24
|
+
* strings produced eagerly. A function entry is a *deferred* fragment:
|
|
25
|
+
* its body is only evaluated at serialization time. This is required for
|
|
26
|
+
* text whose final byte encoding depends on font decisions (embedded
|
|
27
|
+
* CIDFont vs. Type1/WinAnsi vs. Type3 fallback) that are not finalised
|
|
28
|
+
* until `PdfDocumentBuilder.build()`. Deferring keeps the fragment at its
|
|
29
|
+
* exact draw-order position (preserving z-order) while letting the actual
|
|
30
|
+
* encoding run after the font manager's state is settled.
|
|
31
|
+
*/
|
|
22
32
|
private parts;
|
|
23
33
|
/**
|
|
24
34
|
* Append a raw PDF operator string to the content stream.
|
|
25
35
|
* Use this for operators not covered by the typed API (e.g. `d1` for Type3 glyphs).
|
|
26
36
|
*/
|
|
27
37
|
raw(operator: string): this;
|
|
38
|
+
/**
|
|
39
|
+
* Append a deferred fragment whose body is evaluated only at serialization
|
|
40
|
+
* time. Used by text drawing so the final byte encoding can be chosen after
|
|
41
|
+
* the document's fonts are resolved at build time. The fragment occupies its
|
|
42
|
+
* draw-order slot immediately, so z-order relative to other operators is
|
|
43
|
+
* preserved.
|
|
44
|
+
*/
|
|
45
|
+
deferred(produce: () => string): this;
|
|
28
46
|
/**
|
|
29
47
|
* Save the current graphics state (push onto state stack).
|
|
30
48
|
* Must be balanced with a corresponding restore().
|
|
@@ -222,7 +240,16 @@ export declare class PdfContentStream {
|
|
|
222
240
|
*/
|
|
223
241
|
roundedRect(x: number, y: number, width: number, height: number, r: number): this;
|
|
224
242
|
/**
|
|
225
|
-
*
|
|
243
|
+
* Whether any fragment has been appended. Unlike `toString().length > 0`,
|
|
244
|
+
* this does NOT evaluate deferred fragments, so it is safe to call before
|
|
245
|
+
* fonts are resolved (e.g. when probing for overlay content during an
|
|
246
|
+
* editor save, prior to `writeFontResources`). A deferred text fragment
|
|
247
|
+
* counts as content even though its bytes are not produced yet.
|
|
248
|
+
*/
|
|
249
|
+
hasContent(): boolean;
|
|
250
|
+
/**
|
|
251
|
+
* Get the content stream as a string. Deferred fragments (see `deferred`)
|
|
252
|
+
* are evaluated here, after font resolution has completed at build time.
|
|
226
253
|
*/
|
|
227
254
|
toString(): string;
|
|
228
255
|
/**
|
|
@@ -23,6 +23,16 @@ import { pdfNumber } from "./pdf-object.js";
|
|
|
23
23
|
*/
|
|
24
24
|
export class PdfContentStream {
|
|
25
25
|
constructor() {
|
|
26
|
+
/**
|
|
27
|
+
* Content stream fragments in draw order. Most entries are plain operator
|
|
28
|
+
* strings produced eagerly. A function entry is a *deferred* fragment:
|
|
29
|
+
* its body is only evaluated at serialization time. This is required for
|
|
30
|
+
* text whose final byte encoding depends on font decisions (embedded
|
|
31
|
+
* CIDFont vs. Type1/WinAnsi vs. Type3 fallback) that are not finalised
|
|
32
|
+
* until `PdfDocumentBuilder.build()`. Deferring keeps the fragment at its
|
|
33
|
+
* exact draw-order position (preserving z-order) while letting the actual
|
|
34
|
+
* encoding run after the font manager's state is settled.
|
|
35
|
+
*/
|
|
26
36
|
this.parts = [];
|
|
27
37
|
}
|
|
28
38
|
// ===========================================================================
|
|
@@ -36,6 +46,17 @@ export class PdfContentStream {
|
|
|
36
46
|
this.parts.push(operator);
|
|
37
47
|
return this;
|
|
38
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Append a deferred fragment whose body is evaluated only at serialization
|
|
51
|
+
* time. Used by text drawing so the final byte encoding can be chosen after
|
|
52
|
+
* the document's fonts are resolved at build time. The fragment occupies its
|
|
53
|
+
* draw-order slot immediately, so z-order relative to other operators is
|
|
54
|
+
* preserved.
|
|
55
|
+
*/
|
|
56
|
+
deferred(produce) {
|
|
57
|
+
this.parts.push(produce);
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
39
60
|
// ===========================================================================
|
|
40
61
|
// Graphics State
|
|
41
62
|
// ===========================================================================
|
|
@@ -435,10 +456,25 @@ export class PdfContentStream {
|
|
|
435
456
|
// Serialization
|
|
436
457
|
// ===========================================================================
|
|
437
458
|
/**
|
|
438
|
-
*
|
|
459
|
+
* Whether any fragment has been appended. Unlike `toString().length > 0`,
|
|
460
|
+
* this does NOT evaluate deferred fragments, so it is safe to call before
|
|
461
|
+
* fonts are resolved (e.g. when probing for overlay content during an
|
|
462
|
+
* editor save, prior to `writeFontResources`). A deferred text fragment
|
|
463
|
+
* counts as content even though its bytes are not produced yet.
|
|
464
|
+
*/
|
|
465
|
+
hasContent() {
|
|
466
|
+
return this.parts.length > 0;
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Get the content stream as a string. Deferred fragments (see `deferred`)
|
|
470
|
+
* are evaluated here, after font resolution has completed at build time.
|
|
439
471
|
*/
|
|
440
472
|
toString() {
|
|
441
|
-
|
|
473
|
+
const out = [];
|
|
474
|
+
for (const part of this.parts) {
|
|
475
|
+
out.push(typeof part === "function" ? part() : part);
|
|
476
|
+
}
|
|
477
|
+
return out.join("\n");
|
|
442
478
|
}
|
|
443
479
|
/**
|
|
444
480
|
* Get the content stream as a Uint8Array (UTF-8 encoded).
|
|
@@ -76,9 +76,35 @@ export declare class FontManager {
|
|
|
76
76
|
* Get the embedded font's resource name (if registered).
|
|
77
77
|
*/
|
|
78
78
|
getEmbeddedResourceName(): string;
|
|
79
|
+
/**
|
|
80
|
+
* Resolve the resource name a draw-time-resolved Type1 resource should
|
|
81
|
+
* actually render (and be measured) with, given the font manager's
|
|
82
|
+
* *current* state. If an embedded font exists (possibly auto-discovered
|
|
83
|
+
* at build time, after the text was drawn against a Type1 resource), the
|
|
84
|
+
* embedded resource name is returned so both measurement and encoding go
|
|
85
|
+
* through the CIDFont. Otherwise the original Type1 resource name is kept;
|
|
86
|
+
* `measureText` handles Type3-fallback widths internally from that name.
|
|
87
|
+
*
|
|
88
|
+
* Centralises the routing rule shared by the deferred text renderer and
|
|
89
|
+
* any deferred measurement (anchor alignment, word wrapping) so the two
|
|
90
|
+
* never disagree.
|
|
91
|
+
*/
|
|
92
|
+
resolveRenderResourceName(type1ResourceName: string): string;
|
|
79
93
|
/**
|
|
80
94
|
* Record that a text string will be rendered, tracking its code points.
|
|
81
95
|
* Must be called for every text string before writing the PDF.
|
|
96
|
+
*
|
|
97
|
+
* Two sets are maintained because font selection may be decided *after*
|
|
98
|
+
* drawing (e.g. `PdfDocumentBuilder.build()` auto-discovers and embeds a
|
|
99
|
+
* system font once it sees the accumulated non-WinAnsi code points):
|
|
100
|
+
*
|
|
101
|
+
* - `usedCodePoints` — every code point seen, always. If an embedded
|
|
102
|
+
* font ends up being used (whether registered up front or
|
|
103
|
+
* auto-discovered at build time), the subset must cover all of these,
|
|
104
|
+
* including plain ASCII, so the CIDFont can encode the full run.
|
|
105
|
+
* - `type3CodePoints` — non-WinAnsi code points only. Drives the
|
|
106
|
+
* build-time decision to auto-embed a system font, and the Type3
|
|
107
|
+
* fallback when none is available.
|
|
82
108
|
*/
|
|
83
109
|
trackText(text: string): void;
|
|
84
110
|
/**
|
|
@@ -182,30 +182,47 @@ export class FontManager {
|
|
|
182
182
|
getEmbeddedResourceName() {
|
|
183
183
|
return this.embeddedResourceName;
|
|
184
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* Resolve the resource name a draw-time-resolved Type1 resource should
|
|
187
|
+
* actually render (and be measured) with, given the font manager's
|
|
188
|
+
* *current* state. If an embedded font exists (possibly auto-discovered
|
|
189
|
+
* at build time, after the text was drawn against a Type1 resource), the
|
|
190
|
+
* embedded resource name is returned so both measurement and encoding go
|
|
191
|
+
* through the CIDFont. Otherwise the original Type1 resource name is kept;
|
|
192
|
+
* `measureText` handles Type3-fallback widths internally from that name.
|
|
193
|
+
*
|
|
194
|
+
* Centralises the routing rule shared by the deferred text renderer and
|
|
195
|
+
* any deferred measurement (anchor alignment, word wrapping) so the two
|
|
196
|
+
* never disagree.
|
|
197
|
+
*/
|
|
198
|
+
resolveRenderResourceName(type1ResourceName) {
|
|
199
|
+
return this.embeddedFont ? this.embeddedResourceName : type1ResourceName;
|
|
200
|
+
}
|
|
185
201
|
/**
|
|
186
202
|
* Record that a text string will be rendered, tracking its code points.
|
|
187
203
|
* Must be called for every text string before writing the PDF.
|
|
204
|
+
*
|
|
205
|
+
* Two sets are maintained because font selection may be decided *after*
|
|
206
|
+
* drawing (e.g. `PdfDocumentBuilder.build()` auto-discovers and embeds a
|
|
207
|
+
* system font once it sees the accumulated non-WinAnsi code points):
|
|
208
|
+
*
|
|
209
|
+
* - `usedCodePoints` — every code point seen, always. If an embedded
|
|
210
|
+
* font ends up being used (whether registered up front or
|
|
211
|
+
* auto-discovered at build time), the subset must cover all of these,
|
|
212
|
+
* including plain ASCII, so the CIDFont can encode the full run.
|
|
213
|
+
* - `type3CodePoints` — non-WinAnsi code points only. Drives the
|
|
214
|
+
* build-time decision to auto-embed a system font, and the Type3
|
|
215
|
+
* fallback when none is available.
|
|
188
216
|
*/
|
|
189
217
|
trackText(text) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if (cp > 0xffff) {
|
|
195
|
-
i++; // skip low surrogate
|
|
196
|
-
}
|
|
218
|
+
for (let i = 0; i < text.length; i++) {
|
|
219
|
+
const cp = text.codePointAt(i);
|
|
220
|
+
if (cp > 0xffff) {
|
|
221
|
+
i++; // skip low surrogate
|
|
197
222
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
for (let i = 0; i < text.length; i++) {
|
|
202
|
-
const cp = text.codePointAt(i);
|
|
203
|
-
if (cp > 0xffff) {
|
|
204
|
-
i++;
|
|
205
|
-
}
|
|
206
|
-
if (!isWinAnsiCodePoint(cp)) {
|
|
207
|
-
this.type3CodePoints.add(cp);
|
|
208
|
-
}
|
|
223
|
+
this.usedCodePoints.add(cp);
|
|
224
|
+
if (!isWinAnsiCodePoint(cp)) {
|
|
225
|
+
this.type3CodePoints.add(cp);
|
|
209
226
|
}
|
|
210
227
|
}
|
|
211
228
|
}
|
|
@@ -29,10 +29,58 @@ export declare function renderPage(page: LayoutPage, options: ResolvedPdfOptions
|
|
|
29
29
|
* when needed. For each sub-run the matrix origin is advanced along the
|
|
30
30
|
* text direction (cos, sin) by the rendered width.
|
|
31
31
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
32
|
+
* The emitted operators are written as a *deferred* fragment (see
|
|
33
|
+
* `PdfContentStream.deferred`). The fragment is only evaluated at
|
|
34
|
+
* serialization time, by which point `PdfDocumentBuilder.build()` has
|
|
35
|
+
* finalised the document's fonts (auto-discovered embedded CIDFont,
|
|
36
|
+
* Type3 fallback, or plain Type1). This is essential: at draw time the
|
|
37
|
+
* font manager has not yet decided whether a non-WinAnsi code point (e.g.
|
|
38
|
+
* U+2192 →) will be served by an embedded font or a Type3 glyph, so eager
|
|
39
|
+
* encoding would irreversibly degrade those characters to spaces via the
|
|
40
|
+
* WinAnsi fallback. Deferring the encode keeps the fragment at its exact
|
|
41
|
+
* draw-order slot (preserving z-order) while choosing the correct bytes
|
|
42
|
+
* once fonts are known.
|
|
43
|
+
*
|
|
44
|
+
* The `useType3` argument is the caller's *draw-time* guess and is ignored;
|
|
45
|
+
* the deferred body recomputes the routing from the now-settled font
|
|
46
|
+
* manager state.
|
|
47
|
+
*/
|
|
48
|
+
export declare function emitTextWithMatrix(stream: PdfContentStream, text: string, a: number, b: number, c: number, d: number, tx: number, ty: number, type1ResourceName: string, fontSize: number, fontManager: FontManager, _useType3: boolean): void;
|
|
49
|
+
/** Options for a deferred, font-aware text block (see `emitTextBlock`). */
|
|
50
|
+
export interface TextBlockOptions {
|
|
51
|
+
/** The text to draw (may contain `\n` when `maxWidth` is set). */
|
|
52
|
+
text: string;
|
|
53
|
+
/** Left/anchor x in unrotated page space. */
|
|
54
|
+
x: number;
|
|
55
|
+
/** Baseline y of the first line in unrotated page space. */
|
|
56
|
+
y: number;
|
|
57
|
+
/** Draw-time-resolved Type1 resource name; re-routed at build time. */
|
|
58
|
+
type1ResourceName: string;
|
|
59
|
+
fontSize: number;
|
|
60
|
+
/** Horizontal anchor; applied per line (including each wrapped line). */
|
|
61
|
+
anchor: "start" | "middle" | "end";
|
|
62
|
+
/** Word-wrap width in points; enables multi-line layout when set. */
|
|
63
|
+
maxWidth?: number;
|
|
64
|
+
/** Line-height multiple applied to `fontSize` for wrapped lines. */
|
|
65
|
+
lineHeightFactor: number;
|
|
66
|
+
/** Clockwise rotation in degrees about (x, y); applied to every line. */
|
|
67
|
+
rotation: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Emit a text block as a single *deferred* fragment so that anchor
|
|
71
|
+
* alignment, word wrapping, and glyph encoding are all computed at
|
|
72
|
+
* serialization time — after `PdfDocumentBuilder.build()` has finalised the
|
|
73
|
+
* document's fonts.
|
|
74
|
+
*
|
|
75
|
+
* This matters because text measurement (anchor offset, line breaking) must
|
|
76
|
+
* use the *same* font that ultimately renders the glyphs. At draw time the
|
|
77
|
+
* font may still be unresolved (a non-WinAnsi run can trigger a build-time
|
|
78
|
+
* auto-embed of a system CIDFont), so measuring against the provisional
|
|
79
|
+
* Type1/Helvetica metrics would misplace centred/right-aligned text and
|
|
80
|
+
* break lines at the wrong points. Deferring keeps measurement and encoding
|
|
81
|
+
* consistent while preserving the fragment's draw-order slot (z-order).
|
|
34
82
|
*/
|
|
35
|
-
export declare function
|
|
83
|
+
export declare function emitTextBlock(stream: PdfContentStream, options: TextBlockOptions, fontManager: FontManager): void;
|
|
36
84
|
/**
|
|
37
85
|
* Generate a deterministic ExtGState resource name for a given alpha value.
|
|
38
86
|
* Uses 4 decimal digits to avoid collisions between close alpha values.
|
|
@@ -675,7 +675,7 @@ function drawRotatedGeneral(stream, cell, lines, fontManager, resourceName, font
|
|
|
675
675
|
emitTextWithMatrix(stream, line, cos, sin, -sin, cos, tx, ty, resourceName, fontSize, fontManager, useType3);
|
|
676
676
|
}
|
|
677
677
|
}
|
|
678
|
-
/** Emit a text string with hex encoding if available. */
|
|
678
|
+
/** Emit a text string with hex encoding if available, onto a sink stream. */
|
|
679
679
|
function emitText(stream, fontManager, text, resourceName) {
|
|
680
680
|
const hex = fontManager.encodeText(text, resourceName);
|
|
681
681
|
if (hex) {
|
|
@@ -690,40 +690,133 @@ function emitText(stream, fontManager, text, resourceName) {
|
|
|
690
690
|
* when needed. For each sub-run the matrix origin is advanced along the
|
|
691
691
|
* text direction (cos, sin) by the rendered width.
|
|
692
692
|
*
|
|
693
|
-
*
|
|
694
|
-
*
|
|
693
|
+
* The emitted operators are written as a *deferred* fragment (see
|
|
694
|
+
* `PdfContentStream.deferred`). The fragment is only evaluated at
|
|
695
|
+
* serialization time, by which point `PdfDocumentBuilder.build()` has
|
|
696
|
+
* finalised the document's fonts (auto-discovered embedded CIDFont,
|
|
697
|
+
* Type3 fallback, or plain Type1). This is essential: at draw time the
|
|
698
|
+
* font manager has not yet decided whether a non-WinAnsi code point (e.g.
|
|
699
|
+
* U+2192 →) will be served by an embedded font or a Type3 glyph, so eager
|
|
700
|
+
* encoding would irreversibly degrade those characters to spaces via the
|
|
701
|
+
* WinAnsi fallback. Deferring the encode keeps the fragment at its exact
|
|
702
|
+
* draw-order slot (preserving z-order) while choosing the correct bytes
|
|
703
|
+
* once fonts are known.
|
|
704
|
+
*
|
|
705
|
+
* The `useType3` argument is the caller's *draw-time* guess and is ignored;
|
|
706
|
+
* the deferred body recomputes the routing from the now-settled font
|
|
707
|
+
* manager state.
|
|
708
|
+
*/
|
|
709
|
+
export function emitTextWithMatrix(stream, text, a, b, c, d, tx, ty, type1ResourceName, fontSize, fontManager, _useType3) {
|
|
710
|
+
stream.deferred(() => renderTextBlock(text, a, b, c, d, tx, ty, type1ResourceName, fontSize, fontManager));
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Emit a text block as a single *deferred* fragment so that anchor
|
|
714
|
+
* alignment, word wrapping, and glyph encoding are all computed at
|
|
715
|
+
* serialization time — after `PdfDocumentBuilder.build()` has finalised the
|
|
716
|
+
* document's fonts.
|
|
717
|
+
*
|
|
718
|
+
* This matters because text measurement (anchor offset, line breaking) must
|
|
719
|
+
* use the *same* font that ultimately renders the glyphs. At draw time the
|
|
720
|
+
* font may still be unresolved (a non-WinAnsi run can trigger a build-time
|
|
721
|
+
* auto-embed of a system CIDFont), so measuring against the provisional
|
|
722
|
+
* Type1/Helvetica metrics would misplace centred/right-aligned text and
|
|
723
|
+
* break lines at the wrong points. Deferring keeps measurement and encoding
|
|
724
|
+
* consistent while preserving the fragment's draw-order slot (z-order).
|
|
725
|
+
*/
|
|
726
|
+
export function emitTextBlock(stream, options, fontManager) {
|
|
727
|
+
stream.deferred(() => renderTextBlockLayout(options, fontManager));
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* Lay out and render a text block from the font manager's *current*
|
|
731
|
+
* (build-time) state. Resolves the render resource name once and uses it for
|
|
732
|
+
* both measurement and encoding so the two never disagree.
|
|
733
|
+
*
|
|
734
|
+
* Layout is computed in the text's *local* coordinate frame — x grows along
|
|
735
|
+
* the baseline, y grows upward — then mapped to page space through the
|
|
736
|
+
* rotation matrix. This makes anchor alignment, multi-line word wrapping, and
|
|
737
|
+
* rotation compose correctly together: each line is offset by its anchor
|
|
738
|
+
* shift (along local x) and its line index (down local y), and a single
|
|
739
|
+
* rotation maps the whole block into place. Upright text (rotation 0) reduces
|
|
740
|
+
* to the identity mapping.
|
|
741
|
+
*/
|
|
742
|
+
function renderTextBlockLayout(options, fontManager) {
|
|
743
|
+
const { text, x, y, type1ResourceName, fontSize, anchor, maxWidth, lineHeightFactor, rotation } = options;
|
|
744
|
+
// Resolve the resource name once; measurement and rendering share it so a
|
|
745
|
+
// build-time auto-embedded CIDFont (or Type3 fallback) is measured with the
|
|
746
|
+
// metrics that will actually render the glyphs.
|
|
747
|
+
const measureResource = fontManager.resolveRenderResourceName(type1ResourceName);
|
|
748
|
+
const measure = (s) => fontManager.measureText(s, measureResource, fontSize);
|
|
749
|
+
const lines = maxWidth ? wrapTextLines(text, measure, maxWidth) : [text];
|
|
750
|
+
const leading = fontSize * lineHeightFactor;
|
|
751
|
+
// Rotation matrix [a b; c d] = [cos sin; -sin cos]; identity when upright.
|
|
752
|
+
const theta = (rotation * Math.PI) / 180;
|
|
753
|
+
const cos = rotation === 0 ? 1 : Math.cos(theta);
|
|
754
|
+
const sin = rotation === 0 ? 0 : Math.sin(theta);
|
|
755
|
+
const anchorFactor = anchor === "middle" ? 0.5 : anchor === "end" ? 1 : 0;
|
|
756
|
+
const parts = [];
|
|
757
|
+
for (let i = 0; i < lines.length; i++) {
|
|
758
|
+
// Local-frame origin of this line: anchor shift along x, line index down y.
|
|
759
|
+
const localX = anchorFactor === 0 ? 0 : -measure(lines[i]) * anchorFactor;
|
|
760
|
+
const localY = -i * leading;
|
|
761
|
+
// Map local origin into page space through the rotation matrix.
|
|
762
|
+
const tx = x + localX * cos + localY * -sin;
|
|
763
|
+
const ty = y + localX * sin + localY * cos;
|
|
764
|
+
parts.push(renderTextBlock(lines[i], cos, sin, -sin, cos, tx, ty, type1ResourceName, fontSize, fontManager));
|
|
765
|
+
}
|
|
766
|
+
return parts.join("\n");
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Produce the PDF operator string for a positioned text run, choosing the
|
|
770
|
+
* encoding from the font manager's *current* (build-time) state:
|
|
771
|
+
* - embedded font → single BT/ET with CIDFont hex encoding
|
|
772
|
+
* - Type3 fallback → split into WinAnsi (Type1) and per-glyph Type3 runs
|
|
773
|
+
* - neither → single BT/ET with Type1/WinAnsi encoding
|
|
774
|
+
*
|
|
775
|
+
* Must only be called after font resolution (i.e. from a deferred fragment).
|
|
695
776
|
*/
|
|
696
|
-
|
|
777
|
+
function renderTextBlock(text, a, b, c, d, tx, ty, type1ResourceName, fontSize, fontManager) {
|
|
778
|
+
const sink = new PdfContentStream();
|
|
779
|
+
// Type3 splitting only applies when there is no embedded font but Type3
|
|
780
|
+
// fallback glyphs were generated. Otherwise the run renders as a single
|
|
781
|
+
// BT/ET pair, choosing the resource name from the now-settled state:
|
|
782
|
+
// if an embedded font exists (possibly auto-discovered at build time,
|
|
783
|
+
// after this run was drawn against a Type1 resource), the run must use it
|
|
784
|
+
// so `emitText` → `encodeText` produces CIDFont hex; without that switch
|
|
785
|
+
// the stale Type1 resource name would make `encodeText` return null and
|
|
786
|
+
// non-WinAnsi characters would degrade to spaces via the WinAnsi fallback.
|
|
787
|
+
const useType3 = fontManager.hasType3Fonts() && !fontManager.hasEmbeddedFont();
|
|
697
788
|
if (!useType3) {
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
789
|
+
const resourceName = fontManager.resolveRenderResourceName(type1ResourceName);
|
|
790
|
+
sink.beginText();
|
|
791
|
+
sink.setFont(resourceName, fontSize);
|
|
792
|
+
sink.setTextMatrix(a, b, c, d, tx, ty);
|
|
793
|
+
emitText(sink, fontManager, text, resourceName);
|
|
794
|
+
sink.endText();
|
|
795
|
+
return sink.toString();
|
|
704
796
|
}
|
|
705
797
|
// Type3 path: split into runs and advance origin along text direction
|
|
706
798
|
const runs = splitTextRuns(text, fontManager);
|
|
707
799
|
let curTx = tx;
|
|
708
800
|
let curTy = ty;
|
|
709
801
|
for (const run of runs) {
|
|
710
|
-
|
|
802
|
+
sink.beginText();
|
|
711
803
|
if (run.type3) {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
804
|
+
sink.setFont(run.type3.resourceName, fontSize);
|
|
805
|
+
sink.setTextMatrix(a, b, c, d, curTx, curTy);
|
|
806
|
+
sink.showTextHex(run.type3.hex);
|
|
715
807
|
}
|
|
716
808
|
else {
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
emitText(
|
|
809
|
+
sink.setFont(type1ResourceName, fontSize);
|
|
810
|
+
sink.setTextMatrix(a, b, c, d, curTx, curTy);
|
|
811
|
+
emitText(sink, fontManager, run.text, type1ResourceName);
|
|
720
812
|
}
|
|
721
|
-
|
|
813
|
+
sink.endText();
|
|
722
814
|
const w = fontManager.measureText(run.text, run.type3?.resourceName ?? type1ResourceName, fontSize);
|
|
723
815
|
// Advance along the text direction (first column of the matrix)
|
|
724
816
|
curTx += a * w;
|
|
725
817
|
curTy += b * w;
|
|
726
818
|
}
|
|
819
|
+
return sink.toString();
|
|
727
820
|
}
|
|
728
821
|
/**
|
|
729
822
|
* Split a line of text into runs of consecutive WinAnsi and non-WinAnsi
|
|
@@ -42,7 +42,7 @@ export function updateFields(doc, options) {
|
|
|
42
42
|
// Build style → paragraphs index for STYLEREF
|
|
43
43
|
const styleIndex = buildStyleIndex(doc);
|
|
44
44
|
// Collect INDEX entries (XE fields) from all body content
|
|
45
|
-
const indexEntries = collectIndexEntries(doc);
|
|
45
|
+
const indexEntries = collectIndexEntries(doc, layout);
|
|
46
46
|
// Update body content
|
|
47
47
|
const newBody = updateBody(doc, layout, bookmarkInfo, seqValues, styleIndex, indexEntries, opts);
|
|
48
48
|
// If TOC was updated, register the TOC1..TOCn paragraph styles so the
|
|
@@ -610,23 +610,33 @@ function findStyleRef(styleIndex, styleName, bodyIndex) {
|
|
|
610
610
|
// =============================================================================
|
|
611
611
|
// Index Entry Collection (for INDEX field)
|
|
612
612
|
// =============================================================================
|
|
613
|
-
/**
|
|
614
|
-
|
|
613
|
+
/**
|
|
614
|
+
* Collect all XE (Index Entry) fields from the document body, tagging each
|
|
615
|
+
* with the page it falls on. Page numbers come from `layout.contentPages`
|
|
616
|
+
* keyed by the enclosing top-level body index (the same mechanism used for
|
|
617
|
+
* headings/TOC); entries inside nested structures inherit their outer block's
|
|
618
|
+
* page, falling back to 1 when layout produced no page for that block.
|
|
619
|
+
*/
|
|
620
|
+
function collectIndexEntries(doc, layout) {
|
|
615
621
|
const entries = [];
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
622
|
+
const { contentPages } = layout;
|
|
623
|
+
for (let i = 0; i < doc.body.length; i++) {
|
|
624
|
+
const page = contentPages[i] ?? 1;
|
|
625
|
+
walkBlocks([doc.body[i]], {
|
|
626
|
+
visitRunContent(content) {
|
|
627
|
+
if (content.type !== "field") {
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
const { type, args } = parseFieldInstruction(content.instruction);
|
|
631
|
+
if (type === "XE") {
|
|
632
|
+
const term = parseXeTerm(args);
|
|
633
|
+
if (term) {
|
|
634
|
+
entries.push({ term, page });
|
|
635
|
+
}
|
|
626
636
|
}
|
|
627
637
|
}
|
|
628
|
-
}
|
|
629
|
-
}
|
|
638
|
+
});
|
|
639
|
+
}
|
|
630
640
|
return entries;
|
|
631
641
|
}
|
|
632
642
|
/** Parse the term from an XE field argument: XE "term" or XE term. */
|
|
@@ -643,17 +653,32 @@ function buildIndexContent(entries, args) {
|
|
|
643
653
|
if (entries.length === 0) {
|
|
644
654
|
return "";
|
|
645
655
|
}
|
|
646
|
-
//
|
|
647
|
-
|
|
656
|
+
// Merge entries that share the same term: a term marked on several pages
|
|
657
|
+
// produces a single index line listing each distinct page (Word behaviour),
|
|
658
|
+
// e.g. "widget, 1, 4" rather than two separate "widget" rows.
|
|
659
|
+
const byTerm = new Map();
|
|
660
|
+
for (const entry of entries) {
|
|
661
|
+
let pages = byTerm.get(entry.term);
|
|
662
|
+
if (!pages) {
|
|
663
|
+
pages = new Set();
|
|
664
|
+
byTerm.set(entry.term, pages);
|
|
665
|
+
}
|
|
666
|
+
pages.add(entry.page);
|
|
667
|
+
}
|
|
668
|
+
// Sort terms alphabetically; within each term sort pages numerically.
|
|
669
|
+
const merged = [...byTerm.entries()]
|
|
670
|
+
.map(([term, pages]) => ({ term, pages: [...pages].sort((a, b) => a - b) }))
|
|
671
|
+
.sort((a, b) => a.term.localeCompare(b.term));
|
|
672
|
+
const formatEntry = (e) => `${e.term}\t${e.pages.join(", ")}`;
|
|
648
673
|
// Check for \h switch (group by first letter with headings)
|
|
649
674
|
const grouped = /\\h\b/i.test(args);
|
|
650
675
|
if (!grouped) {
|
|
651
|
-
return
|
|
676
|
+
return merged.map(formatEntry).join("\n");
|
|
652
677
|
}
|
|
653
678
|
// Group by first letter
|
|
654
679
|
const lines = [];
|
|
655
680
|
let currentLetter = "";
|
|
656
|
-
for (const entry of
|
|
681
|
+
for (const entry of merged) {
|
|
657
682
|
const letter = entry.term.charAt(0).toUpperCase();
|
|
658
683
|
if (letter !== currentLetter) {
|
|
659
684
|
currentLetter = letter;
|
|
@@ -662,7 +687,7 @@ function buildIndexContent(entries, args) {
|
|
|
662
687
|
}
|
|
663
688
|
lines.push(currentLetter);
|
|
664
689
|
}
|
|
665
|
-
lines.push(
|
|
690
|
+
lines.push(formatEntry(entry));
|
|
666
691
|
}
|
|
667
692
|
return lines.join("\n");
|
|
668
693
|
}
|
|
@@ -4,45 +4,19 @@
|
|
|
4
4
|
* Provides types and utilities for working with Glossary Document parts,
|
|
5
5
|
* which contain AutoText entries, Quick Parts, and other Building Blocks.
|
|
6
6
|
*
|
|
7
|
-
* INTEGRATION STATUS: This module provides data
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* glossary
|
|
11
|
-
*
|
|
7
|
+
* INTEGRATION STATUS: This module provides the glossary data model and query
|
|
8
|
+
* helpers. To embed a glossary in a document, assign a {@link GlossaryDocument}
|
|
9
|
+
* to `doc.glossary`; the packager then serialises it to
|
|
10
|
+
* `word/glossary/document.xml`, registers the `glossaryDocument` relationship,
|
|
11
|
+
* and adds the `[Content_Types].xml` override (the canonical OOXML location
|
|
12
|
+
* Word reads Quick Parts / AutoText from). Glossary parts in existing files are
|
|
13
|
+
* round-tripped via the same channel. This module is useful for:
|
|
12
14
|
* - Building glossary data structures programmatically
|
|
13
15
|
* - Querying/filtering building block collections
|
|
14
|
-
* -
|
|
15
|
-
*
|
|
16
|
-
* To add glossary content to a document currently, include it as an
|
|
17
|
-
* OpaquePart with path "word/glossary/document.xml".
|
|
16
|
+
* - Assembling a glossary to attach via `doc.glossary`
|
|
18
17
|
*/
|
|
19
|
-
import type { BodyContent, SectionProperties } from "../types.js";
|
|
20
|
-
|
|
21
|
-
export type BuildingBlockGallery = "autoText" | "quickParts" | "coverPages" | "tableOfContents" | "headers" | "footers" | "pageNumbers" | "tables" | "textBoxes" | "watermarks" | "equations" | "bibliographies" | "custom1" | "custom2" | "custom3" | "custom4" | "custom5";
|
|
22
|
-
/** A single building block (AutoText/Quick Part) entry. */
|
|
23
|
-
export interface BuildingBlock {
|
|
24
|
-
/** Name of the building block (displayed in gallery). */
|
|
25
|
-
readonly name: string;
|
|
26
|
-
/** Gallery this block belongs to. */
|
|
27
|
-
readonly gallery: BuildingBlockGallery;
|
|
28
|
-
/** Category within the gallery. */
|
|
29
|
-
readonly category?: string;
|
|
30
|
-
/** Description/tooltip. */
|
|
31
|
-
readonly description?: string;
|
|
32
|
-
/** The content of the building block. */
|
|
33
|
-
readonly content: readonly BodyContent[];
|
|
34
|
-
/** Section properties specific to this building block. */
|
|
35
|
-
readonly sectionProperties?: SectionProperties;
|
|
36
|
-
/** Unique identifier (GUID). */
|
|
37
|
-
readonly guid?: string;
|
|
38
|
-
}
|
|
39
|
-
/** The glossary document model. */
|
|
40
|
-
export interface GlossaryDocument {
|
|
41
|
-
/** Building block entries. */
|
|
42
|
-
readonly blocks: readonly BuildingBlock[];
|
|
43
|
-
/** Raw parts preserved for round-trip (style, settings, fontTable). */
|
|
44
|
-
readonly rawParts?: ReadonlyMap<string, Uint8Array>;
|
|
45
|
-
}
|
|
18
|
+
import type { BodyContent, BuildingBlock, BuildingBlockGallery, GlossaryDocument, SectionProperties } from "../types.js";
|
|
19
|
+
export type { BuildingBlock, BuildingBlockGallery, GlossaryDocument } from "../types.js";
|
|
46
20
|
/**
|
|
47
21
|
* Create a building block entry.
|
|
48
22
|
*
|
|
@@ -4,17 +4,16 @@
|
|
|
4
4
|
* Provides types and utilities for working with Glossary Document parts,
|
|
5
5
|
* which contain AutoText entries, Quick Parts, and other Building Blocks.
|
|
6
6
|
*
|
|
7
|
-
* INTEGRATION STATUS: This module provides data
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* glossary
|
|
11
|
-
*
|
|
7
|
+
* INTEGRATION STATUS: This module provides the glossary data model and query
|
|
8
|
+
* helpers. To embed a glossary in a document, assign a {@link GlossaryDocument}
|
|
9
|
+
* to `doc.glossary`; the packager then serialises it to
|
|
10
|
+
* `word/glossary/document.xml`, registers the `glossaryDocument` relationship,
|
|
11
|
+
* and adds the `[Content_Types].xml` override (the canonical OOXML location
|
|
12
|
+
* Word reads Quick Parts / AutoText from). Glossary parts in existing files are
|
|
13
|
+
* round-tripped via the same channel. This module is useful for:
|
|
12
14
|
* - Building glossary data structures programmatically
|
|
13
15
|
* - Querying/filtering building block collections
|
|
14
|
-
* -
|
|
15
|
-
*
|
|
16
|
-
* To add glossary content to a document currently, include it as an
|
|
17
|
-
* OpaquePart with path "word/glossary/document.xml".
|
|
16
|
+
* - Assembling a glossary to attach via `doc.glossary`
|
|
18
17
|
*/
|
|
19
18
|
import { generateGuid } from "../core/internal-utils.js";
|
|
20
19
|
// =============================================================================
|