postext-pdf 1.4.2 → 1.5.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 (208) hide show
  1. package/README.md +3 -3
  2. package/dist/__tests__/accessibility.test.js +66 -0
  3. package/dist/__tests__/accessibility.test.js.map +1 -1
  4. package/dist/__tests__/alpha.test.d.ts +2 -0
  5. package/dist/__tests__/alpha.test.d.ts.map +1 -0
  6. package/dist/__tests__/alpha.test.js +164 -0
  7. package/dist/__tests__/alpha.test.js.map +1 -0
  8. package/dist/__tests__/bleedClip.test.d.ts +2 -0
  9. package/dist/__tests__/bleedClip.test.d.ts.map +1 -0
  10. package/dist/__tests__/bleedClip.test.js +83 -0
  11. package/dist/__tests__/bleedClip.test.js.map +1 -0
  12. package/dist/__tests__/boxBorderInside.test.d.ts +2 -0
  13. package/dist/__tests__/boxBorderInside.test.d.ts.map +1 -0
  14. package/dist/__tests__/boxBorderInside.test.js +63 -0
  15. package/dist/__tests__/boxBorderInside.test.js.map +1 -0
  16. package/dist/__tests__/calloutRuntTracking.test.d.ts +2 -0
  17. package/dist/__tests__/calloutRuntTracking.test.d.ts.map +1 -0
  18. package/dist/__tests__/calloutRuntTracking.test.js +72 -0
  19. package/dist/__tests__/calloutRuntTracking.test.js.map +1 -0
  20. package/dist/__tests__/calloutStripeRadius.test.d.ts +2 -0
  21. package/dist/__tests__/calloutStripeRadius.test.d.ts.map +1 -0
  22. package/dist/__tests__/calloutStripeRadius.test.js +90 -0
  23. package/dist/__tests__/calloutStripeRadius.test.js.map +1 -0
  24. package/dist/__tests__/chipVerticalPadding.test.d.ts +2 -0
  25. package/dist/__tests__/chipVerticalPadding.test.d.ts.map +1 -0
  26. package/dist/__tests__/chipVerticalPadding.test.js +71 -0
  27. package/dist/__tests__/chipVerticalPadding.test.js.map +1 -0
  28. package/dist/__tests__/chips.test.js +20 -3
  29. package/dist/__tests__/chips.test.js.map +1 -1
  30. package/dist/__tests__/documentLanguage.test.d.ts +2 -0
  31. package/dist/__tests__/documentLanguage.test.d.ts.map +1 -0
  32. package/dist/__tests__/documentLanguage.test.js +44 -0
  33. package/dist/__tests__/documentLanguage.test.js.map +1 -0
  34. package/dist/__tests__/fallbackSpaces.test.d.ts +2 -0
  35. package/dist/__tests__/fallbackSpaces.test.d.ts.map +1 -0
  36. package/dist/__tests__/fallbackSpaces.test.js +156 -0
  37. package/dist/__tests__/fallbackSpaces.test.js.map +1 -0
  38. package/dist/__tests__/floatReadingOrder.test.d.ts +2 -0
  39. package/dist/__tests__/floatReadingOrder.test.d.ts.map +1 -0
  40. package/dist/__tests__/floatReadingOrder.test.js +208 -0
  41. package/dist/__tests__/floatReadingOrder.test.js.map +1 -0
  42. package/dist/__tests__/fontEmbedding.test.d.ts +2 -0
  43. package/dist/__tests__/fontEmbedding.test.d.ts.map +1 -0
  44. package/dist/__tests__/fontEmbedding.test.js +118 -0
  45. package/dist/__tests__/fontEmbedding.test.js.map +1 -0
  46. package/dist/__tests__/fontFaces.test.d.ts +2 -0
  47. package/dist/__tests__/fontFaces.test.d.ts.map +1 -0
  48. package/dist/__tests__/fontFaces.test.js +193 -0
  49. package/dist/__tests__/fontFaces.test.js.map +1 -0
  50. package/dist/__tests__/fontStack.test.d.ts +2 -0
  51. package/dist/__tests__/fontStack.test.d.ts.map +1 -0
  52. package/dist/__tests__/fontStack.test.js +48 -0
  53. package/dist/__tests__/fontStack.test.js.map +1 -0
  54. package/dist/__tests__/headerFooter.test.js +83 -1
  55. package/dist/__tests__/headerFooter.test.js.map +1 -1
  56. package/dist/__tests__/headingAlign.test.d.ts +2 -0
  57. package/dist/__tests__/headingAlign.test.d.ts.map +1 -0
  58. package/dist/__tests__/headingAlign.test.js +66 -0
  59. package/dist/__tests__/headingAlign.test.js.map +1 -0
  60. package/dist/__tests__/hiddenHeadings.test.d.ts +2 -0
  61. package/dist/__tests__/hiddenHeadings.test.d.ts.map +1 -0
  62. package/dist/__tests__/hiddenHeadings.test.js +96 -0
  63. package/dist/__tests__/hiddenHeadings.test.js.map +1 -0
  64. package/dist/__tests__/lineTracking.test.d.ts +2 -0
  65. package/dist/__tests__/lineTracking.test.d.ts.map +1 -0
  66. package/dist/__tests__/lineTracking.test.js +80 -0
  67. package/dist/__tests__/lineTracking.test.js.map +1 -0
  68. package/dist/__tests__/measuredLines.test.d.ts +2 -0
  69. package/dist/__tests__/measuredLines.test.d.ts.map +1 -0
  70. package/dist/__tests__/measuredLines.test.js +255 -0
  71. package/dist/__tests__/measuredLines.test.js.map +1 -0
  72. package/dist/__tests__/metadata.test.d.ts +2 -0
  73. package/dist/__tests__/metadata.test.d.ts.map +1 -0
  74. package/dist/__tests__/metadata.test.js +51 -0
  75. package/dist/__tests__/metadata.test.js.map +1 -0
  76. package/dist/__tests__/outlineTitles.test.d.ts +2 -0
  77. package/dist/__tests__/outlineTitles.test.d.ts.map +1 -0
  78. package/dist/__tests__/outlineTitles.test.js +59 -0
  79. package/dist/__tests__/outlineTitles.test.js.map +1 -0
  80. package/dist/__tests__/pdfGenerationConfig.test.d.ts +2 -0
  81. package/dist/__tests__/pdfGenerationConfig.test.d.ts.map +1 -0
  82. package/dist/__tests__/pdfGenerationConfig.test.js +76 -0
  83. package/dist/__tests__/pdfGenerationConfig.test.js.map +1 -0
  84. package/dist/__tests__/pdfWorker.test.d.ts +2 -0
  85. package/dist/__tests__/pdfWorker.test.d.ts.map +1 -0
  86. package/dist/__tests__/pdfWorker.test.js +123 -0
  87. package/dist/__tests__/pdfWorker.test.js.map +1 -0
  88. package/dist/__tests__/printMarks.test.d.ts +2 -0
  89. package/dist/__tests__/printMarks.test.d.ts.map +1 -0
  90. package/dist/__tests__/printMarks.test.js +170 -0
  91. package/dist/__tests__/printMarks.test.js.map +1 -0
  92. package/dist/__tests__/printMaster.test.d.ts +2 -0
  93. package/dist/__tests__/printMaster.test.d.ts.map +1 -0
  94. package/dist/__tests__/printMaster.test.js +161 -0
  95. package/dist/__tests__/printMaster.test.js.map +1 -0
  96. package/dist/__tests__/renderWarnings.test.d.ts +2 -0
  97. package/dist/__tests__/renderWarnings.test.d.ts.map +1 -0
  98. package/dist/__tests__/renderWarnings.test.js +89 -0
  99. package/dist/__tests__/renderWarnings.test.js.map +1 -0
  100. package/dist/__tests__/repeatedHyphen.test.d.ts +2 -0
  101. package/dist/__tests__/repeatedHyphen.test.d.ts.map +1 -0
  102. package/dist/__tests__/repeatedHyphen.test.js +125 -0
  103. package/dist/__tests__/repeatedHyphen.test.js.map +1 -0
  104. package/dist/__tests__/scriptStacking.test.d.ts +2 -0
  105. package/dist/__tests__/scriptStacking.test.d.ts.map +1 -0
  106. package/dist/__tests__/scriptStacking.test.js +66 -0
  107. package/dist/__tests__/scriptStacking.test.js.map +1 -0
  108. package/dist/__tests__/sectionColumnRule.test.d.ts +2 -0
  109. package/dist/__tests__/sectionColumnRule.test.d.ts.map +1 -0
  110. package/dist/__tests__/sectionColumnRule.test.js +144 -0
  111. package/dist/__tests__/sectionColumnRule.test.js.map +1 -0
  112. package/dist/__tests__/svgFormReuse.test.d.ts +2 -0
  113. package/dist/__tests__/svgFormReuse.test.d.ts.map +1 -0
  114. package/dist/__tests__/svgFormReuse.test.js +102 -0
  115. package/dist/__tests__/svgFormReuse.test.js.map +1 -0
  116. package/dist/__tests__/svgVector.test.js +85 -11
  117. package/dist/__tests__/svgVector.test.js.map +1 -1
  118. package/dist/__tests__/tableFillSeams.test.d.ts +2 -0
  119. package/dist/__tests__/tableFillSeams.test.d.ts.map +1 -0
  120. package/dist/__tests__/tableFillSeams.test.js +72 -0
  121. package/dist/__tests__/tableFillSeams.test.js.map +1 -0
  122. package/dist/__tests__/tocLeaderKerning.test.d.ts +2 -0
  123. package/dist/__tests__/tocLeaderKerning.test.d.ts.map +1 -0
  124. package/dist/__tests__/tocLeaderKerning.test.js +84 -0
  125. package/dist/__tests__/tocLeaderKerning.test.js.map +1 -0
  126. package/dist/__tests__/tocNumberBaseline.test.d.ts +2 -0
  127. package/dist/__tests__/tocNumberBaseline.test.d.ts.map +1 -0
  128. package/dist/__tests__/tocNumberBaseline.test.js +72 -0
  129. package/dist/__tests__/tocNumberBaseline.test.js.map +1 -0
  130. package/dist/__tests__/tocTagging.test.d.ts +2 -0
  131. package/dist/__tests__/tocTagging.test.d.ts.map +1 -0
  132. package/dist/__tests__/tocTagging.test.js +120 -0
  133. package/dist/__tests__/tocTagging.test.js.map +1 -0
  134. package/dist/__tests__/trackedLineAlign.test.d.ts +2 -0
  135. package/dist/__tests__/trackedLineAlign.test.d.ts.map +1 -0
  136. package/dist/__tests__/trackedLineAlign.test.js +73 -0
  137. package/dist/__tests__/trackedLineAlign.test.js.map +1 -0
  138. package/dist/__tests__/uriLinks.test.d.ts +2 -0
  139. package/dist/__tests__/uriLinks.test.d.ts.map +1 -0
  140. package/dist/__tests__/uriLinks.test.js +103 -0
  141. package/dist/__tests__/uriLinks.test.js.map +1 -0
  142. package/dist/colors.d.ts +18 -3
  143. package/dist/colors.d.ts.map +1 -1
  144. package/dist/colors.js +77 -25
  145. package/dist/colors.js.map +1 -1
  146. package/dist/fontCache.d.ts +67 -4
  147. package/dist/fontCache.d.ts.map +1 -1
  148. package/dist/fontCache.js +200 -23
  149. package/dist/fontCache.js.map +1 -1
  150. package/dist/index.d.ts +1 -1
  151. package/dist/index.d.ts.map +1 -1
  152. package/dist/pdf-backend/blockRender.d.ts.map +1 -1
  153. package/dist/pdf-backend/blockRender.js +127 -28
  154. package/dist/pdf-backend/blockRender.js.map +1 -1
  155. package/dist/pdf-backend/fallbackSpaces.d.ts +37 -0
  156. package/dist/pdf-backend/fallbackSpaces.d.ts.map +1 -0
  157. package/dist/pdf-backend/fallbackSpaces.js +119 -0
  158. package/dist/pdf-backend/fallbackSpaces.js.map +1 -0
  159. package/dist/pdf-backend/fontHelpers.d.ts +10 -1
  160. package/dist/pdf-backend/fontHelpers.d.ts.map +1 -1
  161. package/dist/pdf-backend/fontHelpers.js +111 -65
  162. package/dist/pdf-backend/fontHelpers.js.map +1 -1
  163. package/dist/pdf-backend/headerFooter.d.ts +4 -2
  164. package/dist/pdf-backend/headerFooter.d.ts.map +1 -1
  165. package/dist/pdf-backend/headerFooter.js +105 -48
  166. package/dist/pdf-backend/headerFooter.js.map +1 -1
  167. package/dist/pdf-backend/index.d.ts +55 -6
  168. package/dist/pdf-backend/index.d.ts.map +1 -1
  169. package/dist/pdf-backend/index.js +135 -35
  170. package/dist/pdf-backend/index.js.map +1 -1
  171. package/dist/pdf-backend/links.d.ts +82 -1
  172. package/dist/pdf-backend/links.d.ts.map +1 -1
  173. package/dist/pdf-backend/links.js +141 -3
  174. package/dist/pdf-backend/links.js.map +1 -1
  175. package/dist/pdf-backend/outlines.d.ts.map +1 -1
  176. package/dist/pdf-backend/outlines.js +7 -0
  177. package/dist/pdf-backend/outlines.js.map +1 -1
  178. package/dist/pdf-backend/pageDecorations.d.ts.map +1 -1
  179. package/dist/pdf-backend/pageDecorations.js +42 -26
  180. package/dist/pdf-backend/pageDecorations.js.map +1 -1
  181. package/dist/pdf-backend/primitives.d.ts +61 -1
  182. package/dist/pdf-backend/primitives.d.ts.map +1 -1
  183. package/dist/pdf-backend/primitives.js +318 -18
  184. package/dist/pdf-backend/primitives.js.map +1 -1
  185. package/dist/pdf-backend/renderResourceBlock.d.ts +3 -1
  186. package/dist/pdf-backend/renderResourceBlock.d.ts.map +1 -1
  187. package/dist/pdf-backend/renderResourceBlock.js +97 -19
  188. package/dist/pdf-backend/renderResourceBlock.js.map +1 -1
  189. package/dist/pdf-backend/structureFlow.d.ts +70 -3
  190. package/dist/pdf-backend/structureFlow.d.ts.map +1 -1
  191. package/dist/pdf-backend/structureFlow.js +209 -27
  192. package/dist/pdf-backend/structureFlow.js.map +1 -1
  193. package/dist/pdf-backend/svgVector.d.ts +7 -2
  194. package/dist/pdf-backend/svgVector.d.ts.map +1 -1
  195. package/dist/pdf-backend/svgVector.js +157 -72
  196. package/dist/pdf-backend/svgVector.js.map +1 -1
  197. package/dist/pdf-backend/tagging.d.ts +1 -1
  198. package/dist/pdf-backend/tagging.d.ts.map +1 -1
  199. package/dist/pdf-backend/tagging.js.map +1 -1
  200. package/dist/worker/client.d.ts +1 -1
  201. package/dist/worker/client.d.ts.map +1 -1
  202. package/dist/worker/client.js +8 -0
  203. package/dist/worker/client.js.map +1 -1
  204. package/dist/worker/pdf.worker.js +1 -0
  205. package/dist/worker/pdf.worker.js.map +1 -1
  206. package/dist/worker/protocol.d.ts +8 -1
  207. package/dist/worker/protocol.d.ts.map +1 -1
  208. package/package.json +3 -3
package/dist/fontCache.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { padTrueTypeGlyphs } from './trueTypePadding';
2
+ import { PDFDict, PDFName, PDFRef, PDFStream } from 'pdf-lib';
2
3
  import { fontKey, parseFontString } from './fontString';
3
4
  /** True when `bytes` starts with the `OTTO` magic identifying a CFF-flavored
4
5
  * OpenType font — the ones pdf-lib cannot subset reliably, so they embed
@@ -92,20 +93,132 @@ export function coverAllGlyphUnicode(font) {
92
93
  return context.register(context.flateStream(toUnicodeCmap(glyphs)));
93
94
  };
94
95
  }
96
+ /** The nine standard weights: the cuts a font provider may have. */
97
+ const STANDARD_WEIGHTS = [100, 200, 300, 400, 500, 600, 700, 800, 900];
98
+ /** `weights` in the order CSS font matching tries them for `desired`
99
+ * (CSS Fonts 4 §5.2): from 400 to 500, the weights up to 500 ascending,
100
+ * then the lighter ones descending, then the heavier ones ascending; below
101
+ * 400, lighter (or equal) descending, then heavier ascending; above 500,
102
+ * heavier (or equal) ascending, then lighter descending. The browser picks
103
+ * the same face, so the PDF matches the preview. */
104
+ export function cssWeightOrder(desired, weights) {
105
+ const asc = [...new Set(weights)].sort((a, b) => a - b);
106
+ if (desired >= 400 && desired <= 500) {
107
+ return [
108
+ ...asc.filter((w) => w >= desired && w <= 500),
109
+ ...asc.filter((w) => w < desired).reverse(),
110
+ ...asc.filter((w) => w > 500),
111
+ ];
112
+ }
113
+ if (desired < 400)
114
+ return [...asc.filter((w) => w <= desired).reverse(), ...asc.filter((w) => w > desired)];
115
+ return [...asc.filter((w) => w >= desired), ...asc.filter((w) => w < desired).reverse()];
116
+ }
117
+ /** Faces of the same family to try, in order, when the provider rejects
118
+ * `spec`: every standard weight in the requested style, in CSS matching
119
+ * order ({@link cssWeightOrder}), then every weight in the other style
120
+ * the same way — italic falls back to upright, and upright to italic. A
121
+ * family with no italics (a display face) sets its italic runs upright; a
122
+ * family shipping only 400 and 700 takes a 600 as 700; one shipping a
123
+ * single cut sets everything in it. */
124
+ export function fallbackFaces(spec) {
125
+ const weights = cssWeightOrder(spec.weight, [...STANDARD_WEIGHTS, spec.weight]);
126
+ const styles = spec.style === 'italic' ? ['italic', 'normal'] : ['normal', 'italic'];
127
+ const out = [];
128
+ for (const style of styles) {
129
+ for (const weight of weights) {
130
+ if (style === spec.style && weight === spec.weight)
131
+ continue;
132
+ out.push({ family: spec.family, weight, style });
133
+ }
134
+ }
135
+ return out;
136
+ }
95
137
  /**
96
138
  * Per-document mapping from `family|weight|style` to an embedded pdf-lib
97
139
  * font. Entries are populated up-front by `preload()` so that block-level
98
- * rendering (`get()`) is a sync lookup. A fontString that fails to parse or
99
- * to load is mapped to `null` and reported back via `missing()`.
140
+ * rendering (`get()`) is a sync lookup. A face the provider rejects falls
141
+ * back to another face of its family ({@link fallbackFaces}), reported
142
+ * through `onFallback`; a fontString that fails to parse, or whose family
143
+ * the provider cannot supply at all (no standard weight in either style),
144
+ * is mapped to `null` and reported back via `missing()`. Faces the
145
+ * provider answers with the same file share one embedded font, and
146
+ * `dropUnusedFonts()` keeps the fonts no page draws with out of the file.
100
147
  */
101
148
  export class FontCache {
102
149
  pdfDoc;
103
150
  provider;
151
+ onFallback;
104
152
  map = new Map();
105
153
  failed = new Set();
106
- constructor(pdfDoc, provider) {
154
+ /** One load per actual face, shared by every key that falls back to it. */
155
+ loads = new Map();
156
+ errors = new Map();
157
+ /** Loaded faces by lower-cased family, for lookups nothing preloaded. */
158
+ byFamily = new Map();
159
+ /** Embeds by the byte length of their file: a provider that answers
160
+ * several faces with one file (a stand-in for a cut the family lacks)
161
+ * gets it embedded once, whatever the faces. */
162
+ byLength = new Map();
163
+ /** Every font this cache embedded. */
164
+ embedded = new Set();
165
+ constructor(pdfDoc, provider, onFallback) {
107
166
  this.pdfDoc = pdfDoc;
108
167
  this.provider = provider;
168
+ this.onFallback = onFallback;
169
+ }
170
+ /** Embed a font file, once per distinct content. */
171
+ embedBytes(bytes) {
172
+ const same = this.byLength.get(bytes.length) ?? [];
173
+ const known = same.find((entry) => sameBytes(entry.bytes, bytes));
174
+ if (known)
175
+ return known.font;
176
+ const font = (async () => {
177
+ // pdf-lib's CFF subsetter emits a font stream some viewers cannot
178
+ // parse (macOS Preview draws the text in a fallback face), so CFF
179
+ // OpenType (.otf, signature `OTTO`) embeds whole — larger PDF, but
180
+ // every viewer reads it. TrueType fonts subset normally.
181
+ const subset = !isCffOpenType(bytes);
182
+ // fontkit's TrueType subsetter mis-writes the offsets of fonts whose
183
+ // glyph records are not 4-byte aligned (instanced variable fonts,
184
+ // typically): pad them first so every glyph survives the subset.
185
+ const embeddable = subset ? padTrueTypeGlyphs(bytes) : bytes;
186
+ const embedded = await this.pdfDoc.embedFont(embeddable, { subset });
187
+ if (!subset) {
188
+ coverAllGlyphWidths(embedded);
189
+ coverAllGlyphUnicode(embedded);
190
+ }
191
+ this.embedded.add(embedded);
192
+ return embedded;
193
+ })();
194
+ same.push({ bytes, font });
195
+ this.byLength.set(bytes.length, same);
196
+ return font;
197
+ }
198
+ /** Fetch and embed one face, once. Null when the provider rejects it or
199
+ * its bytes do not embed. */
200
+ loadFace(spec) {
201
+ const key = fontKey(spec.family, spec.weight, spec.style);
202
+ const pending = this.loads.get(key);
203
+ if (pending)
204
+ return pending;
205
+ const load = (async () => {
206
+ try {
207
+ const bytes = await this.provider(spec.family, spec.weight, spec.style);
208
+ const font = await this.embedBytes(bytes);
209
+ const family = spec.family.toLowerCase();
210
+ const faces = this.byFamily.get(family) ?? [];
211
+ faces.push({ ...spec, font });
212
+ this.byFamily.set(family, faces);
213
+ return font;
214
+ }
215
+ catch (err) {
216
+ this.errors.set(key, err instanceof Error ? err.message : String(err));
217
+ return null;
218
+ }
219
+ })();
220
+ this.loads.set(key, load);
221
+ return load;
109
222
  }
110
223
  async preloadFontStrings(fontStrings) {
111
224
  const jobs = new Map();
@@ -121,28 +234,27 @@ export class FontCache {
121
234
  jobs.set(key, { family: parsed.family, weight: parsed.weight, style: parsed.style });
122
235
  }
123
236
  await Promise.all(Array.from(jobs.entries()).map(async ([key, spec]) => {
124
- try {
125
- const bytes = await this.provider(spec.family, spec.weight, spec.style);
126
- // pdf-lib's CFF subsetter emits a font stream some viewers cannot
127
- // parse (macOS Preview draws the text in a fallback face), so CFF
128
- // OpenType (.otf, signature `OTTO`) embeds whole — larger PDF, but
129
- // every viewer reads it. TrueType fonts subset normally.
130
- const subset = !isCffOpenType(bytes);
131
- // fontkit's TrueType subsetter mis-writes the offsets of fonts whose
132
- // glyph records are not 4-byte aligned (instanced variable fonts,
133
- // typically): pad them first so every glyph survives the subset.
134
- const embeddable = subset ? padTrueTypeGlyphs(bytes) : bytes;
135
- const font = await this.pdfDoc.embedFont(embeddable, { subset });
136
- if (!subset) {
137
- coverAllGlyphWidths(font);
138
- coverAllGlyphUnicode(font);
139
- }
237
+ const font = await this.loadFace(spec);
238
+ if (font) {
140
239
  this.map.set(key, font);
240
+ return;
141
241
  }
142
- catch {
143
- this.failed.add(`${spec.family} ${spec.weight}${spec.style === 'italic' ? ' italic' : ''}`);
144
- this.map.set(key, null);
242
+ // One candidate at a time, so no face is fetched (and embedded)
243
+ // that nothing is set in; a face asked once is never asked again.
244
+ for (const alt of fallbackFaces(spec)) {
245
+ const altFont = await this.loadFace(alt);
246
+ if (!altFont)
247
+ continue;
248
+ this.map.set(key, altFont);
249
+ this.onFallback?.({
250
+ ...spec,
251
+ fallback: { weight: alt.weight, style: alt.style },
252
+ reason: this.errors.get(key) ?? 'rejected by the font provider',
253
+ });
254
+ return;
145
255
  }
256
+ this.failed.add(`${spec.family} ${spec.weight}${spec.style === 'italic' ? ' italic' : ''}`);
257
+ this.map.set(key, null);
146
258
  }));
147
259
  }
148
260
  get(fontString) {
@@ -150,10 +262,75 @@ export class FontCache {
150
262
  if (!parsed)
151
263
  return null;
152
264
  const key = fontKey(parsed.family, parsed.weight, parsed.style);
153
- return this.map.get(key) ?? null;
265
+ const hit = this.map.get(key);
266
+ if (hit !== undefined)
267
+ return hit;
268
+ // Never preloaded: the nearest loaded face of the family (same style
269
+ // first), so a face the plan missed still paints its text.
270
+ const faces = this.byFamily.get(parsed.family.toLowerCase());
271
+ if (!faces || faces.length === 0)
272
+ return null;
273
+ const sameStyle = faces.filter((f) => f.style === parsed.style);
274
+ const pool = sameStyle.length > 0 ? sameStyle : faces;
275
+ const weight = cssWeightOrder(parsed.weight, pool.map((f) => f.weight))[0];
276
+ return pool.find((f) => f.weight === weight).font;
154
277
  }
155
278
  missing() {
156
279
  return [...this.failed];
157
280
  }
281
+ /** Leave out of the file every font this cache embedded that no page
282
+ * draws with: a face asked for but never set (the text of a figure
283
+ * later drawn as a picture, say) would otherwise be written anyway,
284
+ * since pdf-lib writes every font it embedded. Call it once all pages
285
+ * are drawn, right before `save()`. */
286
+ dropUnusedFonts() {
287
+ // pdf-lib keeps its embedded fonts in a private list and writes each
288
+ // one on save; a font taken out of it is never written.
289
+ const fonts = this.pdfDoc.fonts;
290
+ if (!Array.isArray(fonts))
291
+ return;
292
+ const used = fontRefsInUse(this.pdfDoc);
293
+ for (let i = fonts.length - 1; i >= 0; i--) {
294
+ const font = fonts[i];
295
+ if (this.embedded.has(font) && !used.has(font.ref.toString()))
296
+ fonts.splice(i, 1);
297
+ }
298
+ }
299
+ }
300
+ /** Whether two files hold the same bytes. */
301
+ function sameBytes(a, b) {
302
+ if (a === b)
303
+ return true;
304
+ if (a.length !== b.length)
305
+ return false;
306
+ for (let i = 0; i < a.length; i++)
307
+ if (a[i] !== b[i])
308
+ return false;
309
+ return true;
310
+ }
311
+ /** The fonts the pages name in their resources, and in those of the form
312
+ * XObjects they draw, as reference strings. */
313
+ function fontRefsInUse(pdfDoc) {
314
+ const used = new Set();
315
+ const seen = new Set();
316
+ const visit = (resources) => {
317
+ if (!resources || seen.has(resources))
318
+ return;
319
+ seen.add(resources);
320
+ const fonts = resources.lookupMaybe(PDFName.of('Font'), PDFDict);
321
+ for (const [, value] of fonts?.entries() ?? [])
322
+ used.add(value.toString());
323
+ const xobjects = resources.lookupMaybe(PDFName.of('XObject'), PDFDict);
324
+ for (const [, value] of xobjects?.entries() ?? []) {
325
+ // Images and embedded pages are written on save, so a reference
326
+ // may not resolve yet; only a form drawn here can name a font.
327
+ const xobject = value instanceof PDFRef ? pdfDoc.context.lookup(value) : value;
328
+ if (xobject instanceof PDFStream)
329
+ visit(xobject.dict.lookupMaybe(PDFName.of('Resources'), PDFDict));
330
+ }
331
+ };
332
+ for (const page of pdfDoc.getPages())
333
+ visit(page.node.Resources());
334
+ return used;
158
335
  }
159
336
  //# sourceMappingURL=fontCache.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fontCache.js","sourceRoot":"","sources":["../src/fontCache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fontCache.js","sourceRoot":"","sources":["../src/fontCache.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { renderToPdf } from './pdf-backend';
2
- export type { RenderToPdfOptions, RenderProgress, PdfFontProvider, ResourceBytesProvider } from './pdf-backend';
2
+ export type { RenderToPdfOptions, RenderProgress, PdfFontProvider, PdfWarning, PdfFontFallbackWarning, ResourceBytesProvider } from './pdf-backend';
3
3
  export { decompressWoff2 } from './woff2';
4
4
  export { svgToVectorDrawing, type VectorDrawing } from './pdf-backend/svgVector';
5
5
  export { sniffBytes, rasterizeSvgWithDom, type SvgRasterizer } from './pdf-backend/renderResourceBlock';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAChH,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,mCAAmC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACpJ,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,mCAAmC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"blockRender.d.ts","sourceRoot":"","sources":["../../src/pdf-backend/blockRender.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAuC,MAAM,SAAS,CAAC;AAE7E,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,KAAK,OAAO,EAAsD,MAAM,cAAc,CAAC;AAIhG,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,mFAAmF;AACnF,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,gBAAgB,CAAC;IACzB,YAAY,EAAE,YAAY,CAAC;IAC3B,4EAA4E;IAC5E,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B;AA+PD,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,QAAQ,EACf,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,EACpB,WAAW,CAAC,EAAE,qBAAqB,GAClC,IAAI,CA0DN"}
1
+ {"version":3,"file":"blockRender.d.ts","sourceRoot":"","sources":["../../src/pdf-backend/blockRender.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAuC,MAAM,SAAS,CAAC;AAE7E,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,KAAK,OAAO,EAAiG,MAAM,cAAc,CAAC;AAI3I,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAmB,MAAM,SAAS,CAAC;AAExD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,mFAAmF;AACnF,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,gBAAgB,CAAC;IACzB,YAAY,EAAE,YAAY,CAAC;IAC3B,4EAA4E;IAC5E,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B;AA4VD,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,QAAQ,EACf,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,EACpB,WAAW,CAAC,EAAE,qBAAqB,GAClC,IAAI,CA0DN"}
@@ -1,10 +1,11 @@
1
- import { setCharacterSpacing } from 'pdf-lib';
1
+ import { popGraphicsState, pushGraphicsState, setCharacterSpacing } from 'pdf-lib';
2
2
  import { parseFontString } from '../fontString';
3
- import { drawLinePx, drawSwatchPx, drawTextPx, colorFromHex } from './primitives';
3
+ import { alphaOf, alphaStateOp, drawLinePx, drawMeasuredTextPx, drawSwatchPx, drawTextPx, colorFromHex } from './primitives';
4
4
  import { paintChip } from './chip';
5
5
  import { pickSegmentColor, pickSegmentFont } from './fontHelpers';
6
6
  import { renderHeaderFooterSlot } from './headerFooter';
7
7
  import { renderResourceBlock, } from './renderResourceBlock';
8
+ import { RefRun, UriRuns } from './links';
8
9
  import { tagArtifact, tagContent } from './tagging';
9
10
  function renderMathRender(ctx, render, topLeftXPx, topLeftYPx, fallbackColor) {
10
11
  if (!render.paths.length || render.viewBox.width <= 0 || render.viewBox.height <= 0)
@@ -21,7 +22,14 @@ function renderMathRender(ctx, render, topLeftXPx, topLeftYPx, fallbackColor) {
21
22
  if (path.fill === 'none')
22
23
  continue;
23
24
  const color = path.fill.startsWith('#') ? colorFromHex(path.fill, ctx.colorSpace) : fallbackColor;
25
+ // A translucent text colour: the constant alpha wraps the path (pdf-lib
26
+ // would add an ExtGState per path otherwise).
27
+ const gs = alphaStateOp(ctx, alphaOf(color));
28
+ if (gs)
29
+ ctx.page.pushOperators(pushGraphicsState(), gs);
24
30
  ctx.page.drawSvgPath(path.d, { x, y, scale: S, color });
31
+ if (gs)
32
+ ctx.page.pushOperators(popGraphicsState());
25
33
  }
26
34
  }
27
35
  function renderMathSegment(ctx, seg, xPx, baselinePx, fallbackColor) {
@@ -38,19 +46,28 @@ function renderMathSegment(ctx, seg, xPx, baselinePx, fallbackColor) {
38
46
  * In a tagged render (`elem` set) the text joins `elem`, each inline formula
39
47
  * gets its own `Formula` element (alt text = its TeX) and each ref a `Link`
40
48
  * element; word spaces are painted as real space glyphs so text extraction
41
- * never has to infer them from the gaps of a justified line.
49
+ * never has to infer them from the gaps of a justified line. A ref painted
50
+ * as several runs (small capitals; the later runs flagged `refContinues`)
51
+ * is still one `Link` element with one annotation over all its runs.
42
52
  */
43
53
  function renderSegments(ctx, segments, startX, baseline, line, block, blockFont, blockSize, blockColor, fontCache, linkRegistry, elem, justifiedSpaceWidth) {
44
54
  let x = startX;
45
- for (const seg of segments) {
55
+ const refRun = new RefRun();
56
+ const uris = new UriRuns(ctx, line, linkRegistry, elem);
57
+ const repeatedAt = repeatedHyphenSegment(line, segments);
58
+ for (let i = 0; i < segments.length; i++) {
59
+ const seg = segments[i];
46
60
  if (seg.kind === 'space') {
61
+ const inLink = uris.space(seg.text);
47
62
  if (ctx.tags && seg.text) {
48
- tagContent(ctx, elem);
63
+ tagContent(ctx, inLink ?? elem);
49
64
  drawTextPx(ctx, seg.text, x, baseline, blockFont, blockSize, blockColor);
50
65
  }
51
66
  x += justifiedSpaceWidth ?? seg.width;
52
67
  continue;
53
68
  }
69
+ if (seg.kind !== 'text' || seg.chip)
70
+ uris.other();
54
71
  if (seg.kind === 'math') {
55
72
  if (elem) {
56
73
  const formula = elem.type === 'Formula' ? elem : elem.child('Formula', { alt: seg.mathRender?.tex ?? '' });
@@ -82,32 +99,54 @@ function renderSegments(ctx, segments, startX, baseline, line, block, blockFont,
82
99
  ? block.refColor
83
100
  : pickSegmentColor(!!seg.bold, !!seg.italic, block));
84
101
  const color = colorHex === block.color ? blockColor : colorFromHex(colorHex, ctx.colorSpace);
85
- const link = seg.refResourceId !== undefined && elem ? elem.child('Link') : undefined;
86
- tagContent(ctx, link ?? elem);
87
- drawTextPx(ctx, seg.text, x, baseline + (seg.baselineShift ?? 0), font, size, color);
88
- if (seg.refResourceId !== undefined && linkRegistry) {
102
+ // A `:ref` links to its resource — one `Link` for all the runs of one
103
+ // set in small capitals —, a Markdown link's words to its URL.
104
+ const uriElem = uris.word(seg.refResourceId === undefined ? seg.href : undefined, x, seg.width, seg.text);
105
+ const link = refRun.enter(seg, x, elem);
106
+ tagContent(ctx, link ?? uriElem ?? elem);
107
+ // The hyphen repeated from the line before is painted but not read.
108
+ const actualText = i === repeatedAt ? seg.text.slice(1) : undefined;
109
+ drawTextPx(ctx, seg.text, x, baseline + (seg.baselineShift ?? 0), font, size, color, undefined, actualText);
110
+ const ref = refRun.leave(seg, segments[i + 1]);
111
+ if (ref && linkRegistry) {
89
112
  const { scale, pageHeightPt } = ctx;
90
- const x1 = x * scale;
113
+ const x1 = ref.startX * scale;
91
114
  const x2 = (x + seg.width) * scale;
92
115
  const y2 = pageHeightPt - line.bbox.y * scale;
93
116
  const y1 = pageHeightPt - (line.bbox.y + line.bbox.height) * scale;
94
- linkRegistry.addLink(ctx.page, [x1, y1, x2, y2], seg.refResourceId, link ? { elem: link, contents: seg.text } : undefined);
117
+ linkRegistry.addLink(ctx.page, [x1, y1, x2, y2], ref.resourceId, link ? { elem: link, contents: ref.text } : undefined);
95
118
  }
96
119
  x += seg.width;
97
120
  }
121
+ uris.end();
98
122
  }
99
- /** Column-balancing tracking: the block was measured with extra advance
100
- * after every glyph, so paint it with the matching character spacing
101
- * (`Tc`, in points at the page scale) and reset it afterwards. */
123
+ /** Tracking: the block (column balancing; negative for a runt set short)
124
+ * and the line (justification tracking) were measured with extra advance
125
+ * after every glyph, so paint the line with the matching character
126
+ * spacing (`Tc`, in points at the page scale) and reset it afterwards. */
102
127
  function renderLine(ctx, line, block, columnWidth, columnX, fontCache, linkRegistry, elem) {
103
- const tracked = block.letterSpacing !== undefined && block.letterSpacing > 0;
104
- if (tracked)
105
- ctx.page.pushOperators(setCharacterSpacing(block.letterSpacing * ctx.scale));
106
- renderLineText(ctx, line, block, columnWidth, columnX, fontCache, linkRegistry, elem);
107
- if (tracked)
128
+ const tracking = (block.letterSpacing ?? 0) + (line.letterSpacing ?? 0);
129
+ if (tracking !== 0)
130
+ ctx.page.pushOperators(setCharacterSpacing(tracking * ctx.scale));
131
+ renderLineText(ctx, line, block, columnWidth, columnX, fontCache, linkRegistry, elem, tracking, trailingTracking(line, tracking));
132
+ if (tracking !== 0)
108
133
  ctx.page.pushOperators(setCharacterSpacing(0));
109
134
  }
110
- function renderLineText(ctx, line, block, columnWidth, columnX, fontCache, linkRegistry, elem) {
135
+ /** The tracking a line's measured width carries after its last glyph:
136
+ * `tracking` when the line ends on text, else 0. It is advance, not ink,
137
+ * so centring and right alignment leave it out (EF-153), as the canvas
138
+ * and HTML backends do (`lineTrailingTracking` in postext). */
139
+ function trailingTracking(line, tracking) {
140
+ if (tracking === 0)
141
+ return 0;
142
+ const segments = line.segments;
143
+ if (segments && segments.length > 0) {
144
+ const last = segments[segments.length - 1];
145
+ return last.kind === 'text' && last.text.length > 0 ? tracking : 0;
146
+ }
147
+ return /\S$/.test(line.text) ? tracking : 0;
148
+ }
149
+ function renderLineText(ctx, line, block, columnWidth, columnX, fontCache, linkRegistry, elem, tracking, trailing = 0) {
111
150
  const blockFont = fontCache.get(block.fontString);
112
151
  if (!blockFont)
113
152
  return;
@@ -141,22 +180,78 @@ function renderLineText(ctx, line, block, columnWidth, columnX, fontCache, linkR
141
180
  let contentWidth = 0;
142
181
  for (const seg of segments)
143
182
  contentWidth += seg.width;
144
- const slack = Math.max(0, effectiveWidth - contentWidth);
183
+ const slack = Math.max(0, effectiveWidth - (contentWidth - trailing));
145
184
  const startX = line.bbox.x + (block.textAlign === 'center' ? slack / 2 : slack);
146
185
  renderSegments(ctx, segments, startX, line.baseline, line, block, blockFont, blockSize, blockColor, fontCache, linkRegistry, elem);
147
186
  return;
148
187
  }
149
188
  // Ragged (left-aligned) rendering — also used for last lines of justified
150
189
  // blocks. Segments are needed when any of them styles differently from the
151
- // block (bold/italic/math/ref/own font or colour); otherwise one drawTextPx
152
- // paints the line.
153
- if (segments && segments.some((s) => s.bold || s.italic || s.kind === 'math' || s.kind === 'swatch' || s.kind === 'chip' || s.refResourceId !== undefined || s.fontString !== undefined || s.color !== undefined || s.baselineShift !== undefined)) {
190
+ // block (bold/italic/math/ref/own font or colour); otherwise one text
191
+ // object paints the line.
192
+ if (segments && segments.some((s) => s.bold || s.italic || s.kind === 'math' || s.kind === 'swatch' || s.kind === 'chip' || s.refResourceId !== undefined || s.href !== undefined || s.fontString !== undefined || s.color !== undefined || s.baselineShift !== undefined)) {
154
193
  renderSegments(ctx, segments, line.bbox.x, line.baseline, line, block, blockFont, blockSize, blockColor, fontCache, linkRegistry, elem);
155
194
  return;
156
195
  }
157
196
  tagContent(ctx, elem);
158
- const plainX = block.textAlign === 'right' ? line.bbox.x + Math.max(0, effectiveWidth - line.bbox.width) : line.bbox.x;
159
- drawTextPx(ctx, line.text, plainX, line.baseline, blockFont, blockSize, blockColor);
197
+ const plainSlack = Math.max(0, effectiveWidth - (line.bbox.width - trailing));
198
+ const plainX = line.bbox.x + (block.textAlign === 'right' ? plainSlack : block.textAlign === 'center' ? plainSlack / 2 : 0);
199
+ // Each word where the layout measured it (EF-137): the embedded face's
200
+ // own widths could differ, most of all for a character it has no glyph
201
+ // for, and would carry the rest of the line along. A line with
202
+ // right-to-left letters stays one run, which the shaper turns around.
203
+ // The hyphen repeated from the line before is painted but not read.
204
+ const actualText = line.repeatedHyphen && line.text.startsWith('-') ? line.text.slice(1) : undefined;
205
+ if (segments && segments.length > 0 && !hasRightToLeft(line.text)
206
+ && drawMeasuredTextPx(ctx, withLineEndSpace(segments, line.text), plainX, line.baseline, blockFont, blockSize, blockColor, tracking, actualText))
207
+ return;
208
+ drawTextPx(ctx, line.text, plainX, line.baseline, blockFont, blockSize, blockColor, undefined, actualText);
209
+ }
210
+ /**
211
+ * The index of the segment that opens with the hyphen repeated from the line
212
+ * before (`VDTLine.repeatedHyphen`, "vencer-" | "-se"), or -1. The PDF paints
213
+ * that segment with an `/ActualText` that leaves the hyphen out, so copying
214
+ * and text extraction read the word once, as written ("vencer-se").
215
+ */
216
+ function repeatedHyphenSegment(line, segments) {
217
+ if (!line.repeatedHyphen)
218
+ return -1;
219
+ const i = segments.findIndex((s) => s.kind !== 'space');
220
+ const seg = segments[i];
221
+ return seg && seg.kind === 'text' && !seg.chip && seg.text.startsWith('-') ? i : -1;
222
+ }
223
+ /** A ragged line's segments, plus the space that ends the line when its
224
+ * text has one and the segments leave it out. The space takes no room
225
+ * past the line, but it is painted, as it was when the whole text was one
226
+ * run, so extracted text keeps the words either side of the break apart. */
227
+ function withLineEndSpace(segments, text) {
228
+ let shown = '';
229
+ for (const seg of segments)
230
+ shown += seg.text;
231
+ if (text.length <= shown.length || !text.startsWith(shown))
232
+ return segments;
233
+ const rest = text.slice(shown.length);
234
+ return /^\s+$/.test(rest) ? [...segments, { text: rest, width: 0 }] : segments;
235
+ }
236
+ /** Whether `text` holds a right-to-left letter: Hebrew, Arabic, Syriac,
237
+ * Thaana, N'Ko and the scripts after them up to U+08FF, their
238
+ * presentation forms, and the right-to-left blocks of the supplementary
239
+ * planes. */
240
+ function hasRightToLeft(text) {
241
+ for (let i = 0; i < text.length; i++) {
242
+ const c = text.charCodeAt(i);
243
+ if (c < 0x0590)
244
+ continue;
245
+ if (c <= 0x08ff || (c >= 0xfb1d && c <= 0xfdff) || (c >= 0xfe70 && c <= 0xfefe))
246
+ return true;
247
+ if (c >= 0xd800 && c <= 0xdbff) {
248
+ const cp = text.codePointAt(i);
249
+ if ((cp >= 0x10800 && cp <= 0x10fff) || (cp >= 0x1e800 && cp <= 0x1efff))
250
+ return true;
251
+ i++;
252
+ }
253
+ }
254
+ return false;
160
255
  }
161
256
  function renderBullet(ctx, block, fontCache, elem) {
162
257
  if (!block.bulletText ||
@@ -176,8 +271,12 @@ function renderBullet(ctx, block, fontCache, elem) {
176
271
  // Canvas uses `textBaseline='middle'` at bulletY; pdf-lib draws from the
177
272
  // alphabetic baseline. Shift the baseline down by ~0.3em so the em-square
178
273
  // midline aligns at bulletY, matching canvas placement within hinting tolerance.
274
+ // A marker set as text (a contents number) has its baseline at
275
+ // `bulletBaselineY` (postext 1.5); `bulletY` stays its em-box midpoint.
276
+ const baselineY = block.bulletBaselineY;
277
+ const onBaseline = baselineY !== undefined;
179
278
  const midY = block.bulletY ?? firstLine.baseline;
180
- const baselinePx = midY + size * 0.3;
279
+ const baselinePx = onBaseline ? baselineY : midY + size * 0.3;
181
280
  tagContent(ctx, elem);
182
281
  drawTextPx(ctx, block.bulletText, block.bulletOffsetX, baselinePx, font, size, color);
183
282
  // Ordered-list separator styled apart from the number (own font/colour).
@@ -188,7 +287,7 @@ function renderBullet(ctx, block, fontCache, elem) {
188
287
  return;
189
288
  const sepSize = parseFontString(sepFontString)?.sizePx ?? size;
190
289
  const sepColor = colorFromHex(block.separatorColor ?? colorHex, ctx.colorSpace);
191
- drawTextPx(ctx, block.separatorText, block.separatorX, midY + sepSize * 0.3, sepFont, sepSize, sepColor);
290
+ drawTextPx(ctx, block.separatorText, block.separatorX, onBaseline ? baselineY : midY + sepSize * 0.3, sepFont, sepSize, sepColor);
192
291
  }
193
292
  }
194
293
  function renderStrikethrough(ctx, block) {