@stll/folio-core 0.32.2 → 0.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/dist/ai-edits/__fixtures__/paragraphs.d.ts +17 -0
  2. package/dist/ai-edits/__fixtures__/paragraphs.js +33 -0
  3. package/dist/ai-edits/apply.d.ts +49 -3
  4. package/dist/ai-edits/apply.js +652 -86
  5. package/dist/ai-edits/blockRange.d.ts +7 -3
  6. package/dist/ai-edits/blockRange.js +14 -6
  7. package/dist/ai-edits/headless.d.ts +39 -5
  8. package/dist/ai-edits/headless.js +76 -17
  9. package/dist/ai-edits/index.d.ts +6 -6
  10. package/dist/ai-edits/index.js +3 -3
  11. package/dist/ai-edits/read.d.ts +4 -0
  12. package/dist/ai-edits/read.js +30 -6
  13. package/dist/ai-edits/scoped-reading.js +4 -3
  14. package/dist/ai-edits/snapshot.d.ts +42 -2
  15. package/dist/ai-edits/snapshot.js +127 -62
  16. package/dist/ai-edits/table-row-column-mutations.d.ts +24 -1
  17. package/dist/ai-edits/table-row-column-mutations.js +98 -6
  18. package/dist/ai-edits/table-targets.d.ts +12 -3
  19. package/dist/ai-edits/table-targets.js +15 -5
  20. package/dist/ai-edits/types.d.ts +219 -15
  21. package/dist/ai-edits/word-diff.d.ts +54 -11
  22. package/dist/ai-edits/word-diff.js +221 -61
  23. package/dist/compare/__fixtures__/body-sequence.d.ts +56 -0
  24. package/dist/compare/__fixtures__/body-sequence.js +136 -0
  25. package/dist/compare/__fixtures__/nested-table.d.ts +16 -0
  26. package/dist/compare/__fixtures__/nested-table.js +50 -0
  27. package/dist/compare/__fixtures__/numbered-list.d.ts +34 -0
  28. package/dist/compare/__fixtures__/numbered-list.js +85 -0
  29. package/dist/compare/column-alignment.d.ts +27 -0
  30. package/dist/compare/column-alignment.js +162 -0
  31. package/dist/compare/compare.d.ts +107 -0
  32. package/dist/compare/compare.js +412 -0
  33. package/dist/compare/formatting.d.ts +29 -0
  34. package/dist/compare/formatting.js +84 -0
  35. package/dist/compare/plan.d.ts +22 -0
  36. package/dist/compare/plan.js +1141 -0
  37. package/dist/compare/reproducible-package.d.ts +21 -0
  38. package/dist/compare/reproducible-package.js +47 -0
  39. package/dist/compare/scenario.d.ts +77 -0
  40. package/dist/compare/scenario.js +263 -0
  41. package/dist/compare/types.d.ts +297 -0
  42. package/dist/compare/types.js +42 -0
  43. package/dist/compare/verification.d.ts +83 -0
  44. package/dist/compare/verification.js +189 -0
  45. package/dist/compat/eigenpal.d.ts +9 -6
  46. package/dist/compat/eigenpal.js +6 -3
  47. package/dist/controller/layoutPipeline.d.ts +13 -0
  48. package/dist/controller/layoutPipeline.js +15 -1
  49. package/dist/display-list/build/buildContext.d.ts +39 -0
  50. package/dist/display-list/build/buildContext.js +31 -0
  51. package/dist/display-list/build/buildDisplayList.d.ts +79 -0
  52. package/dist/display-list/build/buildDisplayList.js +283 -0
  53. package/dist/display-list/build/colors.d.ts +20 -0
  54. package/dist/display-list/build/colors.js +136 -0
  55. package/dist/display-list/build/floatingImages.d.ts +24 -0
  56. package/dist/display-list/build/floatingImages.js +41 -0
  57. package/dist/display-list/build/fontTable.d.ts +31 -0
  58. package/dist/display-list/build/fontTable.js +97 -0
  59. package/dist/display-list/build/furniture.d.ts +86 -0
  60. package/dist/display-list/build/furniture.js +98 -0
  61. package/dist/display-list/build/glyphs.d.ts +55 -0
  62. package/dist/display-list/build/glyphs.js +103 -0
  63. package/dist/display-list/build/headerFooterPrimitives.d.ts +17 -0
  64. package/dist/display-list/build/headerFooterPrimitives.js +40 -0
  65. package/dist/display-list/build/imagePrimitives.d.ts +35 -0
  66. package/dist/display-list/build/imagePrimitives.js +264 -0
  67. package/dist/display-list/build/pageBorderPrimitives.d.ts +23 -0
  68. package/dist/display-list/build/pageBorderPrimitives.js +111 -0
  69. package/dist/display-list/build/pageFurniture.d.ts +35 -0
  70. package/dist/display-list/build/pageFurniture.js +141 -0
  71. package/dist/display-list/build/paragraphPrimitives.d.ts +19 -0
  72. package/dist/display-list/build/paragraphPrimitives.js +819 -0
  73. package/dist/display-list/build/regions.d.ts +46 -0
  74. package/dist/display-list/build/regions.js +56 -0
  75. package/dist/display-list/build/storyPrimitives.d.ts +29 -0
  76. package/dist/display-list/build/storyPrimitives.js +279 -0
  77. package/dist/display-list/build/strokes.d.ts +19 -0
  78. package/dist/display-list/build/strokes.js +78 -0
  79. package/dist/display-list/build/tablePrimitives.d.ts +38 -0
  80. package/dist/display-list/build/tablePrimitives.js +409 -0
  81. package/dist/display-list/build/textBoxPrimitives.d.ts +14 -0
  82. package/dist/display-list/build/textBoxPrimitives.js +129 -0
  83. package/dist/display-list/build/textDecorations.d.ts +29 -0
  84. package/dist/display-list/build/textDecorations.js +29 -0
  85. package/dist/display-list/build/unsupported.d.ts +57 -0
  86. package/dist/display-list/build/unsupported.js +0 -0
  87. package/dist/display-list/build/watermarkPrimitives.d.ts +15 -0
  88. package/dist/display-list/build/watermarkPrimitives.js +128 -0
  89. package/dist/display-list/dom/renderDisplayListToDom.d.ts +26 -0
  90. package/dist/display-list/dom/renderDisplayListToDom.js +620 -0
  91. package/dist/display-list/editor/displayListPagePainter.d.ts +22 -0
  92. package/dist/display-list/editor/displayListPagePainter.js +63 -0
  93. package/dist/display-list/editor/pageRenderer.d.ts +24 -0
  94. package/dist/display-list/editor/pageRenderer.js +36 -0
  95. package/dist/display-list/primitives.d.ts +95 -0
  96. package/dist/display-list/primitives.js +127 -0
  97. package/dist/display-list/types.d.ts +472 -0
  98. package/dist/display-list/types.js +0 -0
  99. package/dist/document-operations.d.ts +39 -8
  100. package/dist/document-operations.js +169 -16
  101. package/dist/document-stories.d.ts +16 -0
  102. package/dist/document-stories.js +48 -4
  103. package/dist/docx/hyperlinkParser.d.ts +9 -1
  104. package/dist/docx/hyperlinkParser.js +19 -13
  105. package/dist/docx/packageParts.d.ts +35 -0
  106. package/dist/docx/packageParts.js +120 -0
  107. package/dist/docx/paraIdRangeNormalization.d.ts +40 -0
  108. package/dist/docx/paraIdRangeNormalization.js +64 -0
  109. package/dist/docx/paragraphParser.js +101 -26
  110. package/dist/docx/paragraphTraversal.js +1 -1
  111. package/dist/docx/renderedPageBreakNormalization.js +3 -1
  112. package/dist/docx/revisionIdNormalization.d.ts +27 -0
  113. package/dist/docx/revisionIdNormalization.js +121 -0
  114. package/dist/docx/rezip.d.ts +6 -0
  115. package/dist/docx/rezip.js +51 -19
  116. package/dist/docx/selectiveSave.js +2 -2
  117. package/dist/docx/serializer/commentSerializer.js +6 -1
  118. package/dist/docx/serializer/paragraphSerializer.js +73 -20
  119. package/dist/docx/serializer/runSerializer.js +11 -10
  120. package/dist/docx/serializer/tableSerializer.js +26 -10
  121. package/dist/docx/server/applyDocxXmlPatchProposal.js +1 -1
  122. package/dist/docx/server/createBilingualDocx.js +3 -2
  123. package/dist/docx/streamingXmlParser.d.ts +13 -1
  124. package/dist/docx/streamingXmlParser.js +49 -11
  125. package/dist/docx/unzip.d.ts +1 -2
  126. package/dist/docx/unzip.js +25 -6
  127. package/dist/docx/xmlParser.d.ts +3 -1
  128. package/dist/docx/xmlParser.js +33 -27
  129. package/dist/export-pdf.d.ts +43 -0
  130. package/dist/export-pdf.js +98 -0
  131. package/dist/fonts/headlessMeasure.d.ts +76 -0
  132. package/dist/fonts/headlessMeasure.js +0 -0
  133. package/dist/fonts/sfnt/parse.d.ts +51 -0
  134. package/dist/fonts/sfnt/parse.js +525 -0
  135. package/dist/fonts/sfnt/subset.d.ts +20 -0
  136. package/dist/fonts/sfnt/subset.js +350 -0
  137. package/dist/fonts/sfnt/tables.d.ts +88 -0
  138. package/dist/fonts/sfnt/tables.js +131 -0
  139. package/dist/fonts/sfnt/woff.d.ts +14 -0
  140. package/dist/fonts/sfnt/woff.js +163 -0
  141. package/dist/generated/text_shaper.js +324 -0
  142. package/dist/generated/text_shaper_bg.wasm +0 -0
  143. package/dist/headless-layout.d.ts +75 -0
  144. package/dist/headless-layout.js +350 -0
  145. package/dist/index.d.ts +9 -6
  146. package/dist/index.js +6 -3
  147. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  148. package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
  149. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  150. package/dist/layout-bridge/convert/headerFooterLayout.js +2 -0
  151. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +3 -1
  152. package/dist/layout-bridge/convert/toFlowBlocks.js +2 -0
  153. package/dist/layout-engine/measure/advanceComposition.d.ts +62 -0
  154. package/dist/layout-engine/measure/advanceComposition.js +148 -0
  155. package/dist/layout-engine/measure/cache.d.ts +2 -0
  156. package/dist/layout-engine/measure/measureContainer.js +13 -0
  157. package/dist/layout-engine/measure/measureParagraph.js +1 -2
  158. package/dist/layout-engine/measure/measureTypes.d.ts +12 -0
  159. package/dist/layout-engine/measure/tableInlinePlacement.d.ts +3 -2
  160. package/dist/layout-engine/measure/tableInlinePlacement.js +14 -1
  161. package/dist/layout-engine/tableIndentCompatibility.d.ts +5 -0
  162. package/dist/layout-engine/tableIndentCompatibility.js +15 -0
  163. package/dist/layout-engine/types.d.ts +8 -0
  164. package/dist/layout-painter/renderPage.d.ts +29 -1
  165. package/dist/layout-painter/renderPage.js +47 -19
  166. package/dist/layout-painter/renderParagraph.d.ts +21 -2
  167. package/dist/layout-painter/renderParagraph.js +1 -1
  168. package/dist/layout-painter/renderTable.js +37 -4
  169. package/dist/managers/editorShortcuts.d.ts +33 -1
  170. package/dist/managers/editorShortcuts.js +20 -1
  171. package/dist/markdown/renderRuns.js +7 -2
  172. package/dist/markdown/renderTable.js +5 -1
  173. package/dist/model.d.ts +3 -3
  174. package/dist/model.js +2 -2
  175. package/dist/pdf/contentStream.d.ts +73 -0
  176. package/dist/pdf/contentStream.js +143 -0
  177. package/dist/pdf/fonts.d.ts +96 -0
  178. package/dist/pdf/fonts.js +593 -0
  179. package/dist/pdf/images.d.ts +28 -0
  180. package/dist/pdf/images.js +439 -0
  181. package/dist/pdf/objects.d.ts +93 -0
  182. package/dist/pdf/objects.js +237 -0
  183. package/dist/pdf/pageSpace.d.ts +43 -0
  184. package/dist/pdf/pageSpace.js +57 -0
  185. package/dist/pdf/paint.d.ts +32 -0
  186. package/dist/pdf/paint.js +442 -0
  187. package/dist/pdf/writePdf.d.ts +56 -0
  188. package/dist/pdf/writePdf.js +345 -0
  189. package/dist/prosemirror/commands/comments.js +96 -6
  190. package/dist/prosemirror/conversion/fromProseDoc.js +41 -7
  191. package/dist/prosemirror/conversion/toProseDoc.js +41 -4
  192. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +15 -2
  193. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +35 -6
  194. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +2 -2
  195. package/dist/prosemirror/extensions/features/pasteCleanup.js +4 -3
  196. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.d.ts +3 -1
  197. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +5 -3
  198. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts +7 -1
  199. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.js +9 -3
  200. package/dist/prosemirror/extensions/nodes/TableExtension.js +56 -39
  201. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +3 -1
  202. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +5 -3
  203. package/dist/prosemirror/plugins/suggestionMode.js +1 -0
  204. package/dist/prosemirror/revisionCarriers.js +19 -2
  205. package/dist/prosemirror/utils/extractTrackedChanges.d.ts +2 -2
  206. package/dist/prosemirror/utils/extractTrackedChanges.js +59 -23
  207. package/dist/prosemirror/validation.js +55 -27
  208. package/dist/prosemirror/zeroWidthAnchors.d.ts +10 -0
  209. package/dist/prosemirror/zeroWidthAnchors.js +23 -0
  210. package/dist/redline.js +12 -79
  211. package/dist/server.d.ts +3 -3
  212. package/dist/server.js +2 -2
  213. package/dist/shaping/placeRun.d.ts +51 -0
  214. package/dist/shaping/placeRun.js +84 -0
  215. package/dist/shaping/shaper.d.ts +92 -0
  216. package/dist/shaping/shaper.js +102 -0
  217. package/dist/types/block-id.d.ts +18 -2
  218. package/dist/types/block-id.js +49 -5
  219. package/dist/types/content.d.ts +2 -2
  220. package/dist/utils/clipboard.js +4 -3
  221. package/dist/utils/fontResolver.js +183 -0
  222. package/dist/utils/htmlComments.d.ts +17 -0
  223. package/dist/utils/htmlComments.js +22 -0
  224. package/dist/utils/scriptSegments.d.ts +12 -1
  225. package/dist/utils/scriptSegments.js +17 -1
  226. package/dist/version-comparison.d.ts +1 -1
  227. package/package.json +7 -3
@@ -32,6 +32,25 @@ function classifyEditorKeydown(e, { isMac, isInputLike }) {
32
32
  }
33
33
  return { type: "none" };
34
34
  }
35
+ /** `contains` rejects a non-node argument, so screen the target first. */
36
+ function isNode(target) {
37
+ return typeof target === "object" && target !== null && "nodeType" in target;
38
+ }
39
+ /**
40
+ * Whether a keydown is one the editor answers under `scope`. The adapters own
41
+ * the listener; this decides, from the event target alone, whether the press
42
+ * belongs to this editor or to whatever else the host has on the page.
43
+ */
44
+ function isKeydownInShortcutScope(event, { scope, roots }) {
45
+ switch (scope) {
46
+ case "document": return true;
47
+ case "none": return false;
48
+ case "editor":
49
+ if (!isNode(event.target)) return false;
50
+ return roots.some((root) => root?.contains(event.target) === true);
51
+ default: return scope;
52
+ }
53
+ }
35
54
  /**
36
55
  * If the selection is a ProseMirror `CellSelection` covering every cell of its
37
56
  * table, delete the table and return `true`. Returns `false` for any other
@@ -57,4 +76,4 @@ function deleteSelectedTable(state, dispatch) {
57
76
  return false;
58
77
  }
59
78
  //#endregion
60
- export { classifyEditorKeydown, deleteSelectedTable, isFocusInInputLike, isMacPlatform };
79
+ export { classifyEditorKeydown, deleteSelectedTable, isFocusInInputLike, isKeydownInShortcutScope, isMacPlatform };
@@ -145,11 +145,16 @@ function renderHyperlink(ctx, pkg, link, paraId) {
145
145
  return `[${inner}](${escapeLinkUrl(href)})`;
146
146
  }
147
147
  function renderTrackedWrapper(ctx, pkg, wrapper, paraId) {
148
+ const renderChild = (child) => {
149
+ if (child.type === "run") return renderRun(ctx, pkg, child, paraId);
150
+ if (child.type === "hyperlink") return renderHyperlink(ctx, pkg, child, paraId);
151
+ return "";
152
+ };
148
153
  if (ctx.opts.trackedChanges === "clean") {
149
- if (wrapper.type === "insertion" || wrapper.type === "moveTo") return wrapper.content.map((child) => child.type === "run" ? renderRun(ctx, pkg, child, paraId) : renderHyperlink(ctx, pkg, child, paraId)).join("");
154
+ if (wrapper.type === "insertion" || wrapper.type === "moveTo") return wrapper.content.map(renderChild).join("");
150
155
  return "";
151
156
  }
152
- const inner = wrapper.content.map((child) => child.type === "run" ? renderRun(ctx, pkg, child, paraId) : renderHyperlink(ctx, pkg, child, paraId)).join("");
157
+ const inner = wrapper.content.map(renderChild).join("");
153
158
  switch (wrapper.type) {
154
159
  case "insertion": return wrapInsertion(ctx, wrapper.info, inner);
155
160
  case "deletion": return wrapDeletion(ctx, wrapper.info, inner);
@@ -157,7 +157,11 @@ function renderHtmlInline(ctx, pkg, content, paraId) {
157
157
  return out;
158
158
  }
159
159
  function renderHtmlChildren(ctx, pkg, children, paraId) {
160
- return children.map((c) => c.type === "run" ? renderHtmlRun(ctx, pkg, c, paraId) : renderHtmlHyperlink(ctx, pkg, c, paraId)).join("");
160
+ return children.map((child) => {
161
+ if (child.type === "run") return renderHtmlRun(ctx, pkg, child, paraId);
162
+ if (child.type === "hyperlink") return renderHtmlHyperlink(ctx, pkg, child, paraId);
163
+ return "";
164
+ }).join("");
161
165
  }
162
166
  function renderHtmlRun(ctx, pkg, run, paraId) {
163
167
  if (run.formatting?.hidden) return "";
package/dist/model.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { document_d_exports } from "./types/document.js";
2
- import { DeriveBlockIdInput, FolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
2
+ import { DeriveBlockIdInput, FolioBlockId, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
3
3
  import { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, normalizeShapeTextAnchor } from "./types/documentEnumValues.js";
4
4
  import { types_d_exports } from "./layout-engine/types.js";
5
5
  import { measureTypes_d_exports } from "./layout-engine/measure/measureTypes.js";
6
6
  export * from "@stll/docx-core/model";
7
7
  declare namespace model_d_exports {
8
- export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, DeriveBlockIdInput, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, FolioBlockId, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_d_exports as Layout, measureTypes_d_exports as Measure, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
8
+ export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, DeriveBlockIdInput, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, FolioBlockId, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_d_exports as Layout, measureTypes_d_exports as Measure, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
9
9
  }
10
10
  //#endregion
11
- export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, DeriveBlockIdInput, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, FolioBlockId, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_d_exports as Layout, type measureTypes_d_exports as Measure, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
11
+ export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, DeriveBlockIdInput, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, FolioBlockId, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_d_exports as Layout, type measureTypes_d_exports as Measure, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
package/dist/model.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import { types_exports } from "./layout-engine/types.js";
2
- import { deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
2
+ import { deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
3
3
  import { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, normalizeShapeTextAnchor } from "./types/documentEnumValues.js";
4
- export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_exports as Layout, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
4
+ export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_exports as Layout, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
@@ -0,0 +1,73 @@
1
+ import { DisplayColor } from "../display-list/types.js";
2
+ import { PdfMatrix } from "./pageSpace.js";
3
+ //#region src/pdf/contentStream.d.ts
4
+ type PdfResourceUse = {
5
+ readonly kind: "font";
6
+ readonly resourceIndex: number;
7
+ } | {
8
+ readonly kind: "image";
9
+ readonly imageIndex: number;
10
+ } | {
11
+ readonly kind: "extGState";
12
+ readonly alpha: number;
13
+ };
14
+ type ContentPart = {
15
+ readonly kind: "literal";
16
+ readonly text: string;
17
+ } | PdfResourceUse;
18
+ /** A glyph plus the correction that follows it in a `TJ` array. */
19
+ type PositionedGlyph = {
20
+ readonly glyphId: number;
21
+ /** Thousandths of text space, subtracted from the pen after the glyph. */
22
+ readonly adjustment: number;
23
+ };
24
+ /**
25
+ * Text rendering modes. `fillThenStroke` is what an outlined run (`w:outline`)
26
+ * paints.
27
+ */
28
+ declare const TEXT_RENDER_MODE: {
29
+ readonly fill: 0;
30
+ readonly stroke: 1;
31
+ readonly fillThenStroke: 2;
32
+ };
33
+ type PdfTextRenderMode = (typeof TEXT_RENDER_MODE)[keyof typeof TEXT_RENDER_MODE];
34
+ type ContentStream = {
35
+ readonly save: () => void;
36
+ readonly restore: () => void;
37
+ readonly concat: (matrix: PdfMatrix) => void;
38
+ readonly setFillColor: (color: DisplayColor) => void;
39
+ readonly setStrokeColor: (color: DisplayColor) => void;
40
+ readonly setLineWidth: (widthPx: number) => void;
41
+ readonly setDash: (pattern: readonly number[], phasePx: number) => void;
42
+ /** Selects an `ExtGState` carrying `/ca` and `/CA` set to `alpha`. */
43
+ readonly setAlpha: (alpha: number) => void;
44
+ readonly appendRect: (xPx: number, yPx: number, widthPx: number, heightPx: number) => void;
45
+ readonly moveTo: (xPx: number, yPx: number) => void;
46
+ readonly lineTo: (xPx: number, yPx: number) => void;
47
+ readonly fill: () => void;
48
+ readonly stroke: () => void;
49
+ readonly clipToCurrentPath: () => void;
50
+ readonly beginText: () => void;
51
+ readonly endText: () => void;
52
+ readonly setFont: (resourceIndex: number, sizePx: number) => void;
53
+ readonly setTextRenderMode: (mode: PdfTextRenderMode) => void;
54
+ readonly setTextMatrix: (matrix: PdfMatrix) => void;
55
+ readonly showGlyphs: (glyphs: readonly PositionedGlyph[]) => void;
56
+ /** Shows one already-encoded byte string, for a simple (base-14) font. */
57
+ readonly showBytes: (bytes: readonly number[]) => void;
58
+ readonly drawImage: (imageIndex: number) => void;
59
+ readonly parts: () => readonly ContentPart[];
60
+ };
61
+ declare const createContentStream: () => ContentStream;
62
+ /** Resource names for one page, assigned from sorted keys. */
63
+ type ContentResources = {
64
+ /** Keyed by font resource index: one face can hold several of them. */
65
+ readonly fontNames: ReadonlyMap<number, string>;
66
+ readonly imageNames: ReadonlyMap<number, string>;
67
+ /** Keyed by the formatted alpha, so two alphas that print alike share a state. */
68
+ readonly extGStateNames: ReadonlyMap<string, string>;
69
+ };
70
+ declare const collectResources: (parts: readonly ContentPart[]) => ContentResources;
71
+ declare const renderContentStream: (parts: readonly ContentPart[], resources: ContentResources) => string;
72
+ //#endregion
73
+ export { ContentPart, ContentResources, ContentStream, PdfResourceUse, PdfTextRenderMode, PositionedGlyph, TEXT_RENDER_MODE, collectResources, createContentStream, renderContentStream };
@@ -0,0 +1,143 @@
1
+ import { formatNumber } from "./objects.js";
2
+ import { panic } from "better-result";
3
+ //#region src/pdf/contentStream.ts
4
+ /**
5
+ * Content-stream construction: the graphics operators, and the resource
6
+ * names they refer to.
7
+ *
8
+ * A stream is built as a list of parts rather than a string, because a
9
+ * resource reference (`/F1`, `/Im1`, `/GS1`) is written as a *use* of a font,
10
+ * image or alpha, not as a name. Names are assigned once the whole stream is
11
+ * known, in sorted key order, so nothing about the file depends on the order
12
+ * in which the painter happened to reach a resource. Emitting names as the
13
+ * painter goes would make the bytes depend on traversal order, which is
14
+ * exactly the kind of drift the determinism requirement forbids.
15
+ */
16
+ /**
17
+ * Text rendering modes. `fillThenStroke` is what an outlined run (`w:outline`)
18
+ * paints.
19
+ */
20
+ const TEXT_RENDER_MODE = {
21
+ fill: 0,
22
+ stroke: 1,
23
+ fillThenStroke: 2
24
+ };
25
+ const COLOR_MAX = 255;
26
+ const colorComponents = (color) => `${formatNumber(color.r / COLOR_MAX)} ${formatNumber(color.g / COLOR_MAX)} ${formatNumber(color.b / COLOR_MAX)}`;
27
+ const glyphHex = (glyphId) => {
28
+ if (!Number.isInteger(glyphId) || glyphId < 0 || glyphId > 65535) panic(`glyph id outside Identity-H's two-byte range: ${String(glyphId)}`);
29
+ return glyphId.toString(16).padStart(4, "0").toUpperCase();
30
+ };
31
+ const createContentStream = () => {
32
+ const parts = [];
33
+ const line = (text) => {
34
+ parts.push({
35
+ kind: "literal",
36
+ text: `${text}\n`
37
+ });
38
+ };
39
+ const use = (resource, suffix) => {
40
+ parts.push(resource, {
41
+ kind: "literal",
42
+ text: `${suffix}\n`
43
+ });
44
+ };
45
+ return {
46
+ save: () => line("q"),
47
+ restore: () => line("Q"),
48
+ concat: (matrix) => line(`${matrix.map(formatNumber).join(" ")} cm`),
49
+ setFillColor: (color) => line(`${colorComponents(color)} rg`),
50
+ setStrokeColor: (color) => line(`${colorComponents(color)} RG`),
51
+ setLineWidth: (widthPx) => line(`${formatNumber(widthPx)} w`),
52
+ setDash: (pattern, phasePx) => line(`[${pattern.map(formatNumber).join(" ")}] ${formatNumber(phasePx)} d`),
53
+ setAlpha: (alpha) => use({
54
+ kind: "extGState",
55
+ alpha
56
+ }, " gs"),
57
+ appendRect: (xPx, yPx, widthPx, heightPx) => line(`${formatNumber(xPx)} ${formatNumber(yPx)} ${formatNumber(widthPx)} ${formatNumber(heightPx)} re`),
58
+ moveTo: (xPx, yPx) => line(`${formatNumber(xPx)} ${formatNumber(yPx)} m`),
59
+ lineTo: (xPx, yPx) => line(`${formatNumber(xPx)} ${formatNumber(yPx)} l`),
60
+ fill: () => line("f"),
61
+ stroke: () => line("S"),
62
+ clipToCurrentPath: () => line("W n"),
63
+ beginText: () => line("BT"),
64
+ endText: () => line("ET"),
65
+ setFont: (resourceIndex, sizePx) => use({
66
+ kind: "font",
67
+ resourceIndex
68
+ }, ` ${formatNumber(sizePx)} Tf`),
69
+ setTextRenderMode: (mode) => line(`${String(mode)} Tr`),
70
+ setTextMatrix: (matrix) => line(`${matrix.map(formatNumber).join(" ")} Tm`),
71
+ showGlyphs: (glyphs) => {
72
+ let body = "";
73
+ let pending = "";
74
+ for (const { glyphId, adjustment } of glyphs) {
75
+ pending += glyphHex(glyphId);
76
+ const formatted = formatNumber(adjustment);
77
+ if (formatted !== "0") {
78
+ body += `<${pending}>${formatted}`;
79
+ pending = "";
80
+ }
81
+ }
82
+ if (pending !== "") body += `<${pending}>`;
83
+ line(`[${body}] TJ`);
84
+ },
85
+ showBytes: (bytes) => {
86
+ let text = "";
87
+ for (const byte of bytes) if (byte === 40 || byte === 41 || byte === 92) text += `\\${String.fromCharCode(byte)}`;
88
+ else if (byte < 32 || byte > 126) text += `\\${byte.toString(8).padStart(3, "0")}`;
89
+ else text += String.fromCharCode(byte);
90
+ line(`(${text}) Tj`);
91
+ },
92
+ drawImage: (imageIndex) => use({
93
+ kind: "image",
94
+ imageIndex
95
+ }, " Do"),
96
+ parts: () => parts
97
+ };
98
+ };
99
+ const collectResources = (parts) => {
100
+ const fonts = /* @__PURE__ */ new Set();
101
+ const images = /* @__PURE__ */ new Set();
102
+ const alphas = /* @__PURE__ */ new Set();
103
+ for (const part of parts) switch (part.kind) {
104
+ case "literal": break;
105
+ case "font":
106
+ fonts.add(part.resourceIndex);
107
+ break;
108
+ case "image":
109
+ images.add(part.imageIndex);
110
+ break;
111
+ case "extGState":
112
+ alphas.add(formatNumber(part.alpha));
113
+ break;
114
+ default: panic(`unhandled content part: ${JSON.stringify(part)}`);
115
+ }
116
+ const numberNames = (keys, prefix) => new Map([...keys].sort((left, right) => left - right).map((key, index) => [key, `${prefix}${String(index + 1)}`]));
117
+ return {
118
+ fontNames: numberNames(fonts, "F"),
119
+ imageNames: numberNames(images, "Im"),
120
+ extGStateNames: new Map([...alphas].sort((left, right) => Number(left) - Number(right)).map((key, index) => [key, `GS${String(index + 1)}`]))
121
+ };
122
+ };
123
+ const renderContentStream = (parts, resources) => {
124
+ let out = "";
125
+ for (const part of parts) switch (part.kind) {
126
+ case "literal":
127
+ out += part.text;
128
+ break;
129
+ case "font":
130
+ out += `/${resources.fontNames.get(part.resourceIndex) ?? panic("unnamed font resource")}`;
131
+ break;
132
+ case "image":
133
+ out += `/${resources.imageNames.get(part.imageIndex) ?? panic("unnamed image resource")}`;
134
+ break;
135
+ case "extGState":
136
+ out += `/${resources.extGStateNames.get(formatNumber(part.alpha)) ?? panic("unnamed graphics state")}`;
137
+ break;
138
+ default: panic(`unhandled content part: ${JSON.stringify(part)}`);
139
+ }
140
+ return out;
141
+ };
142
+ //#endregion
143
+ export { TEXT_RENDER_MODE, collectResources, createContentStream, renderContentStream };
@@ -0,0 +1,96 @@
1
+ import { DisplayFontFace } from "../display-list/types.js";
2
+ import { Shaper, ShapingDirection } from "../shaping/shaper.js";
3
+ import { PdfDocument, PdfRef } from "./objects.js";
4
+ import { PdfUnencodable } from "./writePdf.js";
5
+ //#region src/pdf/fonts.d.ts
6
+ type PdfFontSource = {
7
+ /**
8
+ * Every binary that carries part of this face, in priority order. A code
9
+ * point is served by the first binary whose cmap covers it.
10
+ */
11
+ readonly load: (face: DisplayFontFace) => readonly Uint8Array[];
12
+ };
13
+ type PdfSubstitution = {
14
+ readonly family: string;
15
+ readonly weight: number;
16
+ readonly italic: boolean;
17
+ readonly reason: string;
18
+ };
19
+ /** A code point placed in the glyph space of the resource that serves it. */
20
+ type PdfGlyph = {
21
+ /** The PDF font resource this glyph id belongs to. */
22
+ readonly resourceIndex: number;
23
+ readonly glyphId: number;
24
+ /** The width this file declares for the glyph, in 1000ths of an em. */
25
+ readonly widthUnits: number;
26
+ };
27
+ /**
28
+ * One face, ready to paint. The two branches differ in how a code point
29
+ * reaches the page, so the painter switches on `kind` rather than carrying
30
+ * optional fields that are only valid in one of them.
31
+ */
32
+ /** One shaped glyph, in the glyph space of the resource that will paint it. */
33
+ type PlacedPdfGlyph = PdfGlyph & {
34
+ /** Code-point index in the run's text of the cluster this glyph came from. */
35
+ readonly clusterIndex: number;
36
+ readonly xAdvancePx: number;
37
+ readonly xOffsetPx: number;
38
+ readonly yOffsetPx: number;
39
+ };
40
+ /** A run whose glyphs shaping has to choose, as the collection pass saw it. */
41
+ type ShapedRunRequest = {
42
+ readonly text: string;
43
+ readonly direction: ShapingDirection;
44
+ readonly fontSizePx: number;
45
+ };
46
+ /** A face embedded as a subset of its own program. */
47
+ type EmbeddedPdfFont = {
48
+ readonly kind: "embedded";
49
+ /** Resource and subset glyph for a code point the collection pass saw. */
50
+ readonly glyphFor: (codePoint: number) => PdfGlyph;
51
+ /**
52
+ * The glyphs shaping chose for a run, in visual order, or `null` when this
53
+ * run was not shaped: no shaper was resolved, or the run is in a script where
54
+ * a code point selects its own glyph.
55
+ */
56
+ readonly placeShapedRun: (request: ShapedRunRequest) => readonly PlacedPdfGlyph[] | null;
57
+ };
58
+ /** A base-14 stand-in for a face that could not be embedded. */
59
+ type StandardPdfFont = {
60
+ readonly kind: "standard";
61
+ readonly resourceIndex: number;
62
+ /** WinAnsi byte for a code point. */
63
+ readonly byteFor: (codePoint: number) => number;
64
+ };
65
+ type PreparedFont = EmbeddedPdfFont | StandardPdfFont;
66
+ type PrepareFontsOptions = {
67
+ readonly document: PdfDocument;
68
+ readonly faces: readonly DisplayFontFace[];
69
+ /** Font index to the code points the document paints from that face. */
70
+ readonly usedCodePoints: ReadonlyMap<number, ReadonlySet<number>>;
71
+ /** Font index to the runs whose glyphs shaping has to choose. */
72
+ readonly shapedRuns?: ReadonlyMap<number, readonly ShapedRunRequest[]>;
73
+ /**
74
+ * The shaper, when the document contains a run that needs one. Absent leaves
75
+ * such runs painted one glyph per code point, which the scripts that shape do
76
+ * not read as; the caller resolves a shaper whenever the display list has
77
+ * one, which is what keeps the artifact off the path of a Latin document.
78
+ */
79
+ readonly shaper?: Shaper | null;
80
+ readonly source: PdfFontSource;
81
+ };
82
+ type PreparedFonts = {
83
+ readonly byFontIndex: ReadonlyMap<number, PreparedFont>;
84
+ /** Every PDF font resource the pages may name, by resource index. */
85
+ readonly fontRefByResourceIndex: ReadonlyMap<number, PdfRef>;
86
+ readonly substitutions: readonly PdfSubstitution[];
87
+ readonly unencodable: readonly PdfUnencodable[];
88
+ };
89
+ /**
90
+ * Turns the display list's font table into PDF font objects. A face nothing
91
+ * paints is skipped entirely: an unused face is not a substitution, and
92
+ * embedding it would put bytes in the file no page reads.
93
+ */
94
+ declare const prepareFonts: ({ document, faces, usedCodePoints, shapedRuns, shaper, source }: PrepareFontsOptions) => PreparedFonts;
95
+ //#endregion
96
+ export { EmbeddedPdfFont, PdfFontSource, PdfGlyph, PdfSubstitution, PlacedPdfGlyph, PreparedFont, PreparedFonts, ShapedRunRequest, StandardPdfFont, prepareFonts };