postext 1.27.1 → 1.28.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 (544) hide show
  1. package/dist/__tests__/bundle/balloonPlacementPin.test.d.ts +2 -0
  2. package/dist/__tests__/bundle/balloonPlacementPin.test.d.ts.map +1 -0
  3. package/dist/__tests__/bundle/balloonPlacementPin.test.js +71 -0
  4. package/dist/__tests__/bundle/balloonPlacementPin.test.js.map +1 -0
  5. package/dist/__tests__/bundle/cjkRulesPin.test.js +131 -7
  6. package/dist/__tests__/bundle/cjkRulesPin.test.js.map +1 -1
  7. package/dist/__tests__/bundle/designOverflowPin.test.js +3 -3
  8. package/dist/__tests__/bundle/designOverflowPin.test.js.map +1 -1
  9. package/dist/__tests__/bundle/flowColumnsPin.test.js +3 -1
  10. package/dist/__tests__/bundle/flowColumnsPin.test.js.map +1 -1
  11. package/dist/__tests__/bundle/gridBalancingPin.test.js +14 -5
  12. package/dist/__tests__/bundle/gridBalancingPin.test.js.map +1 -1
  13. package/dist/__tests__/bundle/gridBreakRulesPin.test.d.ts +2 -0
  14. package/dist/__tests__/bundle/gridBreakRulesPin.test.d.ts.map +1 -0
  15. package/dist/__tests__/bundle/gridBreakRulesPin.test.js +144 -0
  16. package/dist/__tests__/bundle/gridBreakRulesPin.test.js.map +1 -0
  17. package/dist/__tests__/bundle/indexGroupSplitPin.test.d.ts +2 -0
  18. package/dist/__tests__/bundle/indexGroupSplitPin.test.d.ts.map +1 -0
  19. package/dist/__tests__/bundle/indexGroupSplitPin.test.js +55 -0
  20. package/dist/__tests__/bundle/indexGroupSplitPin.test.js.map +1 -0
  21. package/dist/__tests__/bundle/inlineCaptionSidePin.test.d.ts +2 -0
  22. package/dist/__tests__/bundle/inlineCaptionSidePin.test.d.ts.map +1 -0
  23. package/dist/__tests__/bundle/inlineCaptionSidePin.test.js +60 -0
  24. package/dist/__tests__/bundle/inlineCaptionSidePin.test.js.map +1 -0
  25. package/dist/__tests__/bundle/inlineTableSplitPin.test.js +3 -1
  26. package/dist/__tests__/bundle/inlineTableSplitPin.test.js.map +1 -1
  27. package/dist/__tests__/bundle/looseOrderPin.test.d.ts +2 -0
  28. package/dist/__tests__/bundle/looseOrderPin.test.d.ts.map +1 -0
  29. package/dist/__tests__/bundle/looseOrderPin.test.js +76 -0
  30. package/dist/__tests__/bundle/looseOrderPin.test.js.map +1 -0
  31. package/dist/__tests__/bundle/openerHeadFloatsPin.test.js +2 -1
  32. package/dist/__tests__/bundle/openerHeadFloatsPin.test.js.map +1 -1
  33. package/dist/__tests__/bundle/refLabelBreaksPin.test.d.ts +2 -0
  34. package/dist/__tests__/bundle/refLabelBreaksPin.test.d.ts.map +1 -0
  35. package/dist/__tests__/bundle/refLabelBreaksPin.test.js +72 -0
  36. package/dist/__tests__/bundle/refLabelBreaksPin.test.js.map +1 -0
  37. package/dist/__tests__/bundle/scriptContextPin.test.d.ts +2 -0
  38. package/dist/__tests__/bundle/scriptContextPin.test.d.ts.map +1 -0
  39. package/dist/__tests__/bundle/scriptContextPin.test.js +66 -0
  40. package/dist/__tests__/bundle/scriptContextPin.test.js.map +1 -0
  41. package/dist/__tests__/bundle/trailingStepPin.test.d.ts +2 -0
  42. package/dist/__tests__/bundle/trailingStepPin.test.d.ts.map +1 -0
  43. package/dist/__tests__/bundle/trailingStepPin.test.js +59 -0
  44. package/dist/__tests__/bundle/trailingStepPin.test.js.map +1 -0
  45. package/dist/__tests__/bundle/wideFloatStretchPin.test.d.ts +2 -0
  46. package/dist/__tests__/bundle/wideFloatStretchPin.test.d.ts.map +1 -0
  47. package/dist/__tests__/bundle/wideFloatStretchPin.test.js +59 -0
  48. package/dist/__tests__/bundle/wideFloatStretchPin.test.js.map +1 -0
  49. package/dist/__tests__/bundle.test.js +8 -6
  50. package/dist/__tests__/bundle.test.js.map +1 -1
  51. package/dist/__tests__/cjk/annotations.test.js +223 -0
  52. package/dist/__tests__/cjk/annotations.test.js.map +1 -1
  53. package/dist/__tests__/cjk/annotationsRender.test.js +3 -3
  54. package/dist/__tests__/cjk/annotationsRender.test.js.map +1 -1
  55. package/dist/__tests__/cjk/chipLatinSpacing.test.js +13 -2
  56. package/dist/__tests__/cjk/chipLatinSpacing.test.js.map +1 -1
  57. package/dist/__tests__/cjk/designNumberSeams.test.d.ts +2 -0
  58. package/dist/__tests__/cjk/designNumberSeams.test.d.ts.map +1 -0
  59. package/dist/__tests__/cjk/designNumberSeams.test.js +221 -0
  60. package/dist/__tests__/cjk/designNumberSeams.test.js.map +1 -0
  61. package/dist/__tests__/cjk/grid.test.js +1 -1
  62. package/dist/__tests__/cjk/grid.test.js.map +1 -1
  63. package/dist/__tests__/cjk/gridBalancing.test.js +3 -1
  64. package/dist/__tests__/cjk/gridBalancing.test.js.map +1 -1
  65. package/dist/__tests__/cjk/japaneseSpacing.test.js +3 -1
  66. package/dist/__tests__/cjk/japaneseSpacing.test.js.map +1 -1
  67. package/dist/__tests__/cjk/keepAll.test.js +3 -1
  68. package/dist/__tests__/cjk/keepAll.test.js.map +1 -1
  69. package/dist/__tests__/cjk/keepAllLatinQuotation.test.d.ts +2 -0
  70. package/dist/__tests__/cjk/keepAllLatinQuotation.test.d.ts.map +1 -0
  71. package/dist/__tests__/cjk/keepAllLatinQuotation.test.js +166 -0
  72. package/dist/__tests__/cjk/keepAllLatinQuotation.test.js.map +1 -0
  73. package/dist/__tests__/cjk/latinSpacingEdge.test.d.ts +2 -0
  74. package/dist/__tests__/cjk/latinSpacingEdge.test.d.ts.map +1 -0
  75. package/dist/__tests__/cjk/latinSpacingEdge.test.js +179 -0
  76. package/dist/__tests__/cjk/latinSpacingEdge.test.js.map +1 -0
  77. package/dist/__tests__/cjk/runt.test.js +92 -1
  78. package/dist/__tests__/cjk/runt.test.js.map +1 -1
  79. package/dist/__tests__/codeBlocks.test.js +1 -1
  80. package/dist/__tests__/columnBalancing.test.js +216 -0
  81. package/dist/__tests__/columnBalancing.test.js.map +1 -1
  82. package/dist/__tests__/columnRuleBands.test.js +78 -0
  83. package/dist/__tests__/columnRuleBands.test.js.map +1 -1
  84. package/dist/__tests__/comics/readingDirection.test.js +52 -0
  85. package/dist/__tests__/comics/readingDirection.test.js.map +1 -1
  86. package/dist/__tests__/comics/script.test.js +5 -0
  87. package/dist/__tests__/comics/script.test.js.map +1 -1
  88. package/dist/__tests__/contrast.test.d.ts +2 -0
  89. package/dist/__tests__/contrast.test.d.ts.map +1 -0
  90. package/dist/__tests__/contrast.test.js +258 -0
  91. package/dist/__tests__/contrast.test.js.map +1 -0
  92. package/dist/__tests__/defaults/cjk.test.js +4 -4
  93. package/dist/__tests__/defaults/cjk.test.js.map +1 -1
  94. package/dist/__tests__/defaults/gridBreakRules.test.d.ts +2 -0
  95. package/dist/__tests__/defaults/gridBreakRules.test.d.ts.map +1 -0
  96. package/dist/__tests__/defaults/gridBreakRules.test.js +152 -0
  97. package/dist/__tests__/defaults/gridBreakRules.test.js.map +1 -0
  98. package/dist/__tests__/defaults/headingsBalancing.test.js +25 -0
  99. package/dist/__tests__/defaults/headingsBalancing.test.js.map +1 -1
  100. package/dist/__tests__/defaults/stripContextDefaults.test.js +41 -0
  101. package/dist/__tests__/defaults/stripContextDefaults.test.js.map +1 -1
  102. package/dist/__tests__/defaults/stripRoundTrip.test.js +8 -5
  103. package/dist/__tests__/defaults/stripRoundTrip.test.js.map +1 -1
  104. package/dist/__tests__/exports.test.js +30 -0
  105. package/dist/__tests__/exports.test.js.map +1 -1
  106. package/dist/__tests__/fontUsage.test.d.ts +2 -0
  107. package/dist/__tests__/fontUsage.test.d.ts.map +1 -0
  108. package/dist/__tests__/fontUsage.test.js +113 -0
  109. package/dist/__tests__/fontUsage.test.js.map +1 -0
  110. package/dist/__tests__/hardBreaks.test.js +1 -1
  111. package/dist/__tests__/headingInlineMarks.test.js +7 -5
  112. package/dist/__tests__/headingInlineMarks.test.js.map +1 -1
  113. package/dist/__tests__/hyphenationRules.test.d.ts +2 -0
  114. package/dist/__tests__/hyphenationRules.test.d.ts.map +1 -0
  115. package/dist/__tests__/hyphenationRules.test.js +295 -0
  116. package/dist/__tests__/hyphenationRules.test.js.map +1 -0
  117. package/dist/__tests__/indexGroupSplit.test.d.ts +2 -0
  118. package/dist/__tests__/indexGroupSplit.test.d.ts.map +1 -0
  119. package/dist/__tests__/indexGroupSplit.test.js +175 -0
  120. package/dist/__tests__/indexGroupSplit.test.js.map +1 -0
  121. package/dist/__tests__/mathSizeMigration.test.js +7 -5
  122. package/dist/__tests__/mathSizeMigration.test.js.map +1 -1
  123. package/dist/__tests__/multipleColumns.test.js +19 -0
  124. package/dist/__tests__/multipleColumns.test.js.map +1 -1
  125. package/dist/__tests__/pipeline/calloutInlineResourceGap.test.js +1 -1
  126. package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.js +3 -3
  127. package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.js.map +1 -1
  128. package/dist/__tests__/pipeline/closingBandUnderOpener.test.d.ts +2 -0
  129. package/dist/__tests__/pipeline/closingBandUnderOpener.test.d.ts.map +1 -0
  130. package/dist/__tests__/pipeline/closingBandUnderOpener.test.js +90 -0
  131. package/dist/__tests__/pipeline/closingBandUnderOpener.test.js.map +1 -0
  132. package/dist/__tests__/pipeline/colonListRoom.test.js +5 -4
  133. package/dist/__tests__/pipeline/colonListRoom.test.js.map +1 -1
  134. package/dist/__tests__/pipeline/columnHeadSpace.test.d.ts +2 -0
  135. package/dist/__tests__/pipeline/columnHeadSpace.test.d.ts.map +1 -0
  136. package/dist/__tests__/pipeline/columnHeadSpace.test.js +175 -0
  137. package/dist/__tests__/pipeline/columnHeadSpace.test.js.map +1 -0
  138. package/dist/__tests__/pipeline/compoundBreaks.test.js +6 -6
  139. package/dist/__tests__/pipeline/compoundBreaks.test.js.map +1 -1
  140. package/dist/__tests__/pipeline/dashBreaks.test.js +5 -5
  141. package/dist/__tests__/pipeline/dashBreaks.test.js.map +1 -1
  142. package/dist/__tests__/pipeline/flowColumns.test.js +100 -0
  143. package/dist/__tests__/pipeline/flowColumns.test.js.map +1 -1
  144. package/dist/__tests__/pipeline/headingShortBand.test.js +2 -1
  145. package/dist/__tests__/pipeline/headingShortBand.test.js.map +1 -1
  146. package/dist/__tests__/pipeline/headingSplitOrphans.test.js +6 -5
  147. package/dist/__tests__/pipeline/headingSplitOrphans.test.js.map +1 -1
  148. package/dist/__tests__/pipeline/hyphenAcrossColumns.test.js +188 -1
  149. package/dist/__tests__/pipeline/hyphenAcrossColumns.test.js.map +1 -1
  150. package/dist/__tests__/pipeline/inlineCaptionSide.test.d.ts +2 -0
  151. package/dist/__tests__/pipeline/inlineCaptionSide.test.d.ts.map +1 -0
  152. package/dist/__tests__/pipeline/inlineCaptionSide.test.js +270 -0
  153. package/dist/__tests__/pipeline/inlineCaptionSide.test.js.map +1 -0
  154. package/dist/__tests__/pipeline/inlineFigureSpace.test.js +5 -5
  155. package/dist/__tests__/pipeline/inlineFigureSpace.test.js.map +1 -1
  156. package/dist/__tests__/pipeline/inlineRefRender.test.js +8 -6
  157. package/dist/__tests__/pipeline/inlineRefRender.test.js.map +1 -1
  158. package/dist/__tests__/pipeline/looseBeforeHeadingLines.test.d.ts +2 -0
  159. package/dist/__tests__/pipeline/looseBeforeHeadingLines.test.d.ts.map +1 -0
  160. package/dist/__tests__/pipeline/looseBeforeHeadingLines.test.js +73 -0
  161. package/dist/__tests__/pipeline/looseBeforeHeadingLines.test.js.map +1 -0
  162. package/dist/__tests__/pipeline/openerFloats.test.d.ts +2 -0
  163. package/dist/__tests__/pipeline/openerFloats.test.d.ts.map +1 -0
  164. package/dist/__tests__/pipeline/openerFloats.test.js +137 -0
  165. package/dist/__tests__/pipeline/openerFloats.test.js.map +1 -0
  166. package/dist/__tests__/pipeline/orderedNumberWidthItem.test.d.ts +2 -0
  167. package/dist/__tests__/pipeline/orderedNumberWidthItem.test.d.ts.map +1 -0
  168. package/dist/__tests__/pipeline/orderedNumberWidthItem.test.js +162 -0
  169. package/dist/__tests__/pipeline/orderedNumberWidthItem.test.js.map +1 -0
  170. package/dist/__tests__/pipeline/paragraphContainerTail.test.js +68 -8
  171. package/dist/__tests__/pipeline/paragraphContainerTail.test.js.map +1 -1
  172. package/dist/__tests__/pipeline/paragraphStyleFaces.test.js +1 -1
  173. package/dist/__tests__/pipeline/paragraphStyleFaces.test.js.map +1 -1
  174. package/dist/__tests__/pipeline/raggedLineAndRuntFix.test.d.ts +2 -0
  175. package/dist/__tests__/pipeline/raggedLineAndRuntFix.test.d.ts.map +1 -0
  176. package/dist/__tests__/pipeline/raggedLineAndRuntFix.test.js +151 -0
  177. package/dist/__tests__/pipeline/raggedLineAndRuntFix.test.js.map +1 -0
  178. package/dist/__tests__/pipeline/raggedOptimal.test.js +6 -6
  179. package/dist/__tests__/pipeline/raggedOptimal.test.js.map +1 -1
  180. package/dist/__tests__/pipeline/refLabelBreaks.test.d.ts +2 -0
  181. package/dist/__tests__/pipeline/refLabelBreaks.test.d.ts.map +1 -0
  182. package/dist/__tests__/pipeline/refLabelBreaks.test.js +324 -0
  183. package/dist/__tests__/pipeline/refLabelBreaks.test.js.map +1 -0
  184. package/dist/__tests__/pipeline/resourceTemplateStyles.test.d.ts +2 -0
  185. package/dist/__tests__/pipeline/resourceTemplateStyles.test.d.ts.map +1 -0
  186. package/dist/__tests__/pipeline/resourceTemplateStyles.test.js +145 -0
  187. package/dist/__tests__/pipeline/resourceTemplateStyles.test.js.map +1 -0
  188. package/dist/__tests__/pipeline/shortListSplit.test.d.ts +2 -0
  189. package/dist/__tests__/pipeline/shortListSplit.test.d.ts.map +1 -0
  190. package/dist/__tests__/pipeline/shortListSplit.test.js +181 -0
  191. package/dist/__tests__/pipeline/shortListSplit.test.js.map +1 -0
  192. package/dist/__tests__/pipeline/snapTailAtColumnFoot.test.d.ts +2 -0
  193. package/dist/__tests__/pipeline/snapTailAtColumnFoot.test.d.ts.map +1 -0
  194. package/dist/__tests__/pipeline/snapTailAtColumnFoot.test.js +133 -0
  195. package/dist/__tests__/pipeline/snapTailAtColumnFoot.test.js.map +1 -0
  196. package/dist/__tests__/pipeline/stretchAfterDisplays.test.d.ts +2 -0
  197. package/dist/__tests__/pipeline/stretchAfterDisplays.test.d.ts.map +1 -0
  198. package/dist/__tests__/pipeline/stretchAfterDisplays.test.js +51 -0
  199. package/dist/__tests__/pipeline/stretchAfterDisplays.test.js.map +1 -0
  200. package/dist/__tests__/pipeline/trailingCapFloatHead.test.js +26 -0
  201. package/dist/__tests__/pipeline/trailingCapFloatHead.test.js.map +1 -1
  202. package/dist/__tests__/pipeline/trailingStep.test.d.ts +2 -0
  203. package/dist/__tests__/pipeline/trailingStep.test.d.ts.map +1 -0
  204. package/dist/__tests__/pipeline/trailingStep.test.js +187 -0
  205. package/dist/__tests__/pipeline/trailingStep.test.js.map +1 -0
  206. package/dist/__tests__/pipeline/wideFloatStretch.test.d.ts +2 -0
  207. package/dist/__tests__/pipeline/wideFloatStretch.test.d.ts.map +1 -0
  208. package/dist/__tests__/pipeline/wideFloatStretch.test.js +84 -0
  209. package/dist/__tests__/pipeline/wideFloatStretch.test.js.map +1 -0
  210. package/dist/__tests__/scriptContext.test.d.ts +2 -0
  211. package/dist/__tests__/scriptContext.test.d.ts.map +1 -0
  212. package/dist/__tests__/scriptContext.test.js +919 -0
  213. package/dist/__tests__/scriptContext.test.js.map +1 -0
  214. package/dist/__tests__/softHyphenEdges.test.d.ts +2 -0
  215. package/dist/__tests__/softHyphenEdges.test.d.ts.map +1 -0
  216. package/dist/__tests__/softHyphenEdges.test.js +217 -0
  217. package/dist/__tests__/softHyphenEdges.test.js.map +1 -0
  218. package/dist/__tests__/spaceLimitRatio.test.d.ts +2 -0
  219. package/dist/__tests__/spaceLimitRatio.test.d.ts.map +1 -0
  220. package/dist/__tests__/spaceLimitRatio.test.js +226 -0
  221. package/dist/__tests__/spaceLimitRatio.test.js.map +1 -0
  222. package/dist/__tests__/trackedLigatures.test.js +365 -24
  223. package/dist/__tests__/trackedLigatures.test.js.map +1 -1
  224. package/dist/__tests__/verseLines.test.js +9 -7
  225. package/dist/__tests__/verseLines.test.js.map +1 -1
  226. package/dist/bundle/configVersion.d.ts +201 -6
  227. package/dist/bundle/configVersion.d.ts.map +1 -1
  228. package/dist/bundle/configVersion.js +440 -6
  229. package/dist/bundle/configVersion.js.map +1 -1
  230. package/dist/bundle/index.d.ts +8 -0
  231. package/dist/bundle/index.d.ts.map +1 -1
  232. package/dist/bundle/index.js +8 -0
  233. package/dist/bundle/index.js.map +1 -1
  234. package/dist/canvas-backend/blockRender.d.ts.map +1 -1
  235. package/dist/canvas-backend/blockRender.js +3 -2
  236. package/dist/canvas-backend/blockRender.js.map +1 -1
  237. package/dist/canvas-backend/chip.js +1 -1
  238. package/dist/canvas-backend/chip.js.map +1 -1
  239. package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
  240. package/dist/canvas-backend/headerFooter.js +17 -2
  241. package/dist/canvas-backend/headerFooter.js.map +1 -1
  242. package/dist/canvas-backend/runDirection.d.ts +10 -6
  243. package/dist/canvas-backend/runDirection.d.ts.map +1 -1
  244. package/dist/canvas-backend/runDirection.js +12 -7
  245. package/dist/canvas-backend/runDirection.js.map +1 -1
  246. package/dist/canvas-backend/scriptText.d.ts +11 -0
  247. package/dist/canvas-backend/scriptText.d.ts.map +1 -0
  248. package/dist/canvas-backend/scriptText.js +75 -0
  249. package/dist/canvas-backend/scriptText.js.map +1 -0
  250. package/dist/canvas-backend/segmentText.d.ts.map +1 -1
  251. package/dist/canvas-backend/segmentText.js +9 -1
  252. package/dist/canvas-backend/segmentText.js.map +1 -1
  253. package/dist/canvas-backend/trackedText.d.ts +35 -20
  254. package/dist/canvas-backend/trackedText.d.ts.map +1 -1
  255. package/dist/canvas-backend/trackedText.js +58 -22
  256. package/dist/canvas-backend/trackedText.js.map +1 -1
  257. package/dist/canvas-backend/verticalText.d.ts.map +1 -1
  258. package/dist/canvas-backend/verticalText.js +10 -2
  259. package/dist/canvas-backend/verticalText.js.map +1 -1
  260. package/dist/canvas-backend/wordRuns.d.ts +14 -5
  261. package/dist/canvas-backend/wordRuns.d.ts.map +1 -1
  262. package/dist/canvas-backend/wordRuns.js +20 -7
  263. package/dist/canvas-backend/wordRuns.js.map +1 -1
  264. package/dist/citations/names.d.ts +8 -0
  265. package/dist/citations/names.d.ts.map +1 -0
  266. package/dist/citations/names.js +25 -0
  267. package/dist/citations/names.js.map +1 -0
  268. package/dist/columnClip.d.ts +8 -1
  269. package/dist/columnClip.d.ts.map +1 -1
  270. package/dist/columnClip.js +32 -3
  271. package/dist/columnClip.js.map +1 -1
  272. package/dist/columnRule.d.ts +6 -3
  273. package/dist/columnRule.d.ts.map +1 -1
  274. package/dist/columnRule.js +6 -3
  275. package/dist/columnRule.js.map +1 -1
  276. package/dist/comics/layoutPage.d.ts.map +1 -1
  277. package/dist/comics/layoutPage.js +51 -22
  278. package/dist/comics/layoutPage.js.map +1 -1
  279. package/dist/comics/lettering/__tests__/bystanderFaces.test.d.ts +2 -0
  280. package/dist/comics/lettering/__tests__/bystanderFaces.test.d.ts.map +1 -0
  281. package/dist/comics/lettering/__tests__/bystanderFaces.test.js +204 -0
  282. package/dist/comics/lettering/__tests__/bystanderFaces.test.js.map +1 -0
  283. package/dist/comics/lettering/__tests__/shapeTextDash.test.d.ts +2 -0
  284. package/dist/comics/lettering/__tests__/shapeTextDash.test.d.ts.map +1 -0
  285. package/dist/comics/lettering/__tests__/shapeTextDash.test.js +173 -0
  286. package/dist/comics/lettering/__tests__/shapeTextDash.test.js.map +1 -0
  287. package/dist/comics/lettering/__tests__/strictPlacement.test.d.ts +2 -0
  288. package/dist/comics/lettering/__tests__/strictPlacement.test.d.ts.map +1 -0
  289. package/dist/comics/lettering/__tests__/strictPlacement.test.js +130 -0
  290. package/dist/comics/lettering/__tests__/strictPlacement.test.js.map +1 -0
  291. package/dist/comics/lettering/letter.js +21 -8
  292. package/dist/comics/lettering/letter.js.map +1 -1
  293. package/dist/comics/lettering/placement.d.ts.map +1 -1
  294. package/dist/comics/lettering/placement.js +12 -3
  295. package/dist/comics/lettering/placement.js.map +1 -1
  296. package/dist/comics/lettering/shape-text.d.ts +3 -0
  297. package/dist/comics/lettering/shape-text.d.ts.map +1 -1
  298. package/dist/comics/lettering/shape-text.js +71 -12
  299. package/dist/comics/lettering/shape-text.js.map +1 -1
  300. package/dist/comics/lettering/text.d.ts +5 -0
  301. package/dist/comics/lettering/text.d.ts.map +1 -1
  302. package/dist/comics/lettering/text.js +6 -1
  303. package/dist/comics/lettering/text.js.map +1 -1
  304. package/dist/comics/lettering/types.d.ts +12 -2
  305. package/dist/comics/lettering/types.d.ts.map +1 -1
  306. package/dist/comics/script.js +1 -1
  307. package/dist/comics/script.js.map +1 -1
  308. package/dist/comics/types.d.ts +7 -3
  309. package/dist/comics/types.d.ts.map +1 -1
  310. package/dist/configWarnings.d.ts.map +1 -1
  311. package/dist/configWarnings.js +33 -6
  312. package/dist/configWarnings.js.map +1 -1
  313. package/dist/contrast.d.ts +188 -0
  314. package/dist/contrast.d.ts.map +1 -0
  315. package/dist/contrast.js +583 -0
  316. package/dist/contrast.js.map +1 -0
  317. package/dist/defaults/bodyText.d.ts +31 -3
  318. package/dist/defaults/bodyText.d.ts.map +1 -1
  319. package/dist/defaults/bodyText.js +76 -8
  320. package/dist/defaults/bodyText.js.map +1 -1
  321. package/dist/defaults/citations.d.ts.map +1 -1
  322. package/dist/defaults/citations.js +4 -0
  323. package/dist/defaults/citations.js.map +1 -1
  324. package/dist/defaults/cjk.d.ts +11 -1
  325. package/dist/defaults/cjk.d.ts.map +1 -1
  326. package/dist/defaults/cjk.js +41 -3
  327. package/dist/defaults/cjk.js.map +1 -1
  328. package/dist/defaults/comics.d.ts.map +1 -1
  329. package/dist/defaults/comics.js +2 -0
  330. package/dist/defaults/comics.js.map +1 -1
  331. package/dist/defaults/contrast.d.ts +11 -0
  332. package/dist/defaults/contrast.d.ts.map +1 -0
  333. package/dist/defaults/contrast.js +65 -0
  334. package/dist/defaults/contrast.js.map +1 -0
  335. package/dist/defaults/crossRefs.d.ts +1 -1
  336. package/dist/defaults/crossRefs.d.ts.map +1 -1
  337. package/dist/defaults/crossRefs.js +6 -1
  338. package/dist/defaults/crossRefs.js.map +1 -1
  339. package/dist/defaults/footnotes.d.ts.map +1 -1
  340. package/dist/defaults/footnotes.js +5 -0
  341. package/dist/defaults/footnotes.js.map +1 -1
  342. package/dist/defaults/headings.d.ts +5 -1
  343. package/dist/defaults/headings.d.ts.map +1 -1
  344. package/dist/defaults/headings.js +41 -1
  345. package/dist/defaults/headings.js.map +1 -1
  346. package/dist/defaults/index.d.ts +3 -2
  347. package/dist/defaults/index.d.ts.map +1 -1
  348. package/dist/defaults/index.js +15 -4
  349. package/dist/defaults/index.js.map +1 -1
  350. package/dist/defaults/indexConfig.d.ts +1 -0
  351. package/dist/defaults/indexConfig.d.ts.map +1 -1
  352. package/dist/defaults/indexConfig.js +7 -1
  353. package/dist/defaults/indexConfig.js.map +1 -1
  354. package/dist/defaults/layout.d.ts.map +1 -1
  355. package/dist/defaults/layout.js +13 -1
  356. package/dist/defaults/layout.js.map +1 -1
  357. package/dist/defaults/orderedLists.js +1 -1
  358. package/dist/defaults/orderedLists.js.map +1 -1
  359. package/dist/defaults/paragraphStyles.d.ts.map +1 -1
  360. package/dist/defaults/paragraphStyles.js +5 -0
  361. package/dist/defaults/paragraphStyles.js.map +1 -1
  362. package/dist/defaults/shared.d.ts +4 -1
  363. package/dist/defaults/shared.d.ts.map +1 -1
  364. package/dist/defaults/shared.js +5 -0
  365. package/dist/defaults/shared.js.map +1 -1
  366. package/dist/design/cjkText.d.ts +7 -2
  367. package/dist/design/cjkText.d.ts.map +1 -1
  368. package/dist/design/cjkText.js +8 -2
  369. package/dist/design/cjkText.js.map +1 -1
  370. package/dist/design/layout.d.ts.map +1 -1
  371. package/dist/design/layout.js +85 -12
  372. package/dist/design/layout.js.map +1 -1
  373. package/dist/design/richText.d.ts.map +1 -1
  374. package/dist/design/richText.js +7 -3
  375. package/dist/design/richText.js.map +1 -1
  376. package/dist/fonts/usage.d.ts.map +1 -1
  377. package/dist/fonts/usage.js +89 -0
  378. package/dist/fonts/usage.js.map +1 -1
  379. package/dist/html-backend.d.ts.map +1 -1
  380. package/dist/html-backend.js +97 -27
  381. package/dist/html-backend.js.map +1 -1
  382. package/dist/hyphenate.d.ts +58 -1
  383. package/dist/hyphenate.d.ts.map +1 -1
  384. package/dist/hyphenate.js +228 -19
  385. package/dist/hyphenate.js.map +1 -1
  386. package/dist/hyphenationExceptions.d.ts +10 -0
  387. package/dist/hyphenationExceptions.d.ts.map +1 -0
  388. package/dist/hyphenationExceptions.js +29 -0
  389. package/dist/hyphenationExceptions.js.map +1 -0
  390. package/dist/index.d.ts +12 -4
  391. package/dist/index.d.ts.map +1 -1
  392. package/dist/index.js +10 -3
  393. package/dist/index.js.map +1 -1
  394. package/dist/knuthPlass/pretextAdapter.d.ts.map +1 -1
  395. package/dist/knuthPlass/pretextAdapter.js +4 -17
  396. package/dist/knuthPlass/pretextAdapter.js.map +1 -1
  397. package/dist/knuthPlass/richAdapter.d.ts +9 -0
  398. package/dist/knuthPlass/richAdapter.d.ts.map +1 -1
  399. package/dist/knuthPlass/richAdapter.js +15 -18
  400. package/dist/knuthPlass/richAdapter.js.map +1 -1
  401. package/dist/looseLines.d.ts +15 -4
  402. package/dist/looseLines.d.ts.map +1 -1
  403. package/dist/looseLines.js +17 -4
  404. package/dist/looseLines.js.map +1 -1
  405. package/dist/measure/cache.d.ts.map +1 -1
  406. package/dist/measure/cache.js +14 -4
  407. package/dist/measure/cache.js.map +1 -1
  408. package/dist/measure/canvas.d.ts +18 -0
  409. package/dist/measure/canvas.d.ts.map +1 -1
  410. package/dist/measure/canvas.js +104 -0
  411. package/dist/measure/canvas.js.map +1 -1
  412. package/dist/measure/cjkAnnotate.d.ts +11 -6
  413. package/dist/measure/cjkAnnotate.d.ts.map +1 -1
  414. package/dist/measure/cjkAnnotate.js +27 -11
  415. package/dist/measure/cjkAnnotate.js.map +1 -1
  416. package/dist/measure/cjkCompose.d.ts +6 -2
  417. package/dist/measure/cjkCompose.d.ts.map +1 -1
  418. package/dist/measure/cjkCompose.js +146 -30
  419. package/dist/measure/cjkCompose.js.map +1 -1
  420. package/dist/measure/cjkPunctuation.d.ts +17 -0
  421. package/dist/measure/cjkPunctuation.d.ts.map +1 -1
  422. package/dist/measure/cjkPunctuation.js +15 -1
  423. package/dist/measure/cjkPunctuation.js.map +1 -1
  424. package/dist/measure/font.d.ts +2 -1
  425. package/dist/measure/font.d.ts.map +1 -1
  426. package/dist/measure/font.js +4 -2
  427. package/dist/measure/font.js.map +1 -1
  428. package/dist/measure/hardBreaks.d.ts.map +1 -1
  429. package/dist/measure/hardBreaks.js +6 -2
  430. package/dist/measure/hardBreaks.js.map +1 -1
  431. package/dist/measure/kashida.d.ts.map +1 -1
  432. package/dist/measure/kashida.js +8 -11
  433. package/dist/measure/kashida.js.map +1 -1
  434. package/dist/measure/plain.d.ts +3 -0
  435. package/dist/measure/plain.d.ts.map +1 -1
  436. package/dist/measure/plain.js +70 -5
  437. package/dist/measure/plain.js.map +1 -1
  438. package/dist/measure/rich.d.ts +32 -0
  439. package/dist/measure/rich.d.ts.map +1 -1
  440. package/dist/measure/rich.js +227 -35
  441. package/dist/measure/rich.js.map +1 -1
  442. package/dist/measure/script.d.ts +180 -0
  443. package/dist/measure/script.d.ts.map +1 -0
  444. package/dist/measure/script.js +329 -0
  445. package/dist/measure/script.js.map +1 -0
  446. package/dist/measure/spaceRatios.d.ts +28 -0
  447. package/dist/measure/spaceRatios.d.ts.map +1 -0
  448. package/dist/measure/spaceRatios.js +48 -0
  449. package/dist/measure/spaceRatios.js.map +1 -0
  450. package/dist/measure/spaces.d.ts +10 -0
  451. package/dist/measure/spaces.d.ts.map +1 -1
  452. package/dist/measure/spaces.js +36 -0
  453. package/dist/measure/spaces.js.map +1 -1
  454. package/dist/measure/types.d.ts +9 -0
  455. package/dist/measure/types.d.ts.map +1 -1
  456. package/dist/measure/types.js.map +1 -1
  457. package/dist/numbering.d.ts +5 -0
  458. package/dist/numbering.d.ts.map +1 -1
  459. package/dist/numbering.js +5 -1
  460. package/dist/numbering.js.map +1 -1
  461. package/dist/parse/types.d.ts +13 -0
  462. package/dist/parse/types.d.ts.map +1 -1
  463. package/dist/pipeline/bandCaps.d.ts +35 -1
  464. package/dist/pipeline/bandCaps.d.ts.map +1 -1
  465. package/dist/pipeline/bandCaps.js +95 -3
  466. package/dist/pipeline/bandCaps.js.map +1 -1
  467. package/dist/pipeline/build.d.ts.map +1 -1
  468. package/dist/pipeline/build.js +754 -49
  469. package/dist/pipeline/build.js.map +1 -1
  470. package/dist/pipeline/buildHelpers.d.ts.map +1 -1
  471. package/dist/pipeline/buildHelpers.js +5 -1
  472. package/dist/pipeline/buildHelpers.js.map +1 -1
  473. package/dist/pipeline/buildMeasurement.d.ts +9 -0
  474. package/dist/pipeline/buildMeasurement.d.ts.map +1 -1
  475. package/dist/pipeline/buildMeasurement.js +3 -2
  476. package/dist/pipeline/buildMeasurement.js.map +1 -1
  477. package/dist/pipeline/calloutLayout.d.ts +10 -1
  478. package/dist/pipeline/calloutLayout.d.ts.map +1 -1
  479. package/dist/pipeline/calloutLayout.js +45 -9
  480. package/dist/pipeline/calloutLayout.js.map +1 -1
  481. package/dist/pipeline/columnBalancing.d.ts +44 -7
  482. package/dist/pipeline/columnBalancing.d.ts.map +1 -1
  483. package/dist/pipeline/columnBalancing.js +167 -40
  484. package/dist/pipeline/columnBalancing.js.map +1 -1
  485. package/dist/pipeline/config.d.ts +2 -2
  486. package/dist/pipeline/config.d.ts.map +1 -1
  487. package/dist/pipeline/config.js +18 -3
  488. package/dist/pipeline/config.js.map +1 -1
  489. package/dist/pipeline/contentWarnings.d.ts +6 -0
  490. package/dist/pipeline/contentWarnings.d.ts.map +1 -1
  491. package/dist/pipeline/contentWarnings.js +32 -0
  492. package/dist/pipeline/contentWarnings.js.map +1 -1
  493. package/dist/pipeline/crossRefs.d.ts +12 -1
  494. package/dist/pipeline/crossRefs.d.ts.map +1 -1
  495. package/dist/pipeline/crossRefs.js +22 -14
  496. package/dist/pipeline/crossRefs.js.map +1 -1
  497. package/dist/pipeline/flowColumns.d.ts +2 -1
  498. package/dist/pipeline/flowColumns.d.ts.map +1 -1
  499. package/dist/pipeline/flowColumns.js +12 -2
  500. package/dist/pipeline/flowColumns.js.map +1 -1
  501. package/dist/pipeline/footnotes.d.ts.map +1 -1
  502. package/dist/pipeline/footnotes.js +3 -0
  503. package/dist/pipeline/footnotes.js.map +1 -1
  504. package/dist/pipeline/indexDirective.d.ts.map +1 -1
  505. package/dist/pipeline/indexDirective.js +15 -0
  506. package/dist/pipeline/indexDirective.js.map +1 -1
  507. package/dist/pipeline/lists.d.ts +1 -1
  508. package/dist/pipeline/lists.d.ts.map +1 -1
  509. package/dist/pipeline/lists.js +9 -1
  510. package/dist/pipeline/lists.js.map +1 -1
  511. package/dist/pipeline/measureContentBlock.d.ts +18 -0
  512. package/dist/pipeline/measureContentBlock.d.ts.map +1 -1
  513. package/dist/pipeline/measureContentBlock.js +13 -3
  514. package/dist/pipeline/measureContentBlock.js.map +1 -1
  515. package/dist/pipeline/paragraphContainers.d.ts +4 -1
  516. package/dist/pipeline/paragraphContainers.d.ts.map +1 -1
  517. package/dist/pipeline/paragraphContainers.js +2 -0
  518. package/dist/pipeline/paragraphContainers.js.map +1 -1
  519. package/dist/pipeline/placement.d.ts +15 -0
  520. package/dist/pipeline/placement.d.ts.map +1 -1
  521. package/dist/pipeline/placement.js +36 -4
  522. package/dist/pipeline/placement.js.map +1 -1
  523. package/dist/pipeline/raggedLines.d.ts +8 -6
  524. package/dist/pipeline/raggedLines.d.ts.map +1 -1
  525. package/dist/pipeline/raggedLines.js +13 -10
  526. package/dist/pipeline/raggedLines.js.map +1 -1
  527. package/dist/pipeline/resourceLayout.d.ts +4 -0
  528. package/dist/pipeline/resourceLayout.d.ts.map +1 -1
  529. package/dist/pipeline/resourceLayout.js +22 -7
  530. package/dist/pipeline/resourceLayout.js.map +1 -1
  531. package/dist/pipeline/resourceNumbering.d.ts +6 -3
  532. package/dist/pipeline/resourceNumbering.d.ts.map +1 -1
  533. package/dist/pipeline/resourceNumbering.js +36 -19
  534. package/dist/pipeline/resourceNumbering.js.map +1 -1
  535. package/dist/pipeline/toc.d.ts +0 -3
  536. package/dist/pipeline/toc.d.ts.map +1 -1
  537. package/dist/pipeline/toc.js +19 -2
  538. package/dist/pipeline/toc.js.map +1 -1
  539. package/dist/types.d.ts +411 -15
  540. package/dist/types.d.ts.map +1 -1
  541. package/dist/vdt.d.ts +90 -7
  542. package/dist/vdt.d.ts.map +1 -1
  543. package/dist/vdt.js.map +1 -1
  544. package/package.json +1 -1
@@ -2,30 +2,33 @@ import { FORCED_BREAK, measureForcedBreaks } from './hardBreaks';
2
2
  import { placeTab } from './tabs';
3
3
  import { uprightArabicSpans, uprightFace } from '../uprightArabic';
4
4
  import { createBoundingBox } from '../vdt';
5
- import { hyphenateText, withoutSlashJoints } from '../hyphenate';
5
+ import { getHyphenationRulesKey, hyphenateByDictionary, hyphenateText, softHyphenBreaks, withoutSlashJoints } from '../hyphenate';
6
6
  import { richTokensToItems, computeBreakpoints, reconstructRichLines, } from '../knuthPlass';
7
7
  import { SOFT_HYPHEN } from './types';
8
8
  import { lineStartAt, lineWidthAt, lineWidthFunction, markInsetLines, uniformMeasureFrom } from './types';
9
9
  import { cleanSoftHyphens, measureTextWidth, normalSpaceWidthFor } from './canvas';
10
10
  import { isRuntLastLine } from './runts';
11
- import { computeJustifiedSpaceRatio, hasOverfullLine } from './plain';
11
+ import { hasOverfullLine } from './plain';
12
+ import { justifiedSpaceRatios } from './spaceRatios';
12
13
  import { quoteFamily } from './font';
13
14
  import { trimChipLineEdges } from './chipEdges';
14
15
  import { directChipRuns } from '../design/bidiText';
15
16
  import { cjkJoinBreaks, hasCJK } from './cjk';
16
17
  import { composeCjkParagraph, cjkWordBreaks, composesAsCjk, composesDashRow, spanMarks } from './cjkCompose';
18
+ import { getCjkComposition } from './cjkPunctuation';
17
19
  import { graphemeCount, graphemesOf } from './graphemes';
18
20
  import { CENTRAL, sideMarkerRun } from './cjkAnnotate';
19
21
  import { fontEm, getMeasureRegion, getMeasureUprightDigits, getMeasureWritingMode, lineBaselineOffset, mayHoldVerticalCell, measuringVertically, verticalTextWidth, withMeasureWritingMode } from './vertical';
20
22
  import { latinReader, uprightDigitCandidates } from '../writingMode';
21
23
  import { sliceSpan } from '../parse/links';
22
- import { NO_BREAK_SPACES, WORDS_AND_SPACES_RE, isBlankText, isBreakingSpace, isBreakingSpaceRun } from './spaces';
24
+ import { NO_BREAK_SPACES, WORDS_AND_SPACES_RE, isBlankText, isBreakingSpace, isBreakingSpaceRun, refLabelPieces } from './spaces';
23
25
  import { breaksAfterDash, breaksAfterHardHyphen, hasCompound, isDash, raggedStretchPx } from './breakRules';
24
26
  import { GEMINATE_DOT, endsInsideGeminate, withLineEndHyphen } from './geminate';
25
27
  import { insideJoiningWord, joiningScriptIn, wordLetterSpacing } from './joining';
26
28
  import { applyLineDirections, applySegmentLanguages, getMeasureArabicNumbers, getMeasureDirection, spanLanguages } from './bidiLines';
27
29
  import { TATWEEL, justifyLinesWithKashida, kashidaCapacity } from './kashida';
28
30
  import { needsBidi, resolveParagraph, spanIsolates } from '../bidi';
31
+ import { cutDoubledMarks, faceReadsScript, getMeasureScriptContext, isDoubledMark, isLetterless, pieceScriptContext, resolveScriptContext, rtlTextWidth, scriptAt, scriptContextUntracked, scriptTextWidth, wordPieceScript } from './script';
29
32
  /** Whether a resolved swatch colour can fill the square: a six- or
30
33
  * eight-digit hex (`#rrggbb`, `#rrggbbaa`) or an `rgb()` / `rgba()`
31
34
  * colour. Anything else leaves the swatch an empty outline. */
@@ -121,8 +124,48 @@ function scriptOf(t) {
121
124
  ...(t.smallCaps ? { smallCaps: true } : {}),
122
125
  ...(t.cjkMarks ? { cjkMarks: t.cjkMarks } : {}),
123
126
  ...(t.inserted ? { inserted: true } : {}),
127
+ // The pieces of a word with no letter are shaped in its script (#725).
128
+ ...(t.scriptContext ? { scriptContext: t.scriptContext } : {}),
129
+ ...(t.scriptRtl ? { scriptRtl: true } : {}),
124
130
  };
125
131
  }
132
+ /** The script fields of the piece `[from, to)` of `token`, a head or a
133
+ * tail of it: the token's own when it is a word with no letter, or one
134
+ * measured right to left; else, for a word with a letter that may have
135
+ * pieces with none (`RichToken.wordScript`), the script of the piece when
136
+ * it holds no letter (it is then measured and painted in it), or the
137
+ * script in force where it starts, for the pieces cut from it later. */
138
+ function pieceScriptFields(token, from, to) {
139
+ if (token.wordScript === undefined)
140
+ return {};
141
+ const script = pieceScriptContext(token.text, from, to, token.wordScript);
142
+ if (script)
143
+ return { scriptContext: script };
144
+ const start = scriptAt(token.text, from, token.wordScript);
145
+ return start ? { wordScript: start } : {};
146
+ }
147
+ /** The width of a word of a joining script (Arabic…), always painted
148
+ * right to left: measured so too in a face that draws its punctuation by
149
+ * script (#725, `rtlTextWidth`), so the bracket or the stop at its edge
150
+ * takes the forms it is painted in; as any text otherwise. */
151
+ function rtlWordWidth(text, font) {
152
+ return getMeasureScriptContext().enabled && !measuringVertically() && faceReadsScript(font) ? rtlTextWidth(text, font) : textWidth(text, font, false);
153
+ }
154
+ /** How a token's text is measured: in its script when it is a word with
155
+ * no letter given one (#725), else as any text (`textWidth`). */
156
+ function tokenTextWidth(token, font) {
157
+ const script = token.scriptContext;
158
+ if (script)
159
+ return (text) => (text === '' ? 0 : scriptTextWidth(text, font, script, token.scriptRtl === true));
160
+ // A right-to-left word of a face that draws punctuation by script.
161
+ if (token.scriptRtl)
162
+ return (text) => (text === '' ? 0 : rtlTextWidth(text, font));
163
+ // What opens a word before its first letter is measured in its script.
164
+ const word = token.wordScript;
165
+ if (word)
166
+ return (text) => (isLetterless(text) ? scriptTextWidth(text, font, word, false) : textWidth(text, font, token.smallCaps));
167
+ return (text) => textWidth(text, font, token.smallCaps);
168
+ }
126
169
  /** Small capitals are synthesised, the same way on every backend: a
127
170
  * lowercase letter is set as its capital at this fraction of the text
128
171
  * size, while capitals, digits and punctuation keep the full size — the
@@ -439,17 +482,19 @@ export function urlBreakIndices(text) {
439
482
  /**
440
483
  * A word as laid out (its soft hyphens removed) and the breaks its soft
441
484
  * hyphens mark: the dictionary's when `hyphenate` is on, and the author's
442
- * own — the U+00AD the source carries, which the dictionary leaves as they
443
- * are (it does not hyphenate a word that already has them). The zero-width
485
+ * own — the U+00AD the source carries between two letters or digits
486
+ * (`softHyphenBreaks`), which the dictionary leaves as they are (it does not
487
+ * hyphenate a word that already has them). The zero-width
444
488
  * space the dictionary puts after a slash is dropped: the rich breaker does
445
- * not break there, and it must not reach the line text.
489
+ * not break there, and it must not reach the line text. `byDictionary`
490
+ * leaves the document's rules out (#699): every point of the patterns.
446
491
  */
447
- function syllabify(word, hyphenate) {
492
+ function syllabify(word, hyphenate, byDictionary = false) {
448
493
  // A word of a joining script is never divided, not even at a soft hyphen
449
494
  // its author typed: its letters connect (`measure/joining.ts`).
450
495
  if (joiningScriptIn(word))
451
496
  return { clean: word.includes(SOFT_HYPHEN) ? word.split(SOFT_HYPHEN).join('') : word, soft: [] };
452
- const hyphenated = hyphenate ? withoutSlashJoints(word, hyphenateText(word)) : word;
497
+ const hyphenated = hyphenate ? withoutSlashJoints(word, byDictionary ? hyphenateByDictionary(word) : hyphenateText(word)) : word;
453
498
  if (!hyphenated.includes(SOFT_HYPHEN))
454
499
  return { clean: hyphenated, soft: [] };
455
500
  let clean = '';
@@ -461,10 +506,12 @@ function syllabify(word, hyphenate) {
461
506
  const fromSource = j < word.length && ch === word[j];
462
507
  if (fromSource)
463
508
  j++;
464
- if (ch === SOFT_HYPHEN)
465
- soft.push({ index: clean.length, author: fromSource });
466
- else
509
+ if (ch !== SOFT_HYPHEN)
467
510
  clean += ch;
511
+ // One the author typed at the word's edge or next to punctuation is no
512
+ // break (#700).
513
+ else if (!fromSource || softHyphenBreaks(word, j - 1))
514
+ soft.push({ index: clean.length, author: fromSource });
468
515
  }
469
516
  return { clean, soft };
470
517
  }
@@ -483,10 +530,13 @@ function syllabify(word, hyphenate) {
483
530
  * - next to CJK characters, under the line-break rules of the document's
484
531
  * `cjk.lineBreak` (`cjk`: the word's units, measured once each, whose
485
532
  * running sums give the widths before its breaks). */
486
- function wordBreakPoints(clean, soft, font, letterSpacingPx, smallCaps, dashBreaks = false, touching, cjk) {
533
+ function wordBreakPoints(clean, soft, font, letterSpacingPx, smallCaps, dashBreaks = false, touching, cjk,
534
+ /** How the word's pieces are measured when not as any text: in the
535
+ * script of a word with no letter (#725). */
536
+ measure) {
487
537
  const widthBefore = cjk
488
538
  ? cjk.widthBefore
489
- : (idx) => textWidth(clean.slice(0, idx), font, smallCaps) + (letterSpacingPx === 0 ? 0 : letterSpacingPx * graphemeCount(clean.slice(0, idx)));
539
+ : (idx) => (measure ? measure(clean.slice(0, idx)) : textWidth(clean.slice(0, idx), font, smallCaps)) + (letterSpacingPx === 0 ? 0 : letterSpacingPx * graphemeCount(clean.slice(0, idx)));
490
540
  const byIndex = new Map();
491
541
  const add = (bp) => {
492
542
  if (bp.charIndex <= 0 || bp.charIndex >= clean.length)
@@ -548,9 +598,11 @@ export function emergencySplit(token, font, letterSpacingPx, lineMaxWidth, sylla
548
598
  return null;
549
599
  const joining = joiningScriptIn(text);
550
600
  // The word was measured untracked (`wordLetterSpacing`): its pieces too.
551
- const spacing = joining ? 0 : letterSpacingPx;
601
+ // So was a word with no letter shaped in the Arabic script (#725).
602
+ const spacing = joining || scriptContextUntracked(token.scriptContext) ? 0 : letterSpacingPx;
552
603
  const hyphenW = measureTextWidth('-', font) + spacing;
553
- const widthBefore = (idx) => textWidth(text.slice(0, idx), font, token.smallCaps) + (spacing === 0 ? 0 : spacing * graphemeCount(text.slice(0, idx)));
604
+ const measure = tokenTextWidth(token, font);
605
+ const widthBefore = (idx) => measure(text.slice(0, idx)) + (spacing === 0 ? 0 : spacing * graphemeCount(text.slice(0, idx)));
554
606
  const flags = { bold: token.bold, italic: token.italic, captionLabel: token.captionLabel, ...scriptOf(token) };
555
607
  // A group glued by no-break spaces too wide for any line: the space is
556
608
  // the least bad place to part it (EF-66). The line ends before it and the
@@ -562,8 +614,8 @@ export function emergencySplit(token, font, letterSpacingPx, lineMaxWidth, sylla
562
614
  if (headWidth > lineMaxWidth)
563
615
  continue;
564
616
  return {
565
- head: { ...flags, text: text.slice(0, idx), kind: 'text', width: headWidth },
566
- tail: { ...tailAfter(token, idx + 1, widthBefore(idx + 1)), ...flags },
617
+ head: { ...flags, ...pieceScriptFields(token, 0, idx), text: text.slice(0, idx), kind: 'text', width: headWidth },
618
+ tail: { ...tailAfter(token, idx + 1, widthBefore(idx + 1)), ...flags, ...pieceScriptFields(token, idx + 1, text.length) },
567
619
  };
568
620
  }
569
621
  // No hyphen where the cut falls next to an ideograph, or right after a
@@ -601,6 +653,18 @@ export function emergencySplit(token, font, letterSpacingPx, lineMaxWidth, sylla
601
653
  at = s.index;
602
654
  }
603
655
  }
656
+ // A word the document keeps whole (`hyphenation.exceptions`, capitalised
657
+ // words, cited names) is still divided when it is wider than its measure:
658
+ // at its entry's points above, else at the dictionary's syllables (#699).
659
+ if (at === 0 && getHyphenationRulesKey() !== '') {
660
+ const whole = syllabify(text, true, true);
661
+ if (whole.clean === text) {
662
+ for (const s of whole.soft) {
663
+ if (s.index > 0 && s.index <= reach && fits(s.index))
664
+ at = s.index;
665
+ }
666
+ }
667
+ }
604
668
  if (at === 0 && !syllablesOnly) {
605
669
  for (let idx = reach; idx >= 1; idx--) {
606
670
  // Not right before a hyphen of the text: the next line would open
@@ -624,8 +688,8 @@ export function emergencySplit(token, font, letterSpacingPx, lineMaxWidth, sylla
624
688
  return {
625
689
  head: geminate
626
690
  ? { ...flags, text: withLineEndHyphen(text.slice(0, at)), kind: 'text', width: widthBefore(at - 1) + markW(at) }
627
- : { ...flags, text: text.slice(0, at) + mark, kind: 'text', width: widthBefore(at) + markW(at) },
628
- tail: { ...tailAfter(token, at, widthBefore(at)), ...flags },
691
+ : { ...flags, ...pieceScriptFields(token, 0, at), text: text.slice(0, at) + mark, kind: 'text', width: widthBefore(at) + markW(at) },
692
+ tail: { ...tailAfter(token, at, widthBefore(at)), ...flags, ...pieceScriptFields(token, at, text.length) },
629
693
  ...(afterHyphen(at) ? { hard: true } : {}),
630
694
  };
631
695
  }
@@ -851,6 +915,42 @@ export function atomicSpanToken(span, normalFont, boldFont, italicFont, boldItal
851
915
  }
852
916
  return undefined;
853
917
  }
918
+ /**
919
+ * The tokens of a reference whose label is words (`ref.breakable`, #702):
920
+ * one per piece of the label (`refLabelPieces`: a word, with the number that
921
+ * keeps to it, or a run of breaking spaces), or undefined for a label that
922
+ * is one token ({@link atomicSpanToken}). A word is built as the whole
923
+ * label is — the reference's font, no dictionary points, never divided —
924
+ * and a space is an ordinary space of the line: a legal break, stretched
925
+ * and shrunk with the others. Every piece carries the reference, so the
926
+ * link has no holes; every piece after the first is flagged
927
+ * `refContinues`, so the reference stays one position in the source. A
928
+ * no-break space inside the label glues, as anywhere.
929
+ */
930
+ export function refLabelTokens(span, normalFont, boldFont, italicFont, boldItalicFont, letterSpacingPx) {
931
+ if (!span.ref?.breakable || span.footnote)
932
+ return undefined;
933
+ // A number, a Roman numeral or a single letter keeps to the word before
934
+ // it: `Fig. 1a` is one piece, its space set as text.
935
+ const parts = refLabelPieces(span.text);
936
+ if (!parts)
937
+ return undefined;
938
+ const tokens = [];
939
+ for (const part of parts) {
940
+ const token = atomicSpanToken({ ...span, text: part }, normalFont, boldFont, italicFont, boldItalicFont, letterSpacingPx);
941
+ if (!token)
942
+ return undefined;
943
+ if (isBreakingSpaceRun(part)) {
944
+ token.kind = 'space';
945
+ // A space has no capitals to shrink.
946
+ delete token.smallCaps;
947
+ }
948
+ if (tokens.length > 0)
949
+ token.refContinues = true;
950
+ tokens.push(token);
951
+ }
952
+ return tokens;
953
+ }
854
954
  /**
855
955
  * A footnote marker set apart from the text (`footnotes.markerPosition`,
856
956
  * JLReq §4.2.3), at its size (`span.footnote.scale` of `font`, the text's):
@@ -896,7 +996,7 @@ export function tokenSegment(t) {
896
996
  ...(t.mathRender ? { mathRender: t.mathRender } : {}),
897
997
  ...(t.swatch ? { swatch: t.swatch } : {}),
898
998
  ...(t.chip ? { chip: t.chip } : {}),
899
- ...(t.refResourceId !== undefined ? { refResourceId: t.refResourceId, ...(t.refAnchor ? { refAnchor: true } : {}), ...(t.refPageIndex !== undefined ? { refPageIndex: t.refPageIndex } : {}) } : {}),
999
+ ...(t.refResourceId !== undefined ? { refResourceId: t.refResourceId, ...(t.refAnchor ? { refAnchor: true } : {}), ...(t.refPageIndex !== undefined ? { refPageIndex: t.refPageIndex } : {}), ...(t.refContinues ? { refContinues: true } : {}) } : {}),
900
1000
  ...(t.footnoteId !== undefined ? { footnoteId: t.footnoteId } : {}),
901
1001
  ...(t.captionLabel ? { captionLabel: true } : {}),
902
1002
  ...(t.labelTab || t.tab ? { labelTab: true } : {}),
@@ -919,6 +1019,8 @@ export function tokenSegment(t) {
919
1019
  seg.inserted = true;
920
1020
  if (t.runs)
921
1021
  seg.runs = t.runs;
1022
+ if (t.scriptContext)
1023
+ seg.scriptContext = t.scriptContext;
922
1024
  return seg;
923
1025
  }
924
1026
  /**
@@ -956,7 +1058,11 @@ cjkText = true,
956
1058
  * right-to-left text: a word whose level changes inside it (`ABC،`,
957
1059
  * `و١٤٤٥`, `(API)` in Arabic) is cut there into words that touch, each
958
1060
  * measured as it is painted, as a run of its own direction. */
959
- bidi) {
1061
+ bidi,
1062
+ /** `keep-all` is in force for the block (its own `cjkWordBreak`, else
1063
+ * the document's `cjk.wordBreak`): a word that holds CJK characters does
1064
+ * not break between two letters (#705). */
1065
+ keepAll = false) {
960
1066
  const tokens = [];
961
1067
  // Which characters of the joined text sit in a compound, a word (across
962
1068
  // runs: "*after*-dinner") with a hyphen between two letters.
@@ -981,6 +1087,58 @@ bidi) {
981
1087
  return { script: span.script, scriptFont: m.font, baselineShift: m.baselineShift };
982
1088
  };
983
1089
  const spanFont = (span) => scriptFieldsOf(span).scriptFont ?? faceOf(span);
1090
+ // A word with no letter takes the script of the text around it (#725),
1091
+ // in a face that draws its punctuation by script; the paragraph's text
1092
+ // and isolates are read when the first such word turns up.
1093
+ const scriptState = getMeasureScriptContext();
1094
+ let paragraphText;
1095
+ let isolates;
1096
+ // `script` undefined: a word with letters. Right to left, it is measured
1097
+ // as it is painted (`rtlTextWidth`); left to right, the pieces of it
1098
+ // that hold no letter are measured and painted in `pieces`, the script
1099
+ // they have inside it (`wordPieceScript`).
1100
+ const contextOf = !scriptState.enabled || measuringVertically()
1101
+ ? undefined
1102
+ : (word, at, length, font) => {
1103
+ if (!faceReadsScript(font) || hasCJK(word))
1104
+ return undefined;
1105
+ const rtl = bidi !== undefined && (bidi.levels[at] & 1) === 1;
1106
+ if (!isLetterless(word)) {
1107
+ if (rtl)
1108
+ return { script: undefined, rtl };
1109
+ const pieces = wordPieceScript(word);
1110
+ return pieces ? { script: undefined, rtl, pieces } : undefined;
1111
+ }
1112
+ // The Chinese or Japanese document's own ellipsis and dash.
1113
+ if (!rtl && scriptState.hanMarks && isDoubledMark(word))
1114
+ return { script: 'Hani', rtl };
1115
+ paragraphText ??= bidi?.text ?? spans.map((sp) => sp.text).join('');
1116
+ isolates ??= spans.some((sp) => sp.direction) ? spanIsolates(spans) : [];
1117
+ const script = resolveScriptContext(paragraphText, at, at + length, rtl, isolates, scriptState.script);
1118
+ return script ? { script, rtl } : rtl ? { script: undefined, rtl } : undefined;
1119
+ };
1120
+ /** How a word in the context `contextOf` gave it is measured: whole
1121
+ * (`whole`, undefined: as any text) and up to one of its breaks
1122
+ * (`upTo`), the tracking it takes, and the fields its token carries. */
1123
+ const scriptMeasure = (context, font, sc) => {
1124
+ if (!context)
1125
+ return { untracked: false, fields: {} };
1126
+ const { script, rtl, pieces } = context;
1127
+ const whole = script ? (text) => (text === '' ? 0 : scriptTextWidth(text, font, script, rtl))
1128
+ : rtl ? (text) => (text === '' ? 0 : rtlTextWidth(text, font))
1129
+ : undefined;
1130
+ // What stands before the word's first letter is measured in its
1131
+ // script; from that letter on, a shaper gives the text that script.
1132
+ const upTo = pieces
1133
+ ? (text) => (text === '' ? 0 : isLetterless(text) ? scriptTextWidth(text, font, pieces, false) : textWidth(text, font, sc))
1134
+ : whole;
1135
+ return {
1136
+ ...(whole ? { whole } : {}),
1137
+ ...(upTo ? { upTo } : {}),
1138
+ untracked: scriptContextUntracked(script),
1139
+ fields: { ...(script ? { scriptContext: script } : {}), ...(rtl ? { scriptRtl: true } : {}), ...(pieces ? { wordScript: pieces } : {}) },
1140
+ };
1141
+ };
984
1142
  for (const span of spans) {
985
1143
  const spanBase = spanStart;
986
1144
  spanStart += span.text.length;
@@ -994,6 +1152,12 @@ bidi) {
994
1152
  }
995
1153
  continue;
996
1154
  }
1155
+ // A reference whose label is words: one token per word and space (#702).
1156
+ const label = refLabelTokens(span, normalFont, boldFont, italicFont, boldItalicFont, letterSpacingPx);
1157
+ if (label) {
1158
+ tokens.push(...label);
1159
+ continue;
1160
+ }
997
1161
  const atomic = atomicSpanToken(span, normalFont, boldFont, italicFont, boldItalicFont, letterSpacingPx);
998
1162
  if (atomic) {
999
1163
  tokens.push(atomic);
@@ -1026,7 +1190,13 @@ bidi) {
1026
1190
  const matched = span.text.match(WORDS_AND_SPACES_RE);
1027
1191
  if (!matched)
1028
1192
  continue;
1029
- const parts = bidi ? cutAtLevels(matched, spanBase, bidi) : matched;
1193
+ const levelled = bidi ? cutAtLevels(matched, spanBase, bidi) : matched;
1194
+ // In a Chinese or Japanese document a word with no letter is cut
1195
+ // around its doubled ellipses and dashes: the document's own marks,
1196
+ // set as Han text whatever sentence cites them (`cutDoubledMarks`).
1197
+ const parts = contextOf && scriptState.hanMarks && faceReadsScript(font)
1198
+ ? levelled.flatMap((part) => (isBreakingSpaceRun(part) ? undefined : cutDoubledMarks(part)) ?? [part])
1199
+ : levelled;
1030
1200
  let partStart = spanBase;
1031
1201
  for (const part of parts) {
1032
1202
  const partAt = partStart;
@@ -1034,9 +1204,15 @@ bidi) {
1034
1204
  const isSpace = isBreakingSpaceRun(part);
1035
1205
  if (!isSpace && URL_LIKE_RE.test(part.replace(/\u00AD/g, '')) && !(letterSpacingPx !== 0 && joiningScriptIn(part))) {
1036
1206
  const clean = part.replace(/\u00AD/g, '');
1207
+ // An address is one script run: its pieces with no letter
1208
+ // (`10.1006/`, `.2001`) are measured in the script they have in
1209
+ // it, and an address with no letter at all in its context's (#725).
1210
+ const inScript = scriptMeasure(contextOf?.(clean, partAt, part.length, font), font, sc);
1211
+ const spacing = inScript.untracked ? 0 : letterSpacingPx;
1212
+ const upTo = inScript.upTo ?? ((text) => textWidth(text, font, sc));
1037
1213
  const breakPoints = urlBreakIndices(clean).map((charIndex) => ({
1038
1214
  charIndex,
1039
- widthBefore: textWidth(clean.slice(0, charIndex), font, sc) + (letterSpacingPx === 0 ? 0 : letterSpacingPx * graphemeCount(clean.slice(0, charIndex))),
1215
+ widthBefore: upTo(clean.slice(0, charIndex)) + (spacing === 0 ? 0 : spacing * graphemeCount(clean.slice(0, charIndex))),
1040
1216
  }));
1041
1217
  tokens.push({
1042
1218
  text: clean,
@@ -1045,8 +1221,9 @@ bidi) {
1045
1221
  captionLabel: span.captionLabel,
1046
1222
  ...scriptFields,
1047
1223
  ...scFields,
1224
+ ...inScript.fields,
1048
1225
  kind: 'text',
1049
- width: textWidth(clean, font, sc) + track(clean),
1226
+ width: (inScript.whole ? inScript.whole(clean) : textWidth(clean, font, sc)) + (inScript.untracked ? 0 : track(clean)),
1050
1227
  ...(breakPoints.length > 0 ? { breakPoints, hyphenWidth: 0, bareBreaks: true } : {}),
1051
1228
  });
1052
1229
  continue;
@@ -1060,11 +1237,20 @@ bidi) {
1060
1237
  ? before.text.slice(-2)
1061
1238
  : undefined;
1062
1239
  // A word that holds CJK characters: measured unit by unit, once each.
1063
- const cjk = cjkText && !isSpace && hasCJK(clean) ? cjkWordBreaks(clean, font, sc, letterSpacingPx) : undefined;
1240
+ const cjk = cjkText && !isSpace && hasCJK(clean) ? cjkWordBreaks(clean, font, sc, letterSpacingPx, undefined, keepAll) : undefined;
1064
1241
  // A word of a joining script is measured untracked, its break points
1065
1242
  // (after a hyphen or a dash it carries) too.
1066
- const wordSpacing = isSpace ? letterSpacingPx : wordLetterSpacing(clean, letterSpacingPx);
1067
- const breakPoints = isSpace ? [] : wordBreakPoints(clean, soft, font, wordSpacing, sc, dashBreaks, touching, cjk);
1243
+ // A word with no letter: measured in the script of its context, its
1244
+ // pieces at a break too (#725). In the Arabic script it takes no
1245
+ // tracking, as the Arabic words around it take none.
1246
+ // A word with a letter: its pieces with no letter (`COVID-` | `19`)
1247
+ // in the script they have inside it.
1248
+ const measured = scriptMeasure(contextOf && !isSpace && !cjk ? contextOf(clean, partAt, part.length, font) : undefined, font, sc);
1249
+ const untracked = measured.untracked;
1250
+ const wordSpacing = isSpace ? letterSpacingPx : untracked ? 0 : wordLetterSpacing(clean, letterSpacingPx);
1251
+ const inScript = measured.whole;
1252
+ const contextFields = measured.fields;
1253
+ const breakPoints = isSpace ? [] : wordBreakPoints(clean, soft, font, wordSpacing, sc, dashBreaks, touching, cjk, measured.upTo);
1068
1254
  if (breakPoints.length > 0) {
1069
1255
  tokens.push({
1070
1256
  text: clean,
@@ -1073,8 +1259,9 @@ bidi) {
1073
1259
  captionLabel: span.captionLabel,
1074
1260
  ...scriptFields,
1075
1261
  ...scFields,
1262
+ ...contextFields,
1076
1263
  kind: 'text',
1077
- width: cjk ? cjk.width : textWidth(clean, font, sc) + track(clean),
1264
+ width: cjk ? cjk.width : (inScript ? inScript(clean) : textWidth(clean, font, sc)) + (untracked ? 0 : track(clean)),
1078
1265
  breakPoints,
1079
1266
  hyphenWidth: measureTextWidth('-', font) + letterSpacingPx,
1080
1267
  });
@@ -1090,8 +1277,9 @@ bidi) {
1090
1277
  captionLabel: span.captionLabel,
1091
1278
  ...scriptFields,
1092
1279
  ...(isSpace ? {} : scFields),
1280
+ ...contextFields,
1093
1281
  kind: isSpace ? 'space' : 'text',
1094
- width: textWidth(word, font, sc && !isSpace) + track(word),
1282
+ width: (inScript ? inScript(word) : textWidth(word, font, sc && !isSpace)) + (untracked ? 0 : track(word)),
1095
1283
  });
1096
1284
  }
1097
1285
  }
@@ -1176,7 +1364,7 @@ function joinStyledRuns(tokens, normalFont, boldFont, italicFont, boldItalicFont
1176
1364
  italic: dominant.italic,
1177
1365
  ...(parts[0].captionLabel ? { captionLabel: true } : {}),
1178
1366
  kind: 'text',
1179
- width: textWidth(text, tokenFont(dominant, normalFont, boldFont, italicFont, boldItalicFont), false),
1367
+ width: rtlWordWidth(text, tokenFont(dominant, normalFont, boldFont, italicFont, boldItalicFont)),
1180
1368
  ...(dominant.faceFont ? { faceFont: dominant.faceFont } : {}),
1181
1369
  ...(runs.length > 1 ? { runs } : {}),
1182
1370
  ...(parts[parts.length - 1].dashJoin ? { dashJoin: true } : {}),
@@ -1296,9 +1484,10 @@ function splitToken(token, bp, mark, markWidth) {
1296
1484
  return {
1297
1485
  head: mark !== '' && bp.replacesWidth !== undefined
1298
1486
  ? { ...flags, text: withLineEndHyphen(token.text.slice(0, bp.charIndex)), kind: 'text', width: bp.widthBefore - bp.replacesWidth + markWidth }
1299
- : { ...flags, text: token.text.slice(0, bp.charIndex) + mark, kind: 'text', width: bp.widthBefore + markWidth },
1487
+ : { ...flags, ...pieceScriptFields(token, 0, bp.charIndex), text: token.text.slice(0, bp.charIndex) + mark, kind: 'text', width: bp.widthBefore + markWidth },
1300
1488
  tail: {
1301
1489
  ...flags,
1490
+ ...pieceScriptFields(token, bp.charIndex, token.text.length),
1302
1491
  text: token.text.slice(bp.charIndex),
1303
1492
  kind: 'text',
1304
1493
  width: token.width - bp.widthBefore,
@@ -1451,7 +1640,10 @@ function measureRichText(spans, plainText, normalFont, boldFont, italicFont, bol
1451
1640
  // The languages the paragraph's isolates name (`:ltr[…]{lang=en}`), set
1452
1641
  // on the segments of their text (`VDTLineSegment.lang`).
1453
1642
  const languages = spans.some((sp) => sp.direction?.lang !== undefined || sp.direction?.outer !== undefined) ? spanLanguages(spans) : [];
1454
- const tokens = tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont, shouldHyphenate, letterSpacingPx, options?.breakAfterDashes === true, options?.hyphenateCompounds === false, cjkText, bidi);
1643
+ // `keep-all` holds in a Latin paragraph that quotes CJK characters as it
1644
+ // does in one the composer sets (#705).
1645
+ const keepAll = cjkText && (options?.cjkWordBreak !== undefined ? options.cjkWordBreak === 'keep-all' : (options?.cjkComposition ?? getCjkComposition()).keepAll === true);
1646
+ const tokens = tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont, shouldHyphenate, letterSpacingPx, options?.breakAfterDashes === true, options?.hyphenateCompounds === false, cjkText, bidi, keepAll);
1455
1647
  if (options?.labelColumnPx !== undefined)
1456
1648
  setLabelTabs(tokens, (t) => t.labelTab, options.labelColumnPx, (t, w) => { t.width = w; });
1457
1649
  const repeatHyphen = options?.repeatHyphen === true;
@@ -1470,7 +1662,7 @@ function measureRichText(spans, plainText, normalFont, boldFont, italicFont, bol
1470
1662
  return;
1471
1663
  justifyLinesWithKashida(lines, (li) => {
1472
1664
  return lineWidthAt(maxWidthPx, options, li);
1473
- }, normalSpaceWidth, kashida, (seg, text) => textWidth(text, fontOf(seg), false));
1665
+ }, normalSpaceWidth, kashida, (seg, text) => rtlWordWidth(text, fontOf(seg)));
1474
1666
  };
1475
1667
  // Knuth-Plass optimal line breaking path. A Latin paragraph quoting CJK
1476
1668
  // words takes it too: the breaks next to their characters are free
@@ -1817,7 +2009,7 @@ function measureRichText(spans, plainText, normalFont, boldFont, italicFont, bol
1817
2009
  const lineText = lineTokens.map((t) => cleanSoftHyphens(t.text)).join('');
1818
2010
  const contentWidth = segments.reduce((sum, t) => sum + t.width, 0);
1819
2011
  // A tabbed line is set as measured: its widths are final.
1820
- const justifiedSpaceRatio = lineTabbed ? undefined : computeJustifiedSpaceRatio(segments, lineMaxWidth, normalSpaceWidth, textAlign, isLastLine);
2012
+ const spaceRatios = lineTabbed || textAlign !== 'justify' || isLastLine ? {} : justifiedSpaceRatios(segments, lineMaxWidth, normalSpaceWidth);
1821
2013
  lines.push({
1822
2014
  text: lineText,
1823
2015
  bbox: createBoundingBox(lineIndent, y, contentWidth, lineHeightPx),
@@ -1827,7 +2019,7 @@ function measureRichText(spans, plainText, normalFont, boldFont, italicFont, bol
1827
2019
  ...(lineRepeated && lineText.startsWith('-') ? { repeatedHyphen: true } : {}),
1828
2020
  segments,
1829
2021
  isLastLine,
1830
- ...(justifiedSpaceRatio !== undefined ? { justifiedSpaceRatio } : {}),
2022
+ ...spaceRatios,
1831
2023
  ...(lineWordOverflow ? { wordOverflow: true } : {}),
1832
2024
  ...(lineTabbed ? { tabbed: true, ...(textAlign === 'justify' ? { ragged: true } : {}) } : {}),
1833
2025
  });