postext 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1072) hide show
  1. package/README.md +76 -202
  2. package/dist/__tests__/breakOpportunities.test.d.ts +2 -0
  3. package/dist/__tests__/breakOpportunities.test.d.ts.map +1 -0
  4. package/dist/__tests__/breakOpportunities.test.js +204 -0
  5. package/dist/__tests__/breakOpportunities.test.js.map +1 -0
  6. package/dist/__tests__/bundle.test.js +399 -1
  7. package/dist/__tests__/bundle.test.js.map +1 -1
  8. package/dist/__tests__/bundleLocaleAndBytes.test.d.ts +2 -0
  9. package/dist/__tests__/bundleLocaleAndBytes.test.d.ts.map +1 -0
  10. package/dist/__tests__/bundleLocaleAndBytes.test.js +177 -0
  11. package/dist/__tests__/bundleLocaleAndBytes.test.js.map +1 -0
  12. package/dist/__tests__/colorAlpha.test.d.ts +2 -0
  13. package/dist/__tests__/colorAlpha.test.d.ts.map +1 -0
  14. package/dist/__tests__/colorAlpha.test.js +87 -0
  15. package/dist/__tests__/colorAlpha.test.js.map +1 -0
  16. package/dist/__tests__/columnBalancing.test.js +88 -0
  17. package/dist/__tests__/columnBalancing.test.js.map +1 -1
  18. package/dist/__tests__/columnClip.test.js +20 -0
  19. package/dist/__tests__/columnClip.test.js.map +1 -1
  20. package/dist/__tests__/columnRuleBands.test.d.ts +2 -0
  21. package/dist/__tests__/columnRuleBands.test.d.ts.map +1 -0
  22. package/dist/__tests__/columnRuleBands.test.js +146 -0
  23. package/dist/__tests__/columnRuleBands.test.js.map +1 -0
  24. package/dist/__tests__/contentWarnings.test.d.ts +2 -0
  25. package/dist/__tests__/contentWarnings.test.d.ts.map +1 -0
  26. package/dist/__tests__/contentWarnings.test.js +219 -0
  27. package/dist/__tests__/contentWarnings.test.js.map +1 -0
  28. package/dist/__tests__/continuation.test.js +2 -1
  29. package/dist/__tests__/continuation.test.js.map +1 -1
  30. package/dist/__tests__/createLayout.test.js +18 -1
  31. package/dist/__tests__/createLayout.test.js.map +1 -1
  32. package/dist/__tests__/cropMarks.test.d.ts +2 -0
  33. package/dist/__tests__/cropMarks.test.d.ts.map +1 -0
  34. package/dist/__tests__/cropMarks.test.js +138 -0
  35. package/dist/__tests__/cropMarks.test.js.map +1 -0
  36. package/dist/__tests__/defaults/calloutStyles.test.js +30 -0
  37. package/dist/__tests__/defaults/calloutStyles.test.js.map +1 -1
  38. package/dist/__tests__/defaults/headingsBreakBefore.test.d.ts +2 -0
  39. package/dist/__tests__/defaults/headingsBreakBefore.test.d.ts.map +1 -0
  40. package/dist/__tests__/defaults/headingsBreakBefore.test.js +78 -0
  41. package/dist/__tests__/defaults/headingsBreakBefore.test.js.map +1 -0
  42. package/dist/__tests__/defaults/paragraphStyles.test.js +22 -0
  43. package/dist/__tests__/defaults/paragraphStyles.test.js.map +1 -1
  44. package/dist/__tests__/design/bleedClip.test.d.ts +2 -0
  45. package/dist/__tests__/design/bleedClip.test.d.ts.map +1 -0
  46. package/dist/__tests__/design/bleedClip.test.js +91 -0
  47. package/dist/__tests__/design/bleedClip.test.js.map +1 -0
  48. package/dist/__tests__/design/boxBorderInside.test.d.ts +2 -0
  49. package/dist/__tests__/design/boxBorderInside.test.d.ts.map +1 -0
  50. package/dist/__tests__/design/boxBorderInside.test.js +102 -0
  51. package/dist/__tests__/design/boxBorderInside.test.js.map +1 -0
  52. package/dist/__tests__/design/designLineHeight.test.d.ts +2 -0
  53. package/dist/__tests__/design/designLineHeight.test.d.ts.map +1 -0
  54. package/dist/__tests__/design/designLineHeight.test.js +108 -0
  55. package/dist/__tests__/design/designLineHeight.test.js.map +1 -0
  56. package/dist/__tests__/design/designText.test.d.ts +2 -0
  57. package/dist/__tests__/design/designText.test.d.ts.map +1 -0
  58. package/dist/__tests__/design/designText.test.js +331 -0
  59. package/dist/__tests__/design/designText.test.js.map +1 -0
  60. package/dist/__tests__/design/designTextJustify.test.d.ts +2 -0
  61. package/dist/__tests__/design/designTextJustify.test.d.ts.map +1 -0
  62. package/dist/__tests__/design/designTextJustify.test.js +119 -0
  63. package/dist/__tests__/design/designTextJustify.test.js.map +1 -0
  64. package/dist/__tests__/design/designTextNegativeTracking.test.d.ts +2 -0
  65. package/dist/__tests__/design/designTextNegativeTracking.test.d.ts.map +1 -0
  66. package/dist/__tests__/design/designTextNegativeTracking.test.js +95 -0
  67. package/dist/__tests__/design/designTextNegativeTracking.test.js.map +1 -0
  68. package/dist/__tests__/design/designTextRender.test.d.ts +2 -0
  69. package/dist/__tests__/design/designTextRender.test.d.ts.map +1 -0
  70. package/dist/__tests__/design/designTextRender.test.js +106 -0
  71. package/dist/__tests__/design/designTextRender.test.js.map +1 -0
  72. package/dist/__tests__/design/dropCap.test.d.ts +2 -0
  73. package/dist/__tests__/design/dropCap.test.d.ts.map +1 -0
  74. package/dist/__tests__/design/dropCap.test.js +205 -0
  75. package/dist/__tests__/design/dropCap.test.js.map +1 -0
  76. package/dist/__tests__/design/ellipsis.test.d.ts +2 -0
  77. package/dist/__tests__/design/ellipsis.test.d.ts.map +1 -0
  78. package/dist/__tests__/design/ellipsis.test.js +113 -0
  79. package/dist/__tests__/design/ellipsis.test.js.map +1 -0
  80. package/dist/__tests__/design/headingDesignClip.test.d.ts +2 -0
  81. package/dist/__tests__/design/headingDesignClip.test.d.ts.map +1 -0
  82. package/dist/__tests__/design/headingDesignClip.test.js +60 -0
  83. package/dist/__tests__/design/headingDesignClip.test.js.map +1 -0
  84. package/dist/__tests__/design/headingDesignSideChannel.test.d.ts +2 -0
  85. package/dist/__tests__/design/headingDesignSideChannel.test.d.ts.map +1 -0
  86. package/dist/__tests__/design/headingDesignSideChannel.test.js +187 -0
  87. package/dist/__tests__/design/headingDesignSideChannel.test.js.map +1 -0
  88. package/dist/__tests__/design/inColumnTitleBreak.test.d.ts +2 -0
  89. package/dist/__tests__/design/inColumnTitleBreak.test.d.ts.map +1 -0
  90. package/dist/__tests__/design/inColumnTitleBreak.test.js +60 -0
  91. package/dist/__tests__/design/inColumnTitleBreak.test.js.map +1 -0
  92. package/dist/__tests__/design/openerBottomAnchor.test.d.ts +2 -0
  93. package/dist/__tests__/design/openerBottomAnchor.test.d.ts.map +1 -0
  94. package/dist/__tests__/design/openerBottomAnchor.test.js +106 -0
  95. package/dist/__tests__/design/openerBottomAnchor.test.js.map +1 -0
  96. package/dist/__tests__/design/openerChapterNumber.test.d.ts +2 -0
  97. package/dist/__tests__/design/openerChapterNumber.test.d.ts.map +1 -0
  98. package/dist/__tests__/design/openerChapterNumber.test.js +163 -0
  99. package/dist/__tests__/design/openerChapterNumber.test.js.map +1 -0
  100. package/dist/__tests__/design/openerImageReserve.test.d.ts +2 -0
  101. package/dist/__tests__/design/openerImageReserve.test.d.ts.map +1 -0
  102. package/dist/__tests__/design/openerImageReserve.test.js +83 -0
  103. package/dist/__tests__/design/openerImageReserve.test.js.map +1 -0
  104. package/dist/__tests__/design/openerReserve.test.d.ts +2 -0
  105. package/dist/__tests__/design/openerReserve.test.d.ts.map +1 -0
  106. package/dist/__tests__/design/openerReserve.test.js +147 -0
  107. package/dist/__tests__/design/openerReserve.test.js.map +1 -0
  108. package/dist/__tests__/design/ruleDefaults.test.d.ts +2 -0
  109. package/dist/__tests__/design/ruleDefaults.test.d.ts.map +1 -0
  110. package/dist/__tests__/design/ruleDefaults.test.js +59 -0
  111. package/dist/__tests__/design/ruleDefaults.test.js.map +1 -0
  112. package/dist/__tests__/design/runningHeads.test.js +4 -2
  113. package/dist/__tests__/design/runningHeads.test.js.map +1 -1
  114. package/dist/__tests__/design/titleTextWrapped.test.d.ts +2 -0
  115. package/dist/__tests__/design/titleTextWrapped.test.d.ts.map +1 -0
  116. package/dist/__tests__/design/titleTextWrapped.test.js +258 -0
  117. package/dist/__tests__/design/titleTextWrapped.test.js.map +1 -0
  118. package/dist/__tests__/design/trackingAlignment.test.d.ts +2 -0
  119. package/dist/__tests__/design/trackingAlignment.test.d.ts.map +1 -0
  120. package/dist/__tests__/design/trackingAlignment.test.js +101 -0
  121. package/dist/__tests__/design/trackingAlignment.test.js.map +1 -0
  122. package/dist/__tests__/design/verticalAlignOverflow.test.d.ts +2 -0
  123. package/dist/__tests__/design/verticalAlignOverflow.test.d.ts.map +1 -0
  124. package/dist/__tests__/design/verticalAlignOverflow.test.js +68 -0
  125. package/dist/__tests__/design/verticalAlignOverflow.test.js.map +1 -0
  126. package/dist/__tests__/exports.test.js +24 -0
  127. package/dist/__tests__/exports.test.js.map +1 -1
  128. package/dist/__tests__/fontStack.test.d.ts +2 -0
  129. package/dist/__tests__/fontStack.test.d.ts.map +1 -0
  130. package/dist/__tests__/fontStack.test.js +100 -0
  131. package/dist/__tests__/fontStack.test.js.map +1 -0
  132. package/dist/__tests__/frontmatterValues.test.d.ts +2 -0
  133. package/dist/__tests__/frontmatterValues.test.d.ts.map +1 -0
  134. package/dist/__tests__/frontmatterValues.test.js +119 -0
  135. package/dist/__tests__/frontmatterValues.test.js.map +1 -0
  136. package/dist/__tests__/gradedRunt.test.d.ts +2 -0
  137. package/dist/__tests__/gradedRunt.test.d.ts.map +1 -0
  138. package/dist/__tests__/gradedRunt.test.js +66 -0
  139. package/dist/__tests__/gradedRunt.test.js.map +1 -0
  140. package/dist/__tests__/headingAlign.test.d.ts +2 -0
  141. package/dist/__tests__/headingAlign.test.d.ts.map +1 -0
  142. package/dist/__tests__/headingAlign.test.js +92 -0
  143. package/dist/__tests__/headingAlign.test.js.map +1 -0
  144. package/dist/__tests__/headingInlineMarks.test.d.ts +2 -0
  145. package/dist/__tests__/headingInlineMarks.test.d.ts.map +1 -0
  146. package/dist/__tests__/headingInlineMarks.test.js +126 -0
  147. package/dist/__tests__/headingInlineMarks.test.js.map +1 -0
  148. package/dist/__tests__/headingLetterSpacing.test.d.ts +2 -0
  149. package/dist/__tests__/headingLetterSpacing.test.d.ts.map +1 -0
  150. package/dist/__tests__/headingLetterSpacing.test.js +135 -0
  151. package/dist/__tests__/headingLetterSpacing.test.js.map +1 -0
  152. package/dist/__tests__/headingNumberPlaceholders.test.d.ts +2 -0
  153. package/dist/__tests__/headingNumberPlaceholders.test.d.ts.map +1 -0
  154. package/dist/__tests__/headingNumberPlaceholders.test.js +104 -0
  155. package/dist/__tests__/headingNumberPlaceholders.test.js.map +1 -0
  156. package/dist/__tests__/headingNumberingStyles.test.d.ts +2 -0
  157. package/dist/__tests__/headingNumberingStyles.test.d.ts.map +1 -0
  158. package/dist/__tests__/headingNumberingStyles.test.js +151 -0
  159. package/dist/__tests__/headingNumberingStyles.test.js.map +1 -0
  160. package/dist/__tests__/headingSourceTitle.test.d.ts +2 -0
  161. package/dist/__tests__/headingSourceTitle.test.d.ts.map +1 -0
  162. package/dist/__tests__/headingSourceTitle.test.js +35 -0
  163. package/dist/__tests__/headingSourceTitle.test.js.map +1 -0
  164. package/dist/__tests__/headingStyleBreakAfterPagebreak.test.d.ts +2 -0
  165. package/dist/__tests__/headingStyleBreakAfterPagebreak.test.d.ts.map +1 -0
  166. package/dist/__tests__/headingStyleBreakAfterPagebreak.test.js +52 -0
  167. package/dist/__tests__/headingStyleBreakAfterPagebreak.test.js.map +1 -0
  168. package/dist/__tests__/hiddenHeadings.test.d.ts +2 -0
  169. package/dist/__tests__/hiddenHeadings.test.d.ts.map +1 -0
  170. package/dist/__tests__/hiddenHeadings.test.js +137 -0
  171. package/dist/__tests__/hiddenHeadings.test.js.map +1 -0
  172. package/dist/__tests__/htmlHostReset.test.d.ts +2 -0
  173. package/dist/__tests__/htmlHostReset.test.d.ts.map +1 -0
  174. package/dist/__tests__/htmlHostReset.test.js +63 -0
  175. package/dist/__tests__/htmlHostReset.test.js.map +1 -0
  176. package/dist/__tests__/hyphenationLocale.test.d.ts +2 -0
  177. package/dist/__tests__/hyphenationLocale.test.d.ts.map +1 -0
  178. package/dist/__tests__/hyphenationLocale.test.js +143 -0
  179. package/dist/__tests__/hyphenationLocale.test.js.map +1 -0
  180. package/dist/__tests__/justifyTracking.test.d.ts +2 -0
  181. package/dist/__tests__/justifyTracking.test.d.ts.map +1 -0
  182. package/dist/__tests__/justifyTracking.test.js +217 -0
  183. package/dist/__tests__/justifyTracking.test.js.map +1 -0
  184. package/dist/__tests__/layoutWorkerClient.test.d.ts +2 -0
  185. package/dist/__tests__/layoutWorkerClient.test.d.ts.map +1 -0
  186. package/dist/__tests__/layoutWorkerClient.test.js +140 -0
  187. package/dist/__tests__/layoutWorkerClient.test.js.map +1 -0
  188. package/dist/__tests__/links.test.d.ts +2 -0
  189. package/dist/__tests__/links.test.d.ts.map +1 -0
  190. package/dist/__tests__/links.test.js +227 -0
  191. package/dist/__tests__/links.test.js.map +1 -0
  192. package/dist/__tests__/localisedStrings.test.d.ts +2 -0
  193. package/dist/__tests__/localisedStrings.test.d.ts.map +1 -0
  194. package/dist/__tests__/localisedStrings.test.js +118 -0
  195. package/dist/__tests__/localisedStrings.test.js.map +1 -0
  196. package/dist/__tests__/looseLines.test.d.ts +2 -0
  197. package/dist/__tests__/looseLines.test.d.ts.map +1 -0
  198. package/dist/__tests__/looseLines.test.js +72 -0
  199. package/dist/__tests__/looseLines.test.js.map +1 -0
  200. package/dist/__tests__/mainEntryReact.test.d.ts +2 -0
  201. package/dist/__tests__/mainEntryReact.test.d.ts.map +1 -0
  202. package/dist/__tests__/mainEntryReact.test.js +13 -0
  203. package/dist/__tests__/mainEntryReact.test.js.map +1 -0
  204. package/dist/__tests__/mathBundle.test.d.ts +2 -0
  205. package/dist/__tests__/mathBundle.test.d.ts.map +1 -0
  206. package/dist/__tests__/mathBundle.test.js +80 -0
  207. package/dist/__tests__/mathBundle.test.js.map +1 -0
  208. package/dist/__tests__/mathEngine.test.d.ts +2 -0
  209. package/dist/__tests__/mathEngine.test.d.ts.map +1 -0
  210. package/dist/__tests__/mathEngine.test.js +69 -0
  211. package/dist/__tests__/mathEngine.test.js.map +1 -0
  212. package/dist/__tests__/mathEngineInit.test.d.ts +2 -0
  213. package/dist/__tests__/mathEngineInit.test.d.ts.map +1 -0
  214. package/dist/__tests__/mathEngineInit.test.js +33 -0
  215. package/dist/__tests__/mathEngineInit.test.js.map +1 -0
  216. package/dist/__tests__/mathSize.test.d.ts +2 -0
  217. package/dist/__tests__/mathSize.test.d.ts.map +1 -0
  218. package/dist/__tests__/mathSize.test.js +168 -0
  219. package/dist/__tests__/mathSize.test.js.map +1 -0
  220. package/dist/__tests__/mathSizeMigration.test.d.ts +2 -0
  221. package/dist/__tests__/mathSizeMigration.test.d.ts.map +1 -0
  222. package/dist/__tests__/mathSizeMigration.test.js +188 -0
  223. package/dist/__tests__/mathSizeMigration.test.js.map +1 -0
  224. package/dist/__tests__/measureCache.test.js +148 -4
  225. package/dist/__tests__/measureCache.test.js.map +1 -1
  226. package/dist/__tests__/measureCacheKeepBreaks.test.d.ts +2 -0
  227. package/dist/__tests__/measureCacheKeepBreaks.test.d.ts.map +1 -0
  228. package/dist/__tests__/measureCacheKeepBreaks.test.js +59 -0
  229. package/dist/__tests__/measureCacheKeepBreaks.test.js.map +1 -0
  230. package/dist/__tests__/noBreakSpaces.test.d.ts +2 -0
  231. package/dist/__tests__/noBreakSpaces.test.d.ts.map +1 -0
  232. package/dist/__tests__/noBreakSpaces.test.js +208 -0
  233. package/dist/__tests__/noBreakSpaces.test.js.map +1 -0
  234. package/dist/__tests__/numberFormats.test.d.ts +2 -0
  235. package/dist/__tests__/numberFormats.test.d.ts.map +1 -0
  236. package/dist/__tests__/numberFormats.test.js +142 -0
  237. package/dist/__tests__/numberFormats.test.js.map +1 -0
  238. package/dist/__tests__/paletteEverywhere.test.d.ts +2 -0
  239. package/dist/__tests__/paletteEverywhere.test.d.ts.map +1 -0
  240. package/dist/__tests__/paletteEverywhere.test.js +228 -0
  241. package/dist/__tests__/paletteEverywhere.test.js.map +1 -0
  242. package/dist/__tests__/paragraphStyleIndent.test.d.ts +2 -0
  243. package/dist/__tests__/paragraphStyleIndent.test.d.ts.map +1 -0
  244. package/dist/__tests__/paragraphStyleIndent.test.js +91 -0
  245. package/dist/__tests__/paragraphStyleIndent.test.js.map +1 -0
  246. package/dist/__tests__/parse/attrQuoting.test.d.ts +2 -0
  247. package/dist/__tests__/parse/attrQuoting.test.d.ts.map +1 -0
  248. package/dist/__tests__/parse/attrQuoting.test.js +87 -0
  249. package/dist/__tests__/parse/attrQuoting.test.js.map +1 -0
  250. package/dist/__tests__/parse/codeSpans.test.d.ts +2 -0
  251. package/dist/__tests__/parse/codeSpans.test.d.ts.map +1 -0
  252. package/dist/__tests__/parse/codeSpans.test.js +31 -0
  253. package/dist/__tests__/parse/codeSpans.test.js.map +1 -0
  254. package/dist/__tests__/parse/intrawordUnderscore.test.d.ts +2 -0
  255. package/dist/__tests__/parse/intrawordUnderscore.test.d.ts.map +1 -0
  256. package/dist/__tests__/parse/intrawordUnderscore.test.js +69 -0
  257. package/dist/__tests__/parse/intrawordUnderscore.test.js.map +1 -0
  258. package/dist/__tests__/parse/scripts.test.js +4 -1
  259. package/dist/__tests__/parse/scripts.test.js.map +1 -1
  260. package/dist/__tests__/parts.test.js +103 -0
  261. package/dist/__tests__/parts.test.js.map +1 -1
  262. package/dist/__tests__/pipeline/balancingRecord.test.d.ts +2 -0
  263. package/dist/__tests__/pipeline/balancingRecord.test.d.ts.map +1 -0
  264. package/dist/__tests__/pipeline/balancingRecord.test.js +176 -0
  265. package/dist/__tests__/pipeline/balancingRecord.test.js.map +1 -0
  266. package/dist/__tests__/pipeline/blockquoteStyle.test.d.ts +2 -0
  267. package/dist/__tests__/pipeline/blockquoteStyle.test.d.ts.map +1 -0
  268. package/dist/__tests__/pipeline/blockquoteStyle.test.js +99 -0
  269. package/dist/__tests__/pipeline/blockquoteStyle.test.js.map +1 -0
  270. package/dist/__tests__/pipeline/calloutContinuation.test.d.ts +2 -0
  271. package/dist/__tests__/pipeline/calloutContinuation.test.d.ts.map +1 -0
  272. package/dist/__tests__/pipeline/calloutContinuation.test.js +133 -0
  273. package/dist/__tests__/pipeline/calloutContinuation.test.js.map +1 -0
  274. package/dist/__tests__/pipeline/calloutContinuationInset.test.d.ts +2 -0
  275. package/dist/__tests__/pipeline/calloutContinuationInset.test.d.ts.map +1 -0
  276. package/dist/__tests__/pipeline/calloutContinuationInset.test.js +116 -0
  277. package/dist/__tests__/pipeline/calloutContinuationInset.test.js.map +1 -0
  278. package/dist/__tests__/pipeline/calloutCornerWideIcon.test.d.ts +2 -0
  279. package/dist/__tests__/pipeline/calloutCornerWideIcon.test.d.ts.map +1 -0
  280. package/dist/__tests__/pipeline/calloutCornerWideIcon.test.js +69 -0
  281. package/dist/__tests__/pipeline/calloutCornerWideIcon.test.js.map +1 -0
  282. package/dist/__tests__/pipeline/calloutFloatMargins.test.d.ts +2 -0
  283. package/dist/__tests__/pipeline/calloutFloatMargins.test.d.ts.map +1 -0
  284. package/dist/__tests__/pipeline/calloutFloatMargins.test.js +104 -0
  285. package/dist/__tests__/pipeline/calloutFloatMargins.test.js.map +1 -0
  286. package/dist/__tests__/pipeline/calloutInlineResourceGap.test.d.ts +2 -0
  287. package/dist/__tests__/pipeline/calloutInlineResourceGap.test.d.ts.map +1 -0
  288. package/dist/__tests__/pipeline/calloutInlineResourceGap.test.js +148 -0
  289. package/dist/__tests__/pipeline/calloutInlineResourceGap.test.js.map +1 -0
  290. package/dist/__tests__/pipeline/calloutListColor.test.d.ts +2 -0
  291. package/dist/__tests__/pipeline/calloutListColor.test.d.ts.map +1 -0
  292. package/dist/__tests__/pipeline/calloutListColor.test.js +86 -0
  293. package/dist/__tests__/pipeline/calloutListColor.test.js.map +1 -0
  294. package/dist/__tests__/pipeline/calloutRaggedLines.test.d.ts +2 -0
  295. package/dist/__tests__/pipeline/calloutRaggedLines.test.d.ts.map +1 -0
  296. package/dist/__tests__/pipeline/calloutRaggedLines.test.js +65 -0
  297. package/dist/__tests__/pipeline/calloutRaggedLines.test.js.map +1 -0
  298. package/dist/__tests__/pipeline/calloutRuntTracking.test.d.ts +2 -0
  299. package/dist/__tests__/pipeline/calloutRuntTracking.test.d.ts.map +1 -0
  300. package/dist/__tests__/pipeline/calloutRuntTracking.test.js +84 -0
  301. package/dist/__tests__/pipeline/calloutRuntTracking.test.js.map +1 -0
  302. package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.d.ts +2 -0
  303. package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.d.ts.map +1 -0
  304. package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.js +187 -0
  305. package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.js.map +1 -0
  306. package/dist/__tests__/pipeline/calloutStripeRadius.test.d.ts +2 -0
  307. package/dist/__tests__/pipeline/calloutStripeRadius.test.d.ts.map +1 -0
  308. package/dist/__tests__/pipeline/calloutStripeRadius.test.js +127 -0
  309. package/dist/__tests__/pipeline/calloutStripeRadius.test.js.map +1 -0
  310. package/dist/__tests__/pipeline/calloutTitleLineHeight.test.d.ts +2 -0
  311. package/dist/__tests__/pipeline/calloutTitleLineHeight.test.d.ts.map +1 -0
  312. package/dist/__tests__/pipeline/calloutTitleLineHeight.test.js +81 -0
  313. package/dist/__tests__/pipeline/calloutTitleLineHeight.test.js.map +1 -0
  314. package/dist/__tests__/pipeline/calloutTypography.test.d.ts +2 -0
  315. package/dist/__tests__/pipeline/calloutTypography.test.d.ts.map +1 -0
  316. package/dist/__tests__/pipeline/calloutTypography.test.js +97 -0
  317. package/dist/__tests__/pipeline/calloutTypography.test.js.map +1 -0
  318. package/dist/__tests__/pipeline/capUnderHeadFloats.test.d.ts +2 -0
  319. package/dist/__tests__/pipeline/capUnderHeadFloats.test.d.ts.map +1 -0
  320. package/dist/__tests__/pipeline/capUnderHeadFloats.test.js +68 -0
  321. package/dist/__tests__/pipeline/capUnderHeadFloats.test.js.map +1 -0
  322. package/dist/__tests__/pipeline/captionAlign.test.d.ts +2 -0
  323. package/dist/__tests__/pipeline/captionAlign.test.d.ts.map +1 -0
  324. package/dist/__tests__/pipeline/captionAlign.test.js +99 -0
  325. package/dist/__tests__/pipeline/captionAlign.test.js.map +1 -0
  326. package/dist/__tests__/pipeline/chipPalette.test.d.ts +2 -0
  327. package/dist/__tests__/pipeline/chipPalette.test.d.ts.map +1 -0
  328. package/dist/__tests__/pipeline/chipPalette.test.js +80 -0
  329. package/dist/__tests__/pipeline/chipPalette.test.js.map +1 -0
  330. package/dist/__tests__/pipeline/chipVerticalPadding.test.d.ts +2 -0
  331. package/dist/__tests__/pipeline/chipVerticalPadding.test.d.ts.map +1 -0
  332. package/dist/__tests__/pipeline/chipVerticalPadding.test.js +66 -0
  333. package/dist/__tests__/pipeline/chipVerticalPadding.test.js.map +1 -0
  334. package/dist/__tests__/pipeline/chips.test.js +32 -0
  335. package/dist/__tests__/pipeline/chips.test.js.map +1 -1
  336. package/dist/__tests__/pipeline/closingBoxLever.test.d.ts +2 -0
  337. package/dist/__tests__/pipeline/closingBoxLever.test.d.ts.map +1 -0
  338. package/dist/__tests__/pipeline/closingBoxLever.test.js +68 -0
  339. package/dist/__tests__/pipeline/closingBoxLever.test.js.map +1 -0
  340. package/dist/__tests__/pipeline/closingBoxOrder.test.d.ts +2 -0
  341. package/dist/__tests__/pipeline/closingBoxOrder.test.d.ts.map +1 -0
  342. package/dist/__tests__/pipeline/closingBoxOrder.test.js +87 -0
  343. package/dist/__tests__/pipeline/closingBoxOrder.test.js.map +1 -0
  344. package/dist/__tests__/pipeline/closingPageAfterFloat.test.d.ts +2 -0
  345. package/dist/__tests__/pipeline/closingPageAfterFloat.test.d.ts.map +1 -0
  346. package/dist/__tests__/pipeline/closingPageAfterFloat.test.js +159 -0
  347. package/dist/__tests__/pipeline/closingPageAfterFloat.test.js.map +1 -0
  348. package/dist/__tests__/pipeline/closingPageAfterFloatPage.test.d.ts +2 -0
  349. package/dist/__tests__/pipeline/closingPageAfterFloatPage.test.d.ts.map +1 -0
  350. package/dist/__tests__/pipeline/closingPageAfterFloatPage.test.js +90 -0
  351. package/dist/__tests__/pipeline/closingPageAfterFloatPage.test.js.map +1 -0
  352. package/dist/__tests__/pipeline/colonBalancing.test.js +19 -15
  353. package/dist/__tests__/pipeline/colonBalancing.test.js.map +1 -1
  354. package/dist/__tests__/pipeline/colonListRoom.test.d.ts +2 -0
  355. package/dist/__tests__/pipeline/colonListRoom.test.d.ts.map +1 -0
  356. package/dist/__tests__/pipeline/colonListRoom.test.js +127 -0
  357. package/dist/__tests__/pipeline/colonListRoom.test.js.map +1 -0
  358. package/dist/__tests__/pipeline/columnWidthRebreak.test.d.ts +2 -0
  359. package/dist/__tests__/pipeline/columnWidthRebreak.test.d.ts.map +1 -0
  360. package/dist/__tests__/pipeline/columnWidthRebreak.test.js +124 -0
  361. package/dist/__tests__/pipeline/columnWidthRebreak.test.js.map +1 -0
  362. package/dist/__tests__/pipeline/compoundBreaks.test.d.ts +2 -0
  363. package/dist/__tests__/pipeline/compoundBreaks.test.d.ts.map +1 -0
  364. package/dist/__tests__/pipeline/compoundBreaks.test.js +368 -0
  365. package/dist/__tests__/pipeline/compoundBreaks.test.js.map +1 -0
  366. package/dist/__tests__/pipeline/continuationUnderFloat.test.d.ts +2 -0
  367. package/dist/__tests__/pipeline/continuationUnderFloat.test.d.ts.map +1 -0
  368. package/dist/__tests__/pipeline/continuationUnderFloat.test.js +64 -0
  369. package/dist/__tests__/pipeline/continuationUnderFloat.test.js.map +1 -0
  370. package/dist/__tests__/pipeline/crossChapterRef.test.d.ts +2 -0
  371. package/dist/__tests__/pipeline/crossChapterRef.test.d.ts.map +1 -0
  372. package/dist/__tests__/pipeline/crossChapterRef.test.js +124 -0
  373. package/dist/__tests__/pipeline/crossChapterRef.test.js.map +1 -0
  374. package/dist/__tests__/pipeline/dashBreaks.test.d.ts +2 -0
  375. package/dist/__tests__/pipeline/dashBreaks.test.d.ts.map +1 -0
  376. package/dist/__tests__/pipeline/dashBreaks.test.js +358 -0
  377. package/dist/__tests__/pipeline/dashBreaks.test.js.map +1 -0
  378. package/dist/__tests__/pipeline/defaultOpenerPaint.test.d.ts +2 -0
  379. package/dist/__tests__/pipeline/defaultOpenerPaint.test.d.ts.map +1 -0
  380. package/dist/__tests__/pipeline/defaultOpenerPaint.test.js +128 -0
  381. package/dist/__tests__/pipeline/defaultOpenerPaint.test.js.map +1 -0
  382. package/dist/__tests__/pipeline/displayMathFlow.test.d.ts +2 -0
  383. package/dist/__tests__/pipeline/displayMathFlow.test.d.ts.map +1 -0
  384. package/dist/__tests__/pipeline/displayMathFlow.test.js +156 -0
  385. package/dist/__tests__/pipeline/displayMathFlow.test.js.map +1 -0
  386. package/dist/__tests__/pipeline/emptyResourceTemplate.test.d.ts +2 -0
  387. package/dist/__tests__/pipeline/emptyResourceTemplate.test.d.ts.map +1 -0
  388. package/dist/__tests__/pipeline/emptyResourceTemplate.test.js +66 -0
  389. package/dist/__tests__/pipeline/emptyResourceTemplate.test.js.map +1 -0
  390. package/dist/__tests__/pipeline/figureBodyAlign.test.d.ts +2 -0
  391. package/dist/__tests__/pipeline/figureBodyAlign.test.d.ts.map +1 -0
  392. package/dist/__tests__/pipeline/figureBodyAlign.test.js +92 -0
  393. package/dist/__tests__/pipeline/figureBodyAlign.test.js.map +1 -0
  394. package/dist/__tests__/pipeline/floatAfterCitingLine.test.d.ts +2 -0
  395. package/dist/__tests__/pipeline/floatAfterCitingLine.test.d.ts.map +1 -0
  396. package/dist/__tests__/pipeline/floatAfterCitingLine.test.js +217 -0
  397. package/dist/__tests__/pipeline/floatAfterCitingLine.test.js.map +1 -0
  398. package/dist/__tests__/pipeline/floatFirstSlot.test.js +15 -0
  399. package/dist/__tests__/pipeline/floatFirstSlot.test.js.map +1 -1
  400. package/dist/__tests__/pipeline/floatOverInlineResource.test.d.ts +2 -0
  401. package/dist/__tests__/pipeline/floatOverInlineResource.test.d.ts.map +1 -0
  402. package/dist/__tests__/pipeline/floatOverInlineResource.test.js +75 -0
  403. package/dist/__tests__/pipeline/floatOverInlineResource.test.js.map +1 -0
  404. package/dist/__tests__/pipeline/floatPlacementRules.test.d.ts +2 -0
  405. package/dist/__tests__/pipeline/floatPlacementRules.test.d.ts.map +1 -0
  406. package/dist/__tests__/pipeline/floatPlacementRules.test.js +177 -0
  407. package/dist/__tests__/pipeline/floatPlacementRules.test.js.map +1 -0
  408. package/dist/__tests__/pipeline/floatSlots.test.js +35 -1
  409. package/dist/__tests__/pipeline/floatSlots.test.js.map +1 -1
  410. package/dist/__tests__/pipeline/hardHyphenBreaks.test.d.ts +2 -0
  411. package/dist/__tests__/pipeline/hardHyphenBreaks.test.d.ts.map +1 -0
  412. package/dist/__tests__/pipeline/hardHyphenBreaks.test.js +165 -0
  413. package/dist/__tests__/pipeline/hardHyphenBreaks.test.js.map +1 -0
  414. package/dist/__tests__/pipeline/headingDesignCuts.test.d.ts +2 -0
  415. package/dist/__tests__/pipeline/headingDesignCuts.test.d.ts.map +1 -0
  416. package/dist/__tests__/pipeline/headingDesignCuts.test.js +96 -0
  417. package/dist/__tests__/pipeline/headingDesignCuts.test.js.map +1 -0
  418. package/dist/__tests__/pipeline/headingSnapPerLevel.test.d.ts +2 -0
  419. package/dist/__tests__/pipeline/headingSnapPerLevel.test.d.ts.map +1 -0
  420. package/dist/__tests__/pipeline/headingSnapPerLevel.test.js +97 -0
  421. package/dist/__tests__/pipeline/headingSnapPerLevel.test.js.map +1 -0
  422. package/dist/__tests__/pipeline/headingSplitOrphans.test.d.ts +2 -0
  423. package/dist/__tests__/pipeline/headingSplitOrphans.test.d.ts.map +1 -0
  424. package/dist/__tests__/pipeline/headingSplitOrphans.test.js +134 -0
  425. package/dist/__tests__/pipeline/headingSplitOrphans.test.js.map +1 -0
  426. package/dist/__tests__/pipeline/hyphenAcrossColumns.test.d.ts +2 -0
  427. package/dist/__tests__/pipeline/hyphenAcrossColumns.test.d.ts.map +1 -0
  428. package/dist/__tests__/pipeline/hyphenAcrossColumns.test.js +232 -0
  429. package/dist/__tests__/pipeline/hyphenAcrossColumns.test.js.map +1 -0
  430. package/dist/__tests__/pipeline/indentAfterOutOfFlow.test.d.ts +2 -0
  431. package/dist/__tests__/pipeline/indentAfterOutOfFlow.test.d.ts.map +1 -0
  432. package/dist/__tests__/pipeline/indentAfterOutOfFlow.test.js +93 -0
  433. package/dist/__tests__/pipeline/indentAfterOutOfFlow.test.js.map +1 -0
  434. package/dist/__tests__/pipeline/inlineFigureSpace.test.d.ts +2 -0
  435. package/dist/__tests__/pipeline/inlineFigureSpace.test.d.ts.map +1 -0
  436. package/dist/__tests__/pipeline/inlineFigureSpace.test.js +195 -0
  437. package/dist/__tests__/pipeline/inlineFigureSpace.test.js.map +1 -0
  438. package/dist/__tests__/pipeline/lineSourceEdges.test.d.ts +2 -0
  439. package/dist/__tests__/pipeline/lineSourceEdges.test.d.ts.map +1 -0
  440. package/dist/__tests__/pipeline/lineSourceEdges.test.js +143 -0
  441. package/dist/__tests__/pipeline/lineSourceEdges.test.js.map +1 -0
  442. package/dist/__tests__/pipeline/lineSourceRanges.test.d.ts +2 -0
  443. package/dist/__tests__/pipeline/lineSourceRanges.test.d.ts.map +1 -0
  444. package/dist/__tests__/pipeline/lineSourceRanges.test.js +96 -0
  445. package/dist/__tests__/pipeline/lineSourceRanges.test.js.map +1 -0
  446. package/dist/__tests__/pipeline/listTopSnap.test.d.ts +2 -0
  447. package/dist/__tests__/pipeline/listTopSnap.test.d.ts.map +1 -0
  448. package/dist/__tests__/pipeline/listTopSnap.test.js +90 -0
  449. package/dist/__tests__/pipeline/listTopSnap.test.js.map +1 -0
  450. package/dist/__tests__/pipeline/looseParagraphLimit.test.d.ts +2 -0
  451. package/dist/__tests__/pipeline/looseParagraphLimit.test.d.ts.map +1 -0
  452. package/dist/__tests__/pipeline/looseParagraphLimit.test.js +63 -0
  453. package/dist/__tests__/pipeline/looseParagraphLimit.test.js.map +1 -0
  454. package/dist/__tests__/pipeline/nestedListSpacing.test.d.ts +2 -0
  455. package/dist/__tests__/pipeline/nestedListSpacing.test.d.ts.map +1 -0
  456. package/dist/__tests__/pipeline/nestedListSpacing.test.js +62 -0
  457. package/dist/__tests__/pipeline/nestedListSpacing.test.js.map +1 -0
  458. package/dist/__tests__/pipeline/openerColumnStarts.test.d.ts +2 -0
  459. package/dist/__tests__/pipeline/openerColumnStarts.test.d.ts.map +1 -0
  460. package/dist/__tests__/pipeline/openerColumnStarts.test.js +189 -0
  461. package/dist/__tests__/pipeline/openerColumnStarts.test.js.map +1 -0
  462. package/dist/__tests__/pipeline/openerFillsPage.test.d.ts +2 -0
  463. package/dist/__tests__/pipeline/openerFillsPage.test.d.ts.map +1 -0
  464. package/dist/__tests__/pipeline/openerFillsPage.test.js +133 -0
  465. package/dist/__tests__/pipeline/openerFillsPage.test.js.map +1 -0
  466. package/dist/__tests__/pipeline/openerTallerThanColumn.test.d.ts +2 -0
  467. package/dist/__tests__/pipeline/openerTallerThanColumn.test.d.ts.map +1 -0
  468. package/dist/__tests__/pipeline/openerTallerThanColumn.test.js +139 -0
  469. package/dist/__tests__/pipeline/openerTallerThanColumn.test.js.map +1 -0
  470. package/dist/__tests__/pipeline/orderedNumberWidth.test.d.ts +2 -0
  471. package/dist/__tests__/pipeline/orderedNumberWidth.test.d.ts.map +1 -0
  472. package/dist/__tests__/pipeline/orderedNumberWidth.test.js +69 -0
  473. package/dist/__tests__/pipeline/orderedNumberWidth.test.js.map +1 -0
  474. package/dist/__tests__/pipeline/pageSpanHeadingWidth.test.d.ts +2 -0
  475. package/dist/__tests__/pipeline/pageSpanHeadingWidth.test.d.ts.map +1 -0
  476. package/dist/__tests__/pipeline/pageSpanHeadingWidth.test.js +74 -0
  477. package/dist/__tests__/pipeline/pageSpanHeadingWidth.test.js.map +1 -0
  478. package/dist/__tests__/pipeline/paragraphContainerTail.test.d.ts +2 -0
  479. package/dist/__tests__/pipeline/paragraphContainerTail.test.d.ts.map +1 -0
  480. package/dist/__tests__/pipeline/paragraphContainerTail.test.js +218 -0
  481. package/dist/__tests__/pipeline/paragraphContainerTail.test.js.map +1 -0
  482. package/dist/__tests__/pipeline/paragraphStyleFaces.test.d.ts +2 -0
  483. package/dist/__tests__/pipeline/paragraphStyleFaces.test.d.ts.map +1 -0
  484. package/dist/__tests__/pipeline/paragraphStyleFaces.test.js +121 -0
  485. package/dist/__tests__/pipeline/paragraphStyleFaces.test.js.map +1 -0
  486. package/dist/__tests__/pipeline/paragraphStyles.test.js +85 -0
  487. package/dist/__tests__/pipeline/paragraphStyles.test.js.map +1 -1
  488. package/dist/__tests__/pipeline/raggedOptimal.test.d.ts +2 -0
  489. package/dist/__tests__/pipeline/raggedOptimal.test.d.ts.map +1 -0
  490. package/dist/__tests__/pipeline/raggedOptimal.test.js +231 -0
  491. package/dist/__tests__/pipeline/raggedOptimal.test.js.map +1 -0
  492. package/dist/__tests__/pipeline/resolvedPaletteCopy.test.d.ts +2 -0
  493. package/dist/__tests__/pipeline/resolvedPaletteCopy.test.d.ts.map +1 -0
  494. package/dist/__tests__/pipeline/resolvedPaletteCopy.test.js +68 -0
  495. package/dist/__tests__/pipeline/resolvedPaletteCopy.test.js.map +1 -0
  496. package/dist/__tests__/pipeline/resourceNumberingRules.test.d.ts +2 -0
  497. package/dist/__tests__/pipeline/resourceNumberingRules.test.d.ts.map +1 -0
  498. package/dist/__tests__/pipeline/resourceNumberingRules.test.js +103 -0
  499. package/dist/__tests__/pipeline/resourceNumberingRules.test.js.map +1 -0
  500. package/dist/__tests__/pipeline/sectionPageOwnership.test.d.ts +2 -0
  501. package/dist/__tests__/pipeline/sectionPageOwnership.test.d.ts.map +1 -0
  502. package/dist/__tests__/pipeline/sectionPageOwnership.test.js +89 -0
  503. package/dist/__tests__/pipeline/sectionPageOwnership.test.js.map +1 -0
  504. package/dist/__tests__/pipeline/sectionPaletteSharedBase.test.d.ts +2 -0
  505. package/dist/__tests__/pipeline/sectionPaletteSharedBase.test.d.ts.map +1 -0
  506. package/dist/__tests__/pipeline/sectionPaletteSharedBase.test.js +278 -0
  507. package/dist/__tests__/pipeline/sectionPaletteSharedBase.test.js.map +1 -0
  508. package/dist/__tests__/pipeline/sectionPaletteTables.test.d.ts +2 -0
  509. package/dist/__tests__/pipeline/sectionPaletteTables.test.d.ts.map +1 -0
  510. package/dist/__tests__/pipeline/sectionPaletteTables.test.js +104 -0
  511. package/dist/__tests__/pipeline/sectionPaletteTables.test.js.map +1 -0
  512. package/dist/__tests__/pipeline/sideBoxAtColumnEnd.test.d.ts +2 -0
  513. package/dist/__tests__/pipeline/sideBoxAtColumnEnd.test.d.ts.map +1 -0
  514. package/dist/__tests__/pipeline/sideBoxAtColumnEnd.test.js +176 -0
  515. package/dist/__tests__/pipeline/sideBoxAtColumnEnd.test.js.map +1 -0
  516. package/dist/__tests__/pipeline/sideColumnPercent.test.d.ts +2 -0
  517. package/dist/__tests__/pipeline/sideColumnPercent.test.d.ts.map +1 -0
  518. package/dist/__tests__/pipeline/sideColumnPercent.test.js +114 -0
  519. package/dist/__tests__/pipeline/sideColumnPercent.test.js.map +1 -0
  520. package/dist/__tests__/pipeline/snippetDollarEscape.test.d.ts +2 -0
  521. package/dist/__tests__/pipeline/snippetDollarEscape.test.d.ts.map +1 -0
  522. package/dist/__tests__/pipeline/snippetDollarEscape.test.js +112 -0
  523. package/dist/__tests__/pipeline/snippetDollarEscape.test.js.map +1 -0
  524. package/dist/__tests__/pipeline/snippetLineBreaks.test.d.ts +2 -0
  525. package/dist/__tests__/pipeline/snippetLineBreaks.test.d.ts.map +1 -0
  526. package/dist/__tests__/pipeline/snippetLineBreaks.test.js +178 -0
  527. package/dist/__tests__/pipeline/snippetLineBreaks.test.js.map +1 -0
  528. package/dist/__tests__/pipeline/spanCutUnderColumnFloat.test.d.ts +2 -0
  529. package/dist/__tests__/pipeline/spanCutUnderColumnFloat.test.d.ts.map +1 -0
  530. package/dist/__tests__/pipeline/spanCutUnderColumnFloat.test.js +90 -0
  531. package/dist/__tests__/pipeline/spanCutUnderColumnFloat.test.js.map +1 -0
  532. package/dist/__tests__/pipeline/splitBoxCappedBand.test.d.ts +2 -0
  533. package/dist/__tests__/pipeline/splitBoxCappedBand.test.d.ts.map +1 -0
  534. package/dist/__tests__/pipeline/splitBoxCappedBand.test.js +64 -0
  535. package/dist/__tests__/pipeline/splitBoxCappedBand.test.js.map +1 -0
  536. package/dist/__tests__/pipeline/tableCellNoBreakSpaces.test.d.ts +2 -0
  537. package/dist/__tests__/pipeline/tableCellNoBreakSpaces.test.d.ts.map +1 -0
  538. package/dist/__tests__/pipeline/tableCellNoBreakSpaces.test.js +97 -0
  539. package/dist/__tests__/pipeline/tableCellNoBreakSpaces.test.js.map +1 -0
  540. package/dist/__tests__/pipeline/tableHeaderTracking.test.d.ts +2 -0
  541. package/dist/__tests__/pipeline/tableHeaderTracking.test.d.ts.map +1 -0
  542. package/dist/__tests__/pipeline/tableHeaderTracking.test.js +139 -0
  543. package/dist/__tests__/pipeline/tableHeaderTracking.test.js.map +1 -0
  544. package/dist/__tests__/pipeline/tableSplitTextRoom.test.d.ts +2 -0
  545. package/dist/__tests__/pipeline/tableSplitTextRoom.test.d.ts.map +1 -0
  546. package/dist/__tests__/pipeline/tableSplitTextRoom.test.js +90 -0
  547. package/dist/__tests__/pipeline/tableSplitTextRoom.test.js.map +1 -0
  548. package/dist/__tests__/pipeline/tableStyles.test.js +94 -1
  549. package/dist/__tests__/pipeline/tableStyles.test.js.map +1 -1
  550. package/dist/__tests__/pipeline/tallParagraphShortColumn.test.d.ts +2 -0
  551. package/dist/__tests__/pipeline/tallParagraphShortColumn.test.d.ts.map +1 -0
  552. package/dist/__tests__/pipeline/tallParagraphShortColumn.test.js +79 -0
  553. package/dist/__tests__/pipeline/tallParagraphShortColumn.test.js.map +1 -0
  554. package/dist/__tests__/pipeline/textFaces.test.d.ts +2 -0
  555. package/dist/__tests__/pipeline/textFaces.test.d.ts.map +1 -0
  556. package/dist/__tests__/pipeline/textFaces.test.js +258 -0
  557. package/dist/__tests__/pipeline/textFaces.test.js.map +1 -0
  558. package/dist/__tests__/pipeline/trailingBand.test.js +29 -0
  559. package/dist/__tests__/pipeline/trailingBand.test.js.map +1 -1
  560. package/dist/__tests__/pipeline/trailingCapHeading.test.d.ts +2 -0
  561. package/dist/__tests__/pipeline/trailingCapHeading.test.d.ts.map +1 -0
  562. package/dist/__tests__/pipeline/trailingCapHeading.test.js +69 -0
  563. package/dist/__tests__/pipeline/trailingCapHeading.test.js.map +1 -0
  564. package/dist/__tests__/pipeline/trailingCapOverflow.test.d.ts +2 -0
  565. package/dist/__tests__/pipeline/trailingCapOverflow.test.d.ts.map +1 -0
  566. package/dist/__tests__/pipeline/trailingCapOverflow.test.js +116 -0
  567. package/dist/__tests__/pipeline/trailingCapOverflow.test.js.map +1 -0
  568. package/dist/__tests__/placeholders.test.js +100 -2
  569. package/dist/__tests__/placeholders.test.js.map +1 -1
  570. package/dist/__tests__/punctuationGlue.test.d.ts +2 -0
  571. package/dist/__tests__/punctuationGlue.test.d.ts.map +1 -0
  572. package/dist/__tests__/punctuationGlue.test.js +165 -0
  573. package/dist/__tests__/punctuationGlue.test.js.map +1 -0
  574. package/dist/__tests__/raggedHyphenation.test.d.ts +2 -0
  575. package/dist/__tests__/raggedHyphenation.test.d.ts.map +1 -0
  576. package/dist/__tests__/raggedHyphenation.test.js +184 -0
  577. package/dist/__tests__/raggedHyphenation.test.js.map +1 -0
  578. package/dist/__tests__/renderWarnings.test.d.ts +2 -0
  579. package/dist/__tests__/renderWarnings.test.d.ts.map +1 -0
  580. package/dist/__tests__/renderWarnings.test.js +72 -0
  581. package/dist/__tests__/renderWarnings.test.js.map +1 -0
  582. package/dist/__tests__/resolvedLocale.test.d.ts +2 -0
  583. package/dist/__tests__/resolvedLocale.test.d.ts.map +1 -0
  584. package/dist/__tests__/resolvedLocale.test.js +51 -0
  585. package/dist/__tests__/resolvedLocale.test.js.map +1 -0
  586. package/dist/__tests__/runningChapter.test.d.ts +2 -0
  587. package/dist/__tests__/runningChapter.test.d.ts.map +1 -0
  588. package/dist/__tests__/runningChapter.test.js +161 -0
  589. package/dist/__tests__/runningChapter.test.js.map +1 -0
  590. package/dist/__tests__/runtFixStretchLimit.test.d.ts +2 -0
  591. package/dist/__tests__/runtFixStretchLimit.test.d.ts.map +1 -0
  592. package/dist/__tests__/runtFixStretchLimit.test.js +145 -0
  593. package/dist/__tests__/runtFixStretchLimit.test.js.map +1 -0
  594. package/dist/__tests__/scriptStacking.test.d.ts +2 -0
  595. package/dist/__tests__/scriptStacking.test.d.ts.map +1 -0
  596. package/dist/__tests__/scriptStacking.test.js +331 -0
  597. package/dist/__tests__/scriptStacking.test.js.map +1 -0
  598. package/dist/__tests__/sectionPaletteFlow.test.d.ts +2 -0
  599. package/dist/__tests__/sectionPaletteFlow.test.d.ts.map +1 -0
  600. package/dist/__tests__/sectionPaletteFlow.test.js +51 -0
  601. package/dist/__tests__/sectionPaletteFlow.test.js.map +1 -0
  602. package/dist/__tests__/singleInk.test.js +64 -2
  603. package/dist/__tests__/singleInk.test.js.map +1 -1
  604. package/dist/__tests__/singleInkRender.test.d.ts +2 -0
  605. package/dist/__tests__/singleInkRender.test.d.ts.map +1 -0
  606. package/dist/__tests__/singleInkRender.test.js +396 -0
  607. package/dist/__tests__/singleInkRender.test.js.map +1 -0
  608. package/dist/__tests__/spaceDirective.test.js +75 -0
  609. package/dist/__tests__/spaceDirective.test.js.map +1 -1
  610. package/dist/__tests__/table/model.test.js +124 -1
  611. package/dist/__tests__/table/model.test.js.map +1 -1
  612. package/dist/__tests__/tableFillSeams.test.d.ts +2 -0
  613. package/dist/__tests__/tableFillSeams.test.d.ts.map +1 -0
  614. package/dist/__tests__/tableFillSeams.test.js +180 -0
  615. package/dist/__tests__/tableFillSeams.test.js.map +1 -0
  616. package/dist/__tests__/toc.test.js +23 -2
  617. package/dist/__tests__/toc.test.js.map +1 -1
  618. package/dist/__tests__/tocLeaderKerning.test.d.ts +2 -0
  619. package/dist/__tests__/tocLeaderKerning.test.d.ts.map +1 -0
  620. package/dist/__tests__/tocLeaderKerning.test.js +83 -0
  621. package/dist/__tests__/tocLeaderKerning.test.js.map +1 -0
  622. package/dist/__tests__/tocNumberBaseline.test.d.ts +2 -0
  623. package/dist/__tests__/tocNumberBaseline.test.d.ts.map +1 -0
  624. package/dist/__tests__/tocNumberBaseline.test.js +90 -0
  625. package/dist/__tests__/tocNumberBaseline.test.js.map +1 -0
  626. package/dist/__tests__/tocPartsHeight.test.d.ts +2 -0
  627. package/dist/__tests__/tocPartsHeight.test.d.ts.map +1 -0
  628. package/dist/__tests__/tocPartsHeight.test.js +41 -0
  629. package/dist/__tests__/tocPartsHeight.test.js.map +1 -0
  630. package/dist/__tests__/trackedLineAlign.test.d.ts +2 -0
  631. package/dist/__tests__/trackedLineAlign.test.d.ts.map +1 -0
  632. package/dist/__tests__/trackedLineAlign.test.js +96 -0
  633. package/dist/__tests__/trackedLineAlign.test.js.map +1 -0
  634. package/dist/bundle/adapters.d.ts +10 -3
  635. package/dist/bundle/adapters.d.ts.map +1 -1
  636. package/dist/bundle/adapters.js +13 -5
  637. package/dist/bundle/adapters.js.map +1 -1
  638. package/dist/bundle/api.d.ts +32 -0
  639. package/dist/bundle/api.d.ts.map +1 -1
  640. package/dist/bundle/api.js +12 -2
  641. package/dist/bundle/api.js.map +1 -1
  642. package/dist/bundle/book.d.ts +6 -1
  643. package/dist/bundle/book.d.ts.map +1 -1
  644. package/dist/bundle/book.js +89 -17
  645. package/dist/bundle/book.js.map +1 -1
  646. package/dist/bundle/codec.d.ts +87 -3
  647. package/dist/bundle/codec.d.ts.map +1 -1
  648. package/dist/bundle/codec.js +193 -13
  649. package/dist/bundle/codec.js.map +1 -1
  650. package/dist/bundle/configVersion.d.ts +295 -0
  651. package/dist/bundle/configVersion.d.ts.map +1 -0
  652. package/dist/bundle/configVersion.js +788 -0
  653. package/dist/bundle/configVersion.js.map +1 -0
  654. package/dist/bundle/index.d.ts +6 -4
  655. package/dist/bundle/index.d.ts.map +1 -1
  656. package/dist/bundle/index.js +2 -1
  657. package/dist/bundle/index.js.map +1 -1
  658. package/dist/bundle/manifest.d.ts +19 -5
  659. package/dist/bundle/manifest.d.ts.map +1 -1
  660. package/dist/bundle/manifest.js +53 -21
  661. package/dist/bundle/manifest.js.map +1 -1
  662. package/dist/bundle/types.d.ts +19 -0
  663. package/dist/bundle/types.d.ts.map +1 -1
  664. package/dist/bundle/zip.d.ts +14 -1
  665. package/dist/bundle/zip.d.ts.map +1 -1
  666. package/dist/bundle/zip.js +13 -2
  667. package/dist/bundle/zip.js.map +1 -1
  668. package/dist/canvas-backend/blockRender.d.ts +3 -1
  669. package/dist/canvas-backend/blockRender.d.ts.map +1 -1
  670. package/dist/canvas-backend/blockRender.js +27 -17
  671. package/dist/canvas-backend/blockRender.js.map +1 -1
  672. package/dist/canvas-backend/decorations.d.ts.map +1 -1
  673. package/dist/canvas-backend/decorations.js +6 -36
  674. package/dist/canvas-backend/decorations.js.map +1 -1
  675. package/dist/canvas-backend/headerFooter.d.ts +3 -1
  676. package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
  677. package/dist/canvas-backend/headerFooter.js +85 -22
  678. package/dist/canvas-backend/headerFooter.js.map +1 -1
  679. package/dist/canvas-backend/index.d.ts +17 -3
  680. package/dist/canvas-backend/index.d.ts.map +1 -1
  681. package/dist/canvas-backend/index.js +75 -14
  682. package/dist/canvas-backend/index.js.map +1 -1
  683. package/dist/canvas-backend/renderResourceBlock.d.ts +45 -5
  684. package/dist/canvas-backend/renderResourceBlock.d.ts.map +1 -1
  685. package/dist/canvas-backend/renderResourceBlock.js +133 -22
  686. package/dist/canvas-backend/renderResourceBlock.js.map +1 -1
  687. package/dist/columnClip.d.ts +13 -2
  688. package/dist/columnClip.d.ts.map +1 -1
  689. package/dist/columnClip.js +37 -4
  690. package/dist/columnClip.js.map +1 -1
  691. package/dist/columnRule.d.ts +7 -2
  692. package/dist/columnRule.d.ts.map +1 -1
  693. package/dist/columnRule.js +27 -2
  694. package/dist/columnRule.js.map +1 -1
  695. package/dist/configWarnings.d.ts +26 -0
  696. package/dist/configWarnings.d.ts.map +1 -0
  697. package/dist/configWarnings.js +223 -0
  698. package/dist/configWarnings.js.map +1 -0
  699. package/dist/createLayout.d.ts +16 -1
  700. package/dist/createLayout.d.ts.map +1 -1
  701. package/dist/createLayout.js +25 -22
  702. package/dist/createLayout.js.map +1 -1
  703. package/dist/cropMarks.d.ts +28 -0
  704. package/dist/cropMarks.d.ts.map +1 -0
  705. package/dist/cropMarks.js +40 -0
  706. package/dist/cropMarks.js.map +1 -0
  707. package/dist/defaults/bodyText.d.ts +12 -2
  708. package/dist/defaults/bodyText.d.ts.map +1 -1
  709. package/dist/defaults/bodyText.js +132 -7
  710. package/dist/defaults/bodyText.js.map +1 -1
  711. package/dist/defaults/calloutStyles.d.ts +13 -2
  712. package/dist/defaults/calloutStyles.d.ts.map +1 -1
  713. package/dist/defaults/calloutStyles.js +64 -4
  714. package/dist/defaults/calloutStyles.js.map +1 -1
  715. package/dist/defaults/chipStyles.d.ts +4 -3
  716. package/dist/defaults/chipStyles.d.ts.map +1 -1
  717. package/dist/defaults/chipStyles.js +11 -3
  718. package/dist/defaults/chipStyles.js.map +1 -1
  719. package/dist/defaults/headerFooter.d.ts +11 -1
  720. package/dist/defaults/headerFooter.d.ts.map +1 -1
  721. package/dist/defaults/headerFooter.js +52 -4
  722. package/dist/defaults/headerFooter.js.map +1 -1
  723. package/dist/defaults/headingStyles.d.ts +7 -3
  724. package/dist/defaults/headingStyles.d.ts.map +1 -1
  725. package/dist/defaults/headingStyles.js +34 -6
  726. package/dist/defaults/headingStyles.js.map +1 -1
  727. package/dist/defaults/headings.d.ts +10 -2
  728. package/dist/defaults/headings.d.ts.map +1 -1
  729. package/dist/defaults/headings.js +79 -16
  730. package/dist/defaults/headings.js.map +1 -1
  731. package/dist/defaults/index.d.ts +1 -1
  732. package/dist/defaults/index.d.ts.map +1 -1
  733. package/dist/defaults/index.js +1 -1
  734. package/dist/defaults/index.js.map +1 -1
  735. package/dist/defaults/layout.d.ts.map +1 -1
  736. package/dist/defaults/layout.js +27 -0
  737. package/dist/defaults/layout.js.map +1 -1
  738. package/dist/defaults/lists-shared.d.ts +2 -0
  739. package/dist/defaults/lists-shared.d.ts.map +1 -1
  740. package/dist/defaults/lists-shared.js +2 -0
  741. package/dist/defaults/lists-shared.js.map +1 -1
  742. package/dist/defaults/math.d.ts.map +1 -1
  743. package/dist/defaults/math.js +12 -0
  744. package/dist/defaults/math.js.map +1 -1
  745. package/dist/defaults/orderedLists.d.ts +7 -1
  746. package/dist/defaults/orderedLists.d.ts.map +1 -1
  747. package/dist/defaults/orderedLists.js +30 -4
  748. package/dist/defaults/orderedLists.js.map +1 -1
  749. package/dist/defaults/page.d.ts.map +1 -1
  750. package/dist/defaults/page.js +7 -2
  751. package/dist/defaults/page.js.map +1 -1
  752. package/dist/defaults/paragraphStyles.d.ts +2 -1
  753. package/dist/defaults/paragraphStyles.d.ts.map +1 -1
  754. package/dist/defaults/paragraphStyles.js +26 -1
  755. package/dist/defaults/paragraphStyles.js.map +1 -1
  756. package/dist/defaults/resourceTypes.d.ts +5 -1
  757. package/dist/defaults/resourceTypes.d.ts.map +1 -1
  758. package/dist/defaults/resourceTypes.js +37 -6
  759. package/dist/defaults/resourceTypes.js.map +1 -1
  760. package/dist/defaults/shared.d.ts +10 -0
  761. package/dist/defaults/shared.d.ts.map +1 -1
  762. package/dist/defaults/shared.js +79 -0
  763. package/dist/defaults/shared.js.map +1 -1
  764. package/dist/defaults/tableStyle.d.ts +1 -1
  765. package/dist/defaults/tableStyle.d.ts.map +1 -1
  766. package/dist/defaults/tableStyle.js +40 -6
  767. package/dist/defaults/tableStyle.js.map +1 -1
  768. package/dist/defaults/toc.d.ts +2 -1
  769. package/dist/defaults/toc.d.ts.map +1 -1
  770. package/dist/defaults/toc.js +2 -1
  771. package/dist/defaults/toc.js.map +1 -1
  772. package/dist/defaults/unorderedLists.d.ts +1 -0
  773. package/dist/defaults/unorderedLists.d.ts.map +1 -1
  774. package/dist/defaults/unorderedLists.js +7 -1
  775. package/dist/defaults/unorderedLists.js.map +1 -1
  776. package/dist/design/layout.d.ts +41 -3
  777. package/dist/design/layout.d.ts.map +1 -1
  778. package/dist/design/layout.js +322 -90
  779. package/dist/design/layout.js.map +1 -1
  780. package/dist/design/placeholders.d.ts +39 -4
  781. package/dist/design/placeholders.d.ts.map +1 -1
  782. package/dist/design/placeholders.js +61 -11
  783. package/dist/design/placeholders.js.map +1 -1
  784. package/dist/design/richText.d.ts +110 -0
  785. package/dist/design/richText.d.ts.map +1 -0
  786. package/dist/design/richText.js +458 -0
  787. package/dist/design/richText.js.map +1 -0
  788. package/dist/frontmatter.d.ts +14 -0
  789. package/dist/frontmatter.d.ts.map +1 -1
  790. package/dist/frontmatter.js +61 -0
  791. package/dist/frontmatter.js.map +1 -1
  792. package/dist/html-backend.d.ts +60 -2
  793. package/dist/html-backend.d.ts.map +1 -1
  794. package/dist/html-backend.js +317 -62
  795. package/dist/html-backend.js.map +1 -1
  796. package/dist/hyphenate.d.ts +30 -4
  797. package/dist/hyphenate.d.ts.map +1 -1
  798. package/dist/hyphenate.js +71 -5
  799. package/dist/hyphenate.js.map +1 -1
  800. package/dist/index.d.ts +28 -19
  801. package/dist/index.d.ts.map +1 -1
  802. package/dist/index.js +17 -11
  803. package/dist/index.js.map +1 -1
  804. package/dist/knuthPlass/breakpoints.d.ts +21 -0
  805. package/dist/knuthPlass/breakpoints.d.ts.map +1 -1
  806. package/dist/knuthPlass/breakpoints.js +205 -14
  807. package/dist/knuthPlass/breakpoints.js.map +1 -1
  808. package/dist/knuthPlass/constants.d.ts +15 -0
  809. package/dist/knuthPlass/constants.d.ts.map +1 -1
  810. package/dist/knuthPlass/constants.js +15 -0
  811. package/dist/knuthPlass/constants.js.map +1 -1
  812. package/dist/knuthPlass/pretextAdapter.d.ts +23 -2
  813. package/dist/knuthPlass/pretextAdapter.d.ts.map +1 -1
  814. package/dist/knuthPlass/pretextAdapter.js +95 -9
  815. package/dist/knuthPlass/pretextAdapter.js.map +1 -1
  816. package/dist/knuthPlass/richAdapter.d.ts +26 -2
  817. package/dist/knuthPlass/richAdapter.d.ts.map +1 -1
  818. package/dist/knuthPlass/richAdapter.js +79 -18
  819. package/dist/knuthPlass/richAdapter.js.map +1 -1
  820. package/dist/knuthPlass/tracking.d.ts +24 -0
  821. package/dist/knuthPlass/tracking.d.ts.map +1 -0
  822. package/dist/knuthPlass/tracking.js +77 -0
  823. package/dist/knuthPlass/tracking.js.map +1 -0
  824. package/dist/knuthPlass/types.d.ts +66 -4
  825. package/dist/knuthPlass/types.d.ts.map +1 -1
  826. package/dist/lineInk.d.ts +12 -0
  827. package/dist/lineInk.d.ts.map +1 -0
  828. package/dist/lineInk.js +20 -0
  829. package/dist/lineInk.js.map +1 -0
  830. package/dist/locale.d.ts +26 -0
  831. package/dist/locale.d.ts.map +1 -0
  832. package/dist/locale.js +63 -0
  833. package/dist/locale.js.map +1 -0
  834. package/dist/looseLines.d.ts +44 -0
  835. package/dist/looseLines.d.ts.map +1 -0
  836. package/dist/looseLines.js +46 -0
  837. package/dist/looseLines.js.map +1 -0
  838. package/dist/math/THIRD_PARTY_LICENSES.txt +221 -0
  839. package/dist/math/engine.d.ts +24 -0
  840. package/dist/math/engine.d.ts.map +1 -1
  841. package/dist/math/engine.js +252 -83
  842. package/dist/math/engine.js.map +1 -1
  843. package/dist/math/index.d.ts +1 -1
  844. package/dist/math/index.d.ts.map +1 -1
  845. package/dist/math/index.js +1 -1
  846. package/dist/math/index.js.map +1 -1
  847. package/dist/math/mathjax.d.ts +20 -0
  848. package/dist/math/mathjax.d.ts.map +1 -0
  849. package/dist/math/mathjax.js +29 -0
  850. package/dist/measure/breakRules.d.ts +50 -0
  851. package/dist/measure/breakRules.d.ts.map +1 -0
  852. package/dist/measure/breakRules.js +116 -0
  853. package/dist/measure/breakRules.js.map +1 -0
  854. package/dist/measure/cache.d.ts.map +1 -1
  855. package/dist/measure/cache.js +26 -5
  856. package/dist/measure/cache.js.map +1 -1
  857. package/dist/measure/cjk.d.ts +19 -0
  858. package/dist/measure/cjk.d.ts.map +1 -0
  859. package/dist/measure/cjk.js +70 -0
  860. package/dist/measure/cjk.js.map +1 -0
  861. package/dist/measure/font.d.ts +21 -5
  862. package/dist/measure/font.d.ts.map +1 -1
  863. package/dist/measure/font.js +61 -4
  864. package/dist/measure/font.js.map +1 -1
  865. package/dist/measure/index.d.ts +16 -2
  866. package/dist/measure/index.d.ts.map +1 -1
  867. package/dist/measure/index.js +61 -1
  868. package/dist/measure/index.js.map +1 -1
  869. package/dist/measure/links.d.ts +15 -0
  870. package/dist/measure/links.d.ts.map +1 -0
  871. package/dist/measure/links.js +115 -0
  872. package/dist/measure/links.js.map +1 -0
  873. package/dist/measure/plain.d.ts +10 -2
  874. package/dist/measure/plain.d.ts.map +1 -1
  875. package/dist/measure/plain.js +175 -25
  876. package/dist/measure/plain.js.map +1 -1
  877. package/dist/measure/rich.d.ts +86 -6
  878. package/dist/measure/rich.d.ts.map +1 -1
  879. package/dist/measure/rich.js +808 -131
  880. package/dist/measure/rich.js.map +1 -1
  881. package/dist/measure/spaces.d.ts +34 -0
  882. package/dist/measure/spaces.d.ts.map +1 -0
  883. package/dist/measure/spaces.js +42 -0
  884. package/dist/measure/spaces.js.map +1 -0
  885. package/dist/measure/types.d.ts +99 -0
  886. package/dist/measure/types.d.ts.map +1 -1
  887. package/dist/measure/types.js +19 -0
  888. package/dist/measure/types.js.map +1 -1
  889. package/dist/numberWords.d.ts +22 -0
  890. package/dist/numberWords.d.ts.map +1 -0
  891. package/dist/numberWords.js +155 -0
  892. package/dist/numberWords.js.map +1 -0
  893. package/dist/numbering.d.ts +52 -3
  894. package/dist/numbering.d.ts.map +1 -1
  895. package/dist/numbering.js +116 -16
  896. package/dist/numbering.js.map +1 -1
  897. package/dist/parse/blockParser.d.ts.map +1 -1
  898. package/dist/parse/blockParser.js +54 -7
  899. package/dist/parse/blockParser.js.map +1 -1
  900. package/dist/parse/index.d.ts +1 -1
  901. package/dist/parse/index.d.ts.map +1 -1
  902. package/dist/parse/index.js.map +1 -1
  903. package/dist/parse/injectSpans.d.ts +3 -1
  904. package/dist/parse/injectSpans.d.ts.map +1 -1
  905. package/dist/parse/injectSpans.js +8 -4
  906. package/dist/parse/injectSpans.js.map +1 -1
  907. package/dist/parse/inlineFormatting.d.ts +50 -2
  908. package/dist/parse/inlineFormatting.d.ts.map +1 -1
  909. package/dist/parse/inlineFormatting.js +441 -26
  910. package/dist/parse/inlineFormatting.js.map +1 -1
  911. package/dist/parse/inlineSnippet.d.ts +12 -3
  912. package/dist/parse/inlineSnippet.d.ts.map +1 -1
  913. package/dist/parse/inlineSnippet.js +10 -3
  914. package/dist/parse/inlineSnippet.js.map +1 -1
  915. package/dist/parse/links.d.ts +9 -0
  916. package/dist/parse/links.d.ts.map +1 -0
  917. package/dist/parse/links.js +23 -0
  918. package/dist/parse/links.js.map +1 -0
  919. package/dist/parse/sourceMapping.d.ts.map +1 -1
  920. package/dist/parse/sourceMapping.js +68 -7
  921. package/dist/parse/sourceMapping.js.map +1 -1
  922. package/dist/parse/types.d.ts +32 -0
  923. package/dist/parse/types.d.ts.map +1 -1
  924. package/dist/pipeline/bandCaps.d.ts +26 -5
  925. package/dist/pipeline/bandCaps.d.ts.map +1 -1
  926. package/dist/pipeline/bandCaps.js +47 -20
  927. package/dist/pipeline/bandCaps.js.map +1 -1
  928. package/dist/pipeline/build.d.ts.map +1 -1
  929. package/dist/pipeline/build.js +1417 -172
  930. package/dist/pipeline/build.js.map +1 -1
  931. package/dist/pipeline/buildBlockKind.d.ts +4 -0
  932. package/dist/pipeline/buildBlockKind.d.ts.map +1 -1
  933. package/dist/pipeline/buildBlockKind.js +38 -7
  934. package/dist/pipeline/buildBlockKind.js.map +1 -1
  935. package/dist/pipeline/buildHelpers.d.ts +5 -2
  936. package/dist/pipeline/buildHelpers.d.ts.map +1 -1
  937. package/dist/pipeline/buildHelpers.js +101 -25
  938. package/dist/pipeline/buildHelpers.js.map +1 -1
  939. package/dist/pipeline/buildMeasurement.d.ts.map +1 -1
  940. package/dist/pipeline/buildMeasurement.js +6 -2
  941. package/dist/pipeline/buildMeasurement.js.map +1 -1
  942. package/dist/pipeline/calloutLayout.d.ts +34 -7
  943. package/dist/pipeline/calloutLayout.d.ts.map +1 -1
  944. package/dist/pipeline/calloutLayout.js +331 -44
  945. package/dist/pipeline/calloutLayout.js.map +1 -1
  946. package/dist/pipeline/chips.d.ts.map +1 -1
  947. package/dist/pipeline/chips.js +3 -0
  948. package/dist/pipeline/chips.js.map +1 -1
  949. package/dist/pipeline/columnBalancing.d.ts +26 -6
  950. package/dist/pipeline/columnBalancing.d.ts.map +1 -1
  951. package/dist/pipeline/columnBalancing.js +82 -21
  952. package/dist/pipeline/columnBalancing.js.map +1 -1
  953. package/dist/pipeline/config.d.ts +18 -0
  954. package/dist/pipeline/config.d.ts.map +1 -1
  955. package/dist/pipeline/config.js +44 -7
  956. package/dist/pipeline/config.js.map +1 -1
  957. package/dist/pipeline/contentWarnings.d.ts +50 -0
  958. package/dist/pipeline/contentWarnings.d.ts.map +1 -0
  959. package/dist/pipeline/contentWarnings.js +362 -0
  960. package/dist/pipeline/contentWarnings.js.map +1 -0
  961. package/dist/pipeline/continuation.d.ts.map +1 -1
  962. package/dist/pipeline/continuation.js +25 -5
  963. package/dist/pipeline/continuation.js.map +1 -1
  964. package/dist/pipeline/floatPlacement.d.ts +16 -7
  965. package/dist/pipeline/floatPlacement.d.ts.map +1 -1
  966. package/dist/pipeline/floatPlacement.js +22 -5
  967. package/dist/pipeline/floatPlacement.js.map +1 -1
  968. package/dist/pipeline/floatSlots.d.ts +30 -4
  969. package/dist/pipeline/floatSlots.d.ts.map +1 -1
  970. package/dist/pipeline/floatSlots.js +42 -7
  971. package/dist/pipeline/floatSlots.js.map +1 -1
  972. package/dist/pipeline/headerFooter.d.ts +125 -11
  973. package/dist/pipeline/headerFooter.d.ts.map +1 -1
  974. package/dist/pipeline/headerFooter.js +444 -69
  975. package/dist/pipeline/headerFooter.js.map +1 -1
  976. package/dist/pipeline/headingDesignCuts.d.ts +40 -0
  977. package/dist/pipeline/headingDesignCuts.d.ts.map +1 -0
  978. package/dist/pipeline/headingDesignCuts.js +72 -0
  979. package/dist/pipeline/headingDesignCuts.js.map +1 -0
  980. package/dist/pipeline/headingStyles.d.ts +12 -0
  981. package/dist/pipeline/headingStyles.d.ts.map +1 -1
  982. package/dist/pipeline/headingStyles.js +45 -1
  983. package/dist/pipeline/headingStyles.js.map +1 -1
  984. package/dist/pipeline/lists.d.ts +33 -1
  985. package/dist/pipeline/lists.d.ts.map +1 -1
  986. package/dist/pipeline/lists.js +53 -2
  987. package/dist/pipeline/lists.js.map +1 -1
  988. package/dist/pipeline/measureContentBlock.d.ts +25 -1
  989. package/dist/pipeline/measureContentBlock.d.ts.map +1 -1
  990. package/dist/pipeline/measureContentBlock.js +137 -17
  991. package/dist/pipeline/measureContentBlock.js.map +1 -1
  992. package/dist/pipeline/outline.d.ts +10 -5
  993. package/dist/pipeline/outline.d.ts.map +1 -1
  994. package/dist/pipeline/outline.js +38 -14
  995. package/dist/pipeline/outline.js.map +1 -1
  996. package/dist/pipeline/paragraphContainers.d.ts +13 -4
  997. package/dist/pipeline/paragraphContainers.d.ts.map +1 -1
  998. package/dist/pipeline/paragraphContainers.js +4 -3
  999. package/dist/pipeline/paragraphContainers.js.map +1 -1
  1000. package/dist/pipeline/partPalette.d.ts +49 -3
  1001. package/dist/pipeline/partPalette.d.ts.map +1 -1
  1002. package/dist/pipeline/partPalette.js +414 -46
  1003. package/dist/pipeline/partPalette.js.map +1 -1
  1004. package/dist/pipeline/parts.d.ts +5 -1
  1005. package/dist/pipeline/parts.d.ts.map +1 -1
  1006. package/dist/pipeline/parts.js +16 -0
  1007. package/dist/pipeline/parts.js.map +1 -1
  1008. package/dist/pipeline/placeholders.d.ts +152 -3
  1009. package/dist/pipeline/placeholders.d.ts.map +1 -1
  1010. package/dist/pipeline/placeholders.js +259 -33
  1011. package/dist/pipeline/placeholders.js.map +1 -1
  1012. package/dist/pipeline/placement.d.ts +6 -1
  1013. package/dist/pipeline/placement.d.ts.map +1 -1
  1014. package/dist/pipeline/placement.js +13 -2
  1015. package/dist/pipeline/placement.js.map +1 -1
  1016. package/dist/pipeline/raggedLines.d.ts +5 -0
  1017. package/dist/pipeline/raggedLines.d.ts.map +1 -1
  1018. package/dist/pipeline/raggedLines.js +24 -3
  1019. package/dist/pipeline/raggedLines.js.map +1 -1
  1020. package/dist/pipeline/resourceLayout.d.ts +6 -4
  1021. package/dist/pipeline/resourceLayout.d.ts.map +1 -1
  1022. package/dist/pipeline/resourceLayout.js +137 -36
  1023. package/dist/pipeline/resourceLayout.js.map +1 -1
  1024. package/dist/pipeline/resourceNumbering.d.ts.map +1 -1
  1025. package/dist/pipeline/resourceNumbering.js +5 -15
  1026. package/dist/pipeline/resourceNumbering.js.map +1 -1
  1027. package/dist/pipeline/styles.d.ts +38 -5
  1028. package/dist/pipeline/styles.d.ts.map +1 -1
  1029. package/dist/pipeline/styles.js +99 -46
  1030. package/dist/pipeline/styles.js.map +1 -1
  1031. package/dist/pipeline/toc.d.ts.map +1 -1
  1032. package/dist/pipeline/toc.js +41 -5
  1033. package/dist/pipeline/toc.js.map +1 -1
  1034. package/dist/react/createLayout.d.ts +20 -0
  1035. package/dist/react/createLayout.d.ts.map +1 -0
  1036. package/dist/react/createLayout.js +50 -0
  1037. package/dist/react/createLayout.js.map +1 -0
  1038. package/dist/react/index.d.ts +3 -0
  1039. package/dist/react/index.d.ts.map +1 -0
  1040. package/dist/react/index.js +4 -0
  1041. package/dist/react/index.js.map +1 -0
  1042. package/dist/svg/singleInk.d.ts +46 -1
  1043. package/dist/svg/singleInk.d.ts.map +1 -1
  1044. package/dist/svg/singleInk.js +180 -10
  1045. package/dist/svg/singleInk.js.map +1 -1
  1046. package/dist/table/model.d.ts +36 -1
  1047. package/dist/table/model.d.ts.map +1 -1
  1048. package/dist/table/model.js +163 -20
  1049. package/dist/table/model.js.map +1 -1
  1050. package/dist/types.d.ts +979 -68
  1051. package/dist/types.d.ts.map +1 -1
  1052. package/dist/vdt.d.ts +439 -13
  1053. package/dist/vdt.d.ts.map +1 -1
  1054. package/dist/vdt.js +91 -0
  1055. package/dist/vdt.js.map +1 -1
  1056. package/dist/worker/client.d.ts +15 -1
  1057. package/dist/worker/client.d.ts.map +1 -1
  1058. package/dist/worker/client.js +52 -3
  1059. package/dist/worker/client.js.map +1 -1
  1060. package/dist/worker/entryUrl.d.ts +15 -0
  1061. package/dist/worker/entryUrl.d.ts.map +1 -0
  1062. package/dist/worker/entryUrl.js +33 -0
  1063. package/dist/worker/entryUrl.js.map +1 -0
  1064. package/dist/worker/fonts.d.ts +18 -0
  1065. package/dist/worker/fonts.d.ts.map +1 -0
  1066. package/dist/worker/fonts.js +53 -0
  1067. package/dist/worker/fonts.js.map +1 -0
  1068. package/dist/worker/layout.worker.js +41 -6
  1069. package/dist/worker/layout.worker.js.map +1 -1
  1070. package/dist/worker/protocol.d.ts +4 -0
  1071. package/dist/worker/protocol.d.ts.map +1 -1
  1072. package/package.json +12 -5
@@ -1,12 +1,22 @@
1
1
  import { createBoundingBox } from '../vdt';
2
- import { hyphenateText } from '../hyphenate';
2
+ import { hyphenateText, withoutSlashJoints } from '../hyphenate';
3
3
  import { richTokensToItems, computeBreakpoints, reconstructRichLines, } from '../knuthPlass';
4
4
  import { SOFT_HYPHEN } from './types';
5
+ import { lineMeasure, uniformMeasureFrom } from './types';
5
6
  import { cleanSoftHyphens, measureTextWidth, normalSpaceWidthFor } from './canvas';
6
7
  import { isRuntLastLine } from './runts';
7
- import { computeJustifiedSpaceRatio } from './plain';
8
+ import { computeJustifiedSpaceRatio, hasOverfullLine } from './plain';
8
9
  import { quoteFamily } from './font';
9
10
  import { trimChipLineEdges } from './chipEdges';
11
+ import { cjkBreakIndices, cjkJoinBreaks, hasCJK, hasCJKRun } from './cjk';
12
+ import { NO_BREAK_SPACES, WORDS_AND_SPACES_RE, isBlankText, isBreakingSpace, isBreakingSpaceRun } from './spaces';
13
+ import { breaksAfterDash, breaksAfterHardHyphen, hasCompound, isDash, raggedStretchPx } from './breakRules';
14
+ /** Whether a resolved swatch colour can fill the square: a six- or
15
+ * eight-digit hex (`#rrggbb`, `#rrggbbaa`) or an `rgb()` / `rgba()`
16
+ * colour. Anything else leaves the swatch an empty outline. */
17
+ export function isSwatchFill(color) {
18
+ return /^#(?:[0-9a-f]{6}|[0-9a-f]{8})$/i.test(color) || /^rgba?\([^()]*\)$/i.test(color);
19
+ }
10
20
  /** Side of an inline colour swatch: three quarters of the font size (the
11
21
  * height of a capital), read from the `px` size of the CSS font string. */
12
22
  export function swatchSidePx(font) {
@@ -24,28 +34,170 @@ function pickSpanFont(bold, italic, normalFont, boldFont, italicFont, boldItalic
24
34
  return normalFont;
25
35
  }
26
36
  /** Superscripts and subscripts are set at this fraction of the text size
27
- * and shifted off the baseline by this fraction of it (up for a
28
- * superscript, down for a subscript) — the compositor's defaults. */
37
+ * (the compositor's default). */
29
38
  export const SCRIPT_SIZE_RATIO = 0.583;
30
- export const SCRIPT_SHIFT_RATIO = 0.333;
39
+ /** A superscript rises this fraction of the text size: a third of an em,
40
+ * as browsers raise `vertical-align: super`. */
41
+ export const SUPERSCRIPT_SHIFT_RATIO = 0.333;
42
+ /** A subscript drops this fraction of the text size (EF-80): 0.15 em, the
43
+ * drop TeX gives a subscript alone (σ16 of its text fonts, MathJax's
44
+ * `$T_0$`), which keeps a figure inside the descender line. It used to
45
+ * drop as far as a superscript rises, and hung below the descenders. */
46
+ export const SUBSCRIPT_SHIFT_RATIO = 0.15;
47
+ /** A subscript stacked under a superscript (`T~0~^2^`) drops this fraction
48
+ * of the text size instead: 0.25 em, TeX's drop for a subscript with a
49
+ * superscript over it (σ17, 0.247 em), which clears room between the two. */
50
+ export const STACKED_SUBSCRIPT_SHIFT_RATIO = 0.25;
31
51
  const FONT_SIZE_RE = /(\d*\.?\d+)px/;
32
52
  /** The font a script token is measured and painted with (`font` at the
33
- * script size) and its baseline shift in px. */
34
- export function scriptMetrics(font, script) {
53
+ * script size) and its baseline shift in px (negative: up). `stacked`: a
54
+ * subscript with a superscript set over it, which drops further. */
55
+ export function scriptMetrics(font, script, stacked = false) {
35
56
  const m = FONT_SIZE_RE.exec(font);
36
57
  const size = m ? parseFloat(m[1]) : 0;
37
58
  const scaled = m ? font.replace(FONT_SIZE_RE, `${size * SCRIPT_SIZE_RATIO}px`) : font;
38
- return { font: scaled, baselineShift: (script === 'sup' ? -1 : 1) * size * SCRIPT_SHIFT_RATIO };
59
+ const ratio = script === 'sup'
60
+ ? -SUPERSCRIPT_SHIFT_RATIO
61
+ : stacked ? STACKED_SUBSCRIPT_SHIFT_RATIO : SUBSCRIPT_SHIFT_RATIO;
62
+ return { font: scaled, baselineShift: size * ratio };
63
+ }
64
+ /**
65
+ * The subscripts and superscripts to stack (EF-80): a subscript and a
66
+ * superscript that touch, with nothing between them (`T~0~^2^`, or
67
+ * `T^2^~0~`), are set one over the other, as TeX sets `T_0^2`, not one after
68
+ * the other. `scripts[i]` is the script of the i-th run of a line or word
69
+ * (undefined for anything else); returns the index of the first run of each
70
+ * pair. A run pairs once: after `x~a~^b^~c~` the `c` follows the pair.
71
+ *
72
+ * Stacked runs are painted at the same pen position: the first advances
73
+ * nothing (its width becomes 0 and it is flagged `stacked`), the second
74
+ * carries the pair's advance, the wider of the two — so every renderer that
75
+ * paints runs one after another by their widths sets them stacked, and the
76
+ * widths still add up to the line's.
77
+ */
78
+ export function stackedScriptPairs(scripts) {
79
+ const firsts = [];
80
+ for (let i = 0; i + 1 < scripts.length; i++) {
81
+ const a = scripts[i];
82
+ const b = scripts[i + 1];
83
+ if (a && b && a !== b) {
84
+ firsts.push(i);
85
+ i++;
86
+ }
87
+ }
88
+ return firsts;
39
89
  }
40
90
  /** Font a token is measured with: its span font, or the script font of a
41
91
  * superscript / subscript. */
42
92
  function tokenFont(t, normalFont, boldFont, italicFont, boldItalicFont) {
43
93
  return t.scriptFont ?? pickSpanFont(t.bold, t.italic, normalFont, boldFont, italicFont, boldItalicFont);
44
94
  }
45
- /** The script fields a token derived from another (a split, a hyphenated
46
- * head) carries on. */
95
+ /** The script and small-caps fields a token derived from another (a split,
96
+ * a hyphenated head) carries on. */
47
97
  function scriptOf(t) {
48
- return t.script ? { script: t.script, scriptFont: t.scriptFont, baselineShift: t.baselineShift } : {};
98
+ return {
99
+ ...(t.script ? { script: t.script, scriptFont: t.scriptFont, baselineShift: t.baselineShift } : {}),
100
+ ...(t.smallCaps ? { smallCaps: true } : {}),
101
+ };
102
+ }
103
+ /** Small capitals are synthesised, the same way on every backend: a
104
+ * lowercase letter is set as its capital at this fraction of the text
105
+ * size, while capitals, digits and punctuation keep the full size — the
106
+ * ratio browsers use for a face without real small caps. */
107
+ export const SMALL_CAPS_SIZE_RATIO = 0.7;
108
+ /** `font` at the small-caps size. */
109
+ export function smallCapsFont(font) {
110
+ const m = FONT_SIZE_RE.exec(font);
111
+ return m ? font.replace(FONT_SIZE_RE, `${parseFloat(m[1]) * SMALL_CAPS_SIZE_RATIO}px`) : font;
112
+ }
113
+ /** A lowercase letter with a one-unit capital (`ß` and the like, whose
114
+ * capital is longer, stay as they are so the text keeps its length). */
115
+ function smallCapsLowered(ch) {
116
+ const up = ch.toUpperCase();
117
+ return up !== ch && up.length === 1 ? up : undefined;
118
+ }
119
+ /** A text cut into runs of full-size characters and of lowercase letters
120
+ * (`small`, already set as capitals). */
121
+ export function smallCapsRuns(text) {
122
+ const runs = [];
123
+ for (let i = 0; i < text.length; i++) {
124
+ const ch = text[i];
125
+ const up = smallCapsLowered(ch);
126
+ const small = up !== undefined;
127
+ const last = runs[runs.length - 1];
128
+ if (last && last.small === small)
129
+ last.text += up ?? ch;
130
+ else
131
+ runs.push({ text: up ?? ch, small });
132
+ }
133
+ return runs;
134
+ }
135
+ /** Advance of `text` set in small capitals from `font` (per-character
136
+ * tracking not included). */
137
+ export function smallCapsWidth(text, font) {
138
+ let small;
139
+ let w = 0;
140
+ for (const run of smallCapsRuns(text)) {
141
+ w += measureTextWidth(run.text, run.small ? (small ??= smallCapsFont(font)) : font);
142
+ }
143
+ return w;
144
+ }
145
+ /** Advance of `text` in `font`, set in small capitals when `smallCaps`. */
146
+ function textWidth(text, font, smallCaps) {
147
+ return smallCaps ? smallCapsWidth(text, font) : measureTextWidth(text, font);
148
+ }
149
+ /**
150
+ * Split every small-caps segment of the broken lines into runs painted as
151
+ * they were measured: capitals at the segment's font, lowercase letters as
152
+ * capitals at the small-caps size (a `fontString` of their own). The last
153
+ * run absorbs any rounding so the segment keeps its measured width, and the
154
+ * line text follows the painted case (the same length, so source maps
155
+ * hold).
156
+ */
157
+ function expandSmallCaps(lines, normalFont, boldFont, italicFont, boldItalicFont, letterSpacingPx) {
158
+ for (const line of lines) {
159
+ const segs = line.segments;
160
+ if (!segs || !segs.some((s) => s.smallCaps))
161
+ continue;
162
+ const before = segs.map((s) => s.text).join('');
163
+ const out = [];
164
+ for (const seg of segs) {
165
+ if (!seg.smallCaps) {
166
+ out.push(seg);
167
+ continue;
168
+ }
169
+ const rest = { ...seg };
170
+ delete rest.smallCaps;
171
+ const runs = smallCapsRuns(seg.text);
172
+ if (seg.kind !== 'text' || !runs.some((r) => r.small)) {
173
+ out.push({ ...rest, text: runs.map((r) => r.text).join('') });
174
+ continue;
175
+ }
176
+ const base = seg.fontString ?? pickSpanFont(!!seg.bold, !!seg.italic, normalFont, boldFont, italicFont, boldItalicFont);
177
+ const small = smallCapsFont(base);
178
+ let used = 0;
179
+ runs.forEach((run, i) => {
180
+ const font = run.small ? small : base;
181
+ const width = i === runs.length - 1
182
+ ? seg.width - used
183
+ : measureTextWidth(run.text, font) + (letterSpacingPx + (line.letterSpacing ?? 0)) * run.text.length;
184
+ used += width;
185
+ // Capitals keep the segment's own font (none for a plain run).
186
+ const piece = { ...rest, text: run.text, width };
187
+ if (run.small || seg.fontString)
188
+ piece.fontString = font;
189
+ else
190
+ delete piece.fontString;
191
+ // A reference stays one reference: the later runs continue it.
192
+ if (i > 0 && seg.refResourceId !== undefined)
193
+ piece.refContinues = true;
194
+ out.push(piece);
195
+ });
196
+ }
197
+ line.segments = out;
198
+ if (line.text === before)
199
+ line.text = out.map((s) => s.text).join('');
200
+ }
49
201
  }
50
202
  /** The text band of a chip box around the baseline, as fractions of the
51
203
  * chip's font size: from the ascenders down past the descenders; the
@@ -74,34 +226,62 @@ function chipToken(span, normalFont, boldFont, italicFont, boldItalicFont, lette
74
226
  const sizeMatch = FONT_SIZE_RE.exec(normalFont);
75
227
  const sizePx = box?.fontSizePx ?? (sizeMatch ? parseFloat(sizeMatch[1]) : 16);
76
228
  const runs = [];
229
+ // The script of each run, and the unscaled font of a subscript's (which
230
+ // drops further when a superscript is stacked over it).
231
+ const runScripts = [];
232
+ const runBaseFonts = [];
77
233
  for (const s of chip.spans) {
78
234
  if (s.text.length === 0)
79
235
  continue;
80
236
  const bold = s.bold || span.bold || !!box?.bold;
81
237
  const italic = s.italic || span.italic || !!box?.italic;
82
- let font = withFace(pickSpanFont(bold, italic, normalFont, boldFont, italicFont, boldItalicFont), box?.fontFamily, sizePx);
238
+ const base = withFace(pickSpanFont(bold, italic, normalFont, boldFont, italicFont, boldItalicFont), box?.fontFamily, sizePx);
239
+ let font = base;
83
240
  let baselineShift;
84
241
  if (s.script) {
85
242
  const m = scriptMetrics(font, s.script);
86
243
  font = m.font;
87
244
  baselineShift = m.baselineShift;
88
245
  }
89
- runs.push({
90
- text: s.text,
91
- fontString: font,
92
- width: measureTextWidth(s.text, font) + letterSpacingPx * s.text.length,
93
- ...(bold ? { bold: true } : {}),
94
- ...(italic ? { italic: true } : {}),
95
- ...(baselineShift !== undefined ? { baselineShift } : {}),
96
- });
246
+ // Small capitals (the chip's own words or the text around the chip):
247
+ // one run per capital / lowered stretch.
248
+ const smallCaps = !!(s.smallCaps || span.smallCaps);
249
+ const pieces = smallCaps
250
+ ? smallCapsRuns(s.text).map((r) => ({ text: r.text, font: r.small ? smallCapsFont(font) : font }))
251
+ : [{ text: s.text, font }];
252
+ for (const piece of pieces) {
253
+ runs.push({
254
+ text: piece.text,
255
+ fontString: piece.font,
256
+ width: measureTextWidth(piece.text, piece.font) + letterSpacingPx * piece.text.length,
257
+ ...(bold ? { bold: true } : {}),
258
+ ...(italic ? { italic: true } : {}),
259
+ ...(baselineShift !== undefined ? { baselineShift } : {}),
260
+ });
261
+ runScripts.push(smallCaps ? undefined : s.script);
262
+ runBaseFonts.push(base);
263
+ }
264
+ }
265
+ // A subscript and a superscript that touch are stacked (EF-80).
266
+ for (const i of stackedScriptPairs(runScripts)) {
267
+ const first = runs[i];
268
+ const second = runs[i + 1];
269
+ const sub = runScripts[i] === 'sub' ? i : i + 1;
270
+ runs[sub].baselineShift = scriptMetrics(runBaseFonts[sub], 'sub', true).baselineShift;
271
+ second.width = Math.max(first.width, second.width);
272
+ first.width = 0;
273
+ first.stacked = true;
97
274
  }
98
275
  const textWidth = runs.reduce((sum, r) => sum + r.width, 0);
99
276
  const paddingX = box?.paddingXPx ?? 0;
100
277
  const paddingY = box?.paddingYPx ?? 0;
278
+ // A style may pad the top and the bottom apart (EF-172).
279
+ const paddingTop = box?.paddingTopPx ?? paddingY;
280
+ const paddingBottom = box?.paddingBottomPx ?? paddingY;
101
281
  const borderWidth = box?.borderWidthPx ?? 0;
102
282
  const boxWidth = textWidth + (paddingX + borderWidth) * 2;
103
- const ascent = sizePx * CHIP_ASCENT_RATIO + paddingY + borderWidth;
104
- const descent = sizePx * CHIP_DESCENT_RATIO + paddingY + borderWidth;
283
+ const ascent = sizePx * CHIP_ASCENT_RATIO + paddingTop + borderWidth;
284
+ const descent = sizePx * CHIP_DESCENT_RATIO + paddingBottom + borderWidth;
105
285
  return {
106
286
  text: span.text,
107
287
  bold: span.bold,
@@ -127,12 +307,16 @@ function chipToken(span, normalFont, boldFont, italicFont, boldItalicFont, lette
127
307
  chipGap: box?.gapPx ?? 0,
128
308
  };
129
309
  }
310
+ const LEADING_NO_BREAK_RE = new RegExp(`^[${NO_BREAK_SPACES}]+`);
311
+ const TRAILING_NO_BREAK_RE = new RegExp(`[${NO_BREAK_SPACES}]+$`);
130
312
  /** A chip keeps at least its style's `gap` to a neighbour across a word
131
313
  * space: a narrower space is topped up by a margin inside the chip's own
132
314
  * advance (so justification, which stretches spaces only, never eats it).
133
315
  * Between two chips the shortfall is shared, so the pair ends up exactly
134
- * `gap` apart. Glued neighbours (punctuation) get nothing. */
135
- function applyChipGaps(tokens) {
316
+ * `gap` apart. Glued neighbours (punctuation) get nothing. A no-break
317
+ * space is a word space too, though it rides inside the word it glues:
318
+ * `noBreakWidth` measures the run of them a word opens or closes with. */
319
+ function applyChipGaps(tokens, noBreakWidth) {
136
320
  for (let i = 0; i < tokens.length; i++) {
137
321
  const space = tokens[i];
138
322
  if (space.kind !== 'space')
@@ -151,6 +335,36 @@ function applyChipGaps(tokens) {
151
335
  if (right)
152
336
  tokens[i + 1] = withChipMargins(right, share, 0);
153
337
  }
338
+ for (let i = 0; i < tokens.length; i++) {
339
+ const word = tokens[i];
340
+ if (word.kind !== 'text' || word.chip || word.mathRender || word.swatch || word.refResourceId !== undefined)
341
+ continue;
342
+ const lead = LEADING_NO_BREAK_RE.exec(word.text)?.[0];
343
+ const trail = TRAILING_NO_BREAK_RE.exec(word.text)?.[0];
344
+ const left = lead && tokens[i - 1]?.chip ? tokens[i - 1] : undefined;
345
+ const right = trail && tokens[i + 1]?.chip ? tokens[i + 1] : undefined;
346
+ if (!left && !right)
347
+ continue;
348
+ if (lead === word.text && left && right) {
349
+ // Nothing but no-break spaces between two chips: they share it.
350
+ const shortfall = Math.max(left.chipGap ?? 0, right.chipGap ?? 0) - word.width;
351
+ if (shortfall > 0) {
352
+ tokens[i - 1] = withChipMargins(left, 0, shortfall / 2);
353
+ tokens[i + 1] = withChipMargins(right, shortfall / 2, 0);
354
+ }
355
+ continue;
356
+ }
357
+ if (left) {
358
+ const shortfall = (left.chipGap ?? 0) - noBreakWidth(word, lead);
359
+ if (shortfall > 0)
360
+ tokens[i - 1] = withChipMargins(left, 0, shortfall);
361
+ }
362
+ if (right) {
363
+ const shortfall = (right.chipGap ?? 0) - noBreakWidth(word, trail);
364
+ if (shortfall > 0)
365
+ tokens[i + 1] = withChipMargins(right, shortfall, 0);
366
+ }
367
+ }
154
368
  }
155
369
  function withChipMargins(token, addLeft, addRight) {
156
370
  const chip = token.chip;
@@ -183,57 +397,133 @@ export function urlBreakIndices(text) {
183
397
  }
184
398
  return out;
185
399
  }
186
- const LETTER_RE = /\p{L}/u;
187
- /** Break opportunities inside a word: after each soft hyphen the dictionary
188
- * inserted (a hyphen is added when the line ends there) and after a hard
189
- * hyphen between two letters — "enseñanza-aprendizaje" — where the line
190
- * ends on the hyphen the word already carries. `part` still holds the
191
- * soft hyphens, `clean` is the text as laid out. */
192
- function wordBreakPoints(part, clean, font, letterSpacingPx) {
193
- const out = [];
194
- const widthBefore = (idx) => measureTextWidth(clean.slice(0, idx), font) + letterSpacingPx * idx;
195
- let priorSoft = 0;
196
- for (let i = 0; i < part.length; i++) {
197
- const ch = part[i];
198
- if (ch === SOFT_HYPHEN) {
199
- const idx = i - priorSoft;
200
- if (idx > 0 && idx < clean.length && !out.some((b) => b.charIndex === idx))
201
- out.push({ charIndex: idx, widthBefore: widthBefore(idx) });
202
- priorSoft++;
203
- }
204
- else if (ch === '-' && i > 0 && i < part.length - 1 && LETTER_RE.test(part[i - 1]) && LETTER_RE.test(part[i + 1])) {
205
- const idx = i - priorSoft + 1;
206
- out.push({ charIndex: idx, widthBefore: widthBefore(idx), bare: true });
400
+ /**
401
+ * A word as laid out (its soft hyphens removed) and the breaks its soft
402
+ * hyphens mark: the dictionary's when `hyphenate` is on, and the author's
403
+ * own — the U+00AD the source carries, which the dictionary leaves as they
404
+ * are (it does not hyphenate a word that already has them). The zero-width
405
+ * space the dictionary puts after a slash is dropped: the rich breaker does
406
+ * not break there, and it must not reach the line text.
407
+ */
408
+ function syllabify(word, hyphenate) {
409
+ const hyphenated = hyphenate ? withoutSlashJoints(word, hyphenateText(word)) : word;
410
+ if (!hyphenated.includes(SOFT_HYPHEN))
411
+ return { clean: hyphenated, soft: [] };
412
+ let clean = '';
413
+ const soft = [];
414
+ let j = 0;
415
+ for (let i = 0; i < hyphenated.length; i++) {
416
+ const ch = hyphenated[i];
417
+ // A soft hyphen the dictionary inserted is not the source's character.
418
+ const fromSource = j < word.length && ch === word[j];
419
+ if (fromSource)
420
+ j++;
421
+ if (ch === SOFT_HYPHEN)
422
+ soft.push({ index: clean.length, author: fromSource });
423
+ else
424
+ clean += ch;
425
+ }
426
+ return { clean, soft };
427
+ }
428
+ /** Break opportunities inside a word (`clean`, the text as laid out):
429
+ * - after each soft hyphen, the dictionary's or the author's (`soft`); a
430
+ * hyphen is added when the line ends there;
431
+ * - after a hard hyphen between two letters — "enseñanza-aprendizaje" —
432
+ * where the line ends on the hyphen the word already carries;
433
+ * - after an em or en dash: with `dashBreaks`, one set closed between words
434
+ * as `breaksAfterDash` reads it ("say—that’s", "riddles.—I"), for both
435
+ * breakers — `touching` is the end (the last two characters) of the word
436
+ * run this word touches, with no space in between, which a dash at the
437
+ * start of the word needs; without it, one between two letters
438
+ * ("largas—separadas"), for the greedy breaker only, as pretext breaks a
439
+ * plain paragraph there;
440
+ * - between ideographs, where pretext breaks a plain paragraph (so its
441
+ * kinsoku rules hold here too). */
442
+ function wordBreakPoints(clean, soft, font, letterSpacingPx, smallCaps, dashBreaks = false, touching) {
443
+ const widthBefore = (idx) => textWidth(clean.slice(0, idx), font, smallCaps) + letterSpacingPx * idx;
444
+ const byIndex = new Map();
445
+ const add = (bp) => {
446
+ if (bp.charIndex <= 0 || bp.charIndex >= clean.length)
447
+ return;
448
+ // One break per position; the word's own hyphen wins over a soft one.
449
+ const existing = byIndex.get(bp.charIndex);
450
+ if (existing && !(bp.bare && !existing.bare))
451
+ return;
452
+ byIndex.set(bp.charIndex, { ...bp, widthBefore: widthBefore(bp.charIndex) });
453
+ };
454
+ // The character at `k`, reading back into the run this word touches.
455
+ const charAt = (k) => (k >= 0 ? clean[k] : touching?.[touching.length + k]);
456
+ for (let i = dashBreaks ? 0 : 1; i < clean.length - 1; i++) {
457
+ const ch = clean[i];
458
+ if (ch !== '-' && !isDash(ch))
459
+ continue;
460
+ if (dashBreaks && ch !== '-') {
461
+ if (breaksAfterDash(charAt(i - 1), ch, clean[i + 1], charAt(i - 2)))
462
+ add({ charIndex: i + 1, free: true });
463
+ continue;
207
464
  }
465
+ if (i === 0 || !breaksAfterHardHyphen(clean[i - 1], clean[i + 1]))
466
+ continue;
467
+ add(ch === '-' ? { charIndex: i + 1, bare: true } : { charIndex: i + 1, free: true, greedyOnly: true });
208
468
  }
209
- return out;
469
+ for (const s of soft)
470
+ add(s.author ? { charIndex: s.index, author: true } : { charIndex: s.index });
471
+ for (const idx of cjkBreakIndices(clean, font))
472
+ add({ charIndex: idx, free: true });
473
+ return [...byIndex.values()].sort((a, b) => a.charIndex - b.charIndex);
210
474
  }
211
475
  /**
212
476
  * A word wider than the whole line (a table cell, a narrow column): divide
213
- * it at the last syllable that fits — the dictionary's, a hyphen added —
214
- * or, when none does, at the last character that fits, so no word ever
215
- * runs past its measure. Null when not even one character fits.
477
+ * it at the last no-break space that leaves a head that fits ("300 000 |
478
+ * 000", nothing added), else at the last syllable that fits — the
479
+ * dictionary's, a hyphen added — or, when none does, at the last character
480
+ * that fits, so no word ever runs past its measure. A cut next to a hyphen
481
+ * the word carries falls after it and adds none (`hard`): never "fisica-" |
482
+ * "-universitaria" nor "fisica--". Null when not even one character fits,
483
+ * or, with `syllablesOnly`, when no no-break space or syllable does.
216
484
  */
217
- function emergencySplit(token, font, letterSpacingPx, lineMaxWidth) {
485
+ function emergencySplit(token, font, letterSpacingPx, lineMaxWidth, syllablesOnly = false) {
218
486
  const text = token.text;
219
487
  if (text.length < 2)
220
488
  return null;
221
489
  const hyphenW = measureTextWidth('-', font) + letterSpacingPx;
222
- const widthBefore = (idx) => measureTextWidth(text.slice(0, idx), font) + letterSpacingPx * idx;
223
- const fits = (idx) => widthBefore(idx) + hyphenW <= lineMaxWidth;
224
- let at = 0;
225
- const syllabified = hyphenateText(text);
226
- let priorSoft = 0;
227
- for (let i = 0; i < syllabified.length; i++) {
228
- if (syllabified[i] !== SOFT_HYPHEN)
490
+ const widthBefore = (idx) => textWidth(text.slice(0, idx), font, token.smallCaps) + letterSpacingPx * idx;
491
+ const flags = { bold: token.bold, italic: token.italic, captionLabel: token.captionLabel, ...scriptOf(token) };
492
+ // A group glued by no-break spaces too wide for any line: the space is
493
+ // the least bad place to part it (EF-66). The line ends before it and the
494
+ // next one opens after it.
495
+ for (let idx = text.length - 2; idx >= 1; idx--) {
496
+ if (!NO_BREAK_SPACES.includes(text[idx]) || NO_BREAK_SPACES.includes(text[idx - 1]))
229
497
  continue;
230
- const idx = i - priorSoft;
231
- priorSoft++;
232
- if (idx > 0 && idx < text.length && fits(idx))
233
- at = idx;
498
+ const headWidth = widthBefore(idx);
499
+ if (headWidth > lineMaxWidth)
500
+ continue;
501
+ return {
502
+ head: { ...flags, text: text.slice(0, idx), kind: 'text', width: headWidth },
503
+ tail: { ...tailAfter(token, idx + 1, widthBefore(idx + 1)), ...flags },
504
+ };
234
505
  }
235
- if (at === 0) {
506
+ // No hyphen where the cut falls next to an ideograph, or right after a
507
+ // hyphen of the text.
508
+ const afterHyphen = (idx) => text[idx - 1] === '-';
509
+ const markW = (idx) => (afterHyphen(idx) || hasCJK(text.slice(idx - 1, idx + 1)) ? 0 : hyphenW);
510
+ const fits = (idx) => widthBefore(idx) + markW(idx) <= lineMaxWidth;
511
+ let at = 0;
512
+ // The dictionary's syllables, as offsets into the text: `syllabify` maps
513
+ // them past anything else the dictionary might put in.
514
+ const { clean, soft } = syllabify(text, true);
515
+ if (clean === text) {
516
+ for (const s of soft) {
517
+ if (s.index > 0 && s.index < text.length && fits(s.index))
518
+ at = s.index;
519
+ }
520
+ }
521
+ if (at === 0 && !syllablesOnly) {
236
522
  for (let idx = text.length - 1; idx >= 1; idx--) {
523
+ // Not right before a hyphen of the text: the next line would open
524
+ // on it.
525
+ if (text[idx] === '-')
526
+ continue;
237
527
  if (fits(idx)) {
238
528
  at = idx;
239
529
  break;
@@ -242,14 +532,64 @@ function emergencySplit(token, font, letterSpacingPx, lineMaxWidth) {
242
532
  }
243
533
  if (at === 0)
244
534
  return null;
245
- const flags = { bold: token.bold, italic: token.italic, captionLabel: token.captionLabel, ...scriptOf(token) };
535
+ const mark = markW(at) > 0 ? '-' : '';
536
+ return {
537
+ head: { ...flags, text: text.slice(0, at) + mark, kind: 'text', width: widthBefore(at) + markW(at) },
538
+ tail: { ...tailAfter(token, at, widthBefore(at)), ...flags },
539
+ ...(afterHyphen(at) ? { hard: true } : {}),
540
+ };
541
+ }
542
+ /** What is left of `token` after a cut at `at` (`cutWidth` px in): its text
543
+ * and width from there, the break points after the cut moved with it, and
544
+ * what they need (the hyphen's width; a web address's joints stay bare),
545
+ * so the next line breaks the rest where it could break the whole. */
546
+ function tailAfter(token, at, cutWidth) {
547
+ const residual = (token.breakPoints ?? [])
548
+ .filter((b) => b.charIndex > at)
549
+ .map((b) => ({ ...b, charIndex: b.charIndex - at, widthBefore: b.widthBefore - cutWidth }));
246
550
  return {
247
- head: { ...flags, text: text.slice(0, at) + '-', kind: 'text', width: widthBefore(at) + hyphenW },
248
- tail: { ...flags, text: text.slice(at), kind: 'text', width: token.width - widthBefore(at) },
551
+ text: token.text.slice(at),
552
+ bold: token.bold,
553
+ italic: token.italic,
554
+ kind: 'text',
555
+ width: token.width - cutWidth,
556
+ ...(residual.length > 0 ? { breakPoints: residual, hyphenWidth: token.hyphenWidth } : {}),
557
+ ...(token.bareBreaks ? { bareBreaks: true } : {}),
558
+ ...(token.dashJoin ? { dashJoin: true } : {}),
249
559
  };
250
560
  }
251
- function tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont, shouldHyphenate, letterSpacingPx = 0) {
561
+ /** For each character of the spans' joined text, whether it sits in a
562
+ * compound: a run of text between breaking spaces with a hyphen between
563
+ * two letters (see `hasCompound`). */
564
+ function compoundMask(spans) {
565
+ const text = spans.map((s) => s.text).join('');
566
+ const mask = new Array(text.length).fill(false);
567
+ let i = 0;
568
+ while (i < text.length) {
569
+ if (isBreakingSpace(text[i])) {
570
+ i++;
571
+ continue;
572
+ }
573
+ let j = i;
574
+ while (j < text.length && !isBreakingSpace(text[j]))
575
+ j++;
576
+ if (hasCompound(text.slice(i, j)))
577
+ mask.fill(true, i, j);
578
+ i = j;
579
+ }
580
+ return mask;
581
+ }
582
+ function tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont, shouldHyphenate, letterSpacingPx = 0,
583
+ /** `MeasureBlockOptions.breakAfterDashes`. */
584
+ dashBreaks = false,
585
+ /** `MeasureBlockOptions.hyphenateCompounds === false`: the dictionary
586
+ * leaves the words of a compound whole. */
587
+ keepCompounds = false) {
252
588
  const tokens = [];
589
+ // Which characters of the joined text sit in a compound, a word (across
590
+ // runs: "*after*-dinner") with a hyphen between two letters.
591
+ const inCompound = keepCompounds && shouldHyphenate ? compoundMask(spans) : undefined;
592
+ let spanStart = 0;
253
593
  // Tracking: every character (spaces included) advances `letterSpacingPx`
254
594
  // more, exactly as canvas `letterSpacing` / CSS `letter-spacing` / PDF `Tc`
255
595
  // paint it, so measured widths stay in step with the renderers.
@@ -264,6 +604,8 @@ function tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont,
264
604
  };
265
605
  const spanFont = (span) => scriptFieldsOf(span).scriptFont ?? pickSpanFont(span.bold, span.italic, normalFont, boldFont, italicFont, boldItalicFont);
266
606
  for (const span of spans) {
607
+ const spanBase = spanStart;
608
+ spanStart += span.text.length;
267
609
  // Inline `:ref` spans are atomic: the resolved label (already in `text`)
268
610
  // is one non-breaking box so it never wraps apart. Kind 'text' keeps the
269
611
  // generic layout/renderers treating it like a word; `refResourceId` flows
@@ -276,8 +618,9 @@ function tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont,
276
618
  italic: span.italic,
277
619
  captionLabel: span.captionLabel,
278
620
  ...scriptFieldsOf(span),
621
+ ...(span.smallCaps ? { smallCaps: true } : {}),
279
622
  kind: 'text',
280
- width: measureTextWidth(span.text, refFont) + track(span.text),
623
+ width: textWidth(span.text, refFont, span.smallCaps) + track(span.text),
281
624
  refResourceId: span.ref.resourceId,
282
625
  });
283
626
  continue;
@@ -297,7 +640,7 @@ function tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont,
297
640
  captionLabel: span.captionLabel,
298
641
  kind: 'text',
299
642
  width: swatchSidePx(swatchFont),
300
- swatch: /^#[0-9a-f]{6}$/i.test(span.swatch.color) ? { color: span.swatch.color } : {},
643
+ swatch: isSwatchFill(span.swatch.color) ? { color: span.swatch.color } : {},
301
644
  });
302
645
  continue;
303
646
  }
@@ -316,20 +659,30 @@ function tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont,
316
659
  });
317
660
  continue;
318
661
  }
319
- const text = shouldHyphenate ? hyphenateText(span.text) : span.text;
320
662
  const font = spanFont(span);
321
663
  const scriptFields = scriptFieldsOf(span);
322
- // Split on word boundaries while preserving spaces
323
- const parts = text.match(/\S+|\s+/g);
664
+ // Small capitals: the words keep their case (hyphenation reads it) and
665
+ // measure as they will be painted.
666
+ const sc = !!span.smallCaps;
667
+ const scFields = sc ? { smallCaps: true } : {};
668
+ // Split on word boundaries while preserving spaces. Each word is
669
+ // hyphenated on its own (the dictionary works word by word anyway), so
670
+ // its soft hyphens can be told apart from the ones the source carries.
671
+ // A no-break space is no boundary: it stays inside the word it glues
672
+ // ("37 °C"), which the line then never breaks at (EF-66).
673
+ const parts = span.text.match(WORDS_AND_SPACES_RE);
324
674
  if (!parts)
325
675
  continue;
676
+ let partStart = spanBase;
326
677
  for (const part of parts) {
327
- const isSpace = part.trim().length === 0;
678
+ const partAt = partStart;
679
+ partStart += part.length;
680
+ const isSpace = isBreakingSpaceRun(part);
328
681
  if (!isSpace && URL_LIKE_RE.test(part.replace(/\u00AD/g, ''))) {
329
682
  const clean = part.replace(/\u00AD/g, '');
330
683
  const breakPoints = urlBreakIndices(clean).map((charIndex) => ({
331
684
  charIndex,
332
- widthBefore: measureTextWidth(clean.slice(0, charIndex), font) + letterSpacingPx * charIndex,
685
+ widthBefore: textWidth(clean.slice(0, charIndex), font, sc) + letterSpacingPx * charIndex,
333
686
  }));
334
687
  tokens.push({
335
688
  text: clean,
@@ -337,14 +690,22 @@ function tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont,
337
690
  italic: span.italic,
338
691
  captionLabel: span.captionLabel,
339
692
  ...scriptFields,
693
+ ...scFields,
340
694
  kind: 'text',
341
- width: measureTextWidth(clean, font) + track(clean),
695
+ width: textWidth(clean, font, sc) + track(clean),
342
696
  ...(breakPoints.length > 0 ? { breakPoints, hyphenWidth: 0, bareBreaks: true } : {}),
343
697
  });
344
698
  continue;
345
699
  }
346
- const clean = isSpace ? part : part.replace(/\u00AD/g, '');
347
- const breakPoints = isSpace ? [] : wordBreakPoints(part, clean, font, letterSpacingPx);
700
+ const { clean, soft } = isSpace ? { clean: part, soft: [] } : syllabify(part, shouldHyphenate && inCompound?.[partAt] !== true);
701
+ // The characters this word touches, for a dash that opens it
702
+ // ("**riddles.**—I", "*\"no\"*—and"): the end of a word run just
703
+ // before, no space in between.
704
+ const before = tokens[tokens.length - 1];
705
+ const touching = dashBreaks && before && before.kind === 'text' && !before.mathRender && !before.swatch && !before.chip
706
+ ? before.text.slice(-2)
707
+ : undefined;
708
+ const breakPoints = isSpace ? [] : wordBreakPoints(clean, soft, font, letterSpacingPx, sc, dashBreaks, touching);
348
709
  if (breakPoints.length > 0) {
349
710
  tokens.push({
350
711
  text: clean,
@@ -352,8 +713,9 @@ function tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont,
352
713
  italic: span.italic,
353
714
  captionLabel: span.captionLabel,
354
715
  ...scriptFields,
716
+ ...scFields,
355
717
  kind: 'text',
356
- width: measureTextWidth(clean, font) + track(clean),
718
+ width: textWidth(clean, font, sc) + track(clean),
357
719
  breakPoints,
358
720
  hyphenWidth: measureTextWidth('-', font) + letterSpacingPx,
359
721
  });
@@ -365,46 +727,237 @@ function tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont,
365
727
  italic: span.italic,
366
728
  captionLabel: span.captionLabel,
367
729
  ...scriptFields,
730
+ ...(isSpace ? {} : scFields),
368
731
  kind: isSpace ? 'space' : 'text',
369
- width: measureTextWidth(part, font) + track(part),
732
+ width: textWidth(part, font, sc && !isSpace) + track(part),
370
733
  });
371
734
  }
372
735
  }
373
736
  }
374
- if (tokens.some((t) => t.chip))
375
- applyChipGaps(tokens);
737
+ if (tokens.some((t) => t.script))
738
+ stackScriptTokens(tokens, normalFont, boldFont, italicFont, boldItalicFont);
739
+ if (tokens.some((t) => t.chip)) {
740
+ applyChipGaps(tokens, (t, run) => measureTextWidth(run, tokenFont(t, normalFont, boldFont, italicFont, boldItalicFont)) + letterSpacingPx * run.length);
741
+ }
742
+ if (dashBreaks)
743
+ markDashJoins(tokens);
376
744
  return tokens;
377
745
  }
746
+ /** A run of words a dash break may read across: not a formula, a swatch,
747
+ * a chip or one of two stacked scripts. */
748
+ function isWordRun(t) {
749
+ return t !== undefined && t.kind === 'text' && !t.mathRender && !t.swatch && !t.chip && !t.stacked;
750
+ }
751
+ /** Flag `dashJoin` on each word run that ends on a closed dash (as
752
+ * `breaksAfterDash` reads it) touched by the next word run: the dash
753
+ * closes one run and the next one opens in another style ("riddles—*and*",
754
+ * "say—**that**"). A dash inside a run, or opening one, is a break point
755
+ * of its own word (see {@link wordBreakPoints}). */
756
+ function markDashJoins(tokens) {
757
+ for (let t = 0; t + 1 < tokens.length; t++) {
758
+ const a = tokens[t];
759
+ const b = tokens[t + 1];
760
+ if (!isWordRun(a) || !isWordRun(b) || a.refResourceId !== undefined)
761
+ continue;
762
+ const dash = a.text[a.text.length - 1];
763
+ if (!isDash(dash))
764
+ continue;
765
+ // The dash and the two characters before it, read back into the run
766
+ // before when this one is shorter.
767
+ const tail = (isWordRun(tokens[t - 1]) ? tokens[t - 1].text.slice(-2) : '') + a.text.slice(-3);
768
+ if (breaksAfterDash(tail[tail.length - 2], dash, b.text[0], tail[tail.length - 3]))
769
+ a.dashJoin = true;
770
+ }
771
+ }
772
+ /** Set every subscript and superscript that touch one over the other (see
773
+ * {@link stackedScriptPairs}): the first token of a pair advances nothing,
774
+ * the second the pair's advance; the subscript drops to its stacked
775
+ * position; neither keeps a break point, so the pair never parts. Words
776
+ * only: a script reference, or one in small capitals, sets as it is. */
777
+ function stackScriptTokens(tokens, normalFont, boldFont, italicFont, boldItalicFont) {
778
+ const scripts = tokens.map((t) => (t.kind === 'text' && t.script && !t.smallCaps && t.refResourceId === undefined && !t.chip && !t.mathRender && !t.swatch
779
+ ? t.script
780
+ : undefined));
781
+ for (const i of stackedScriptPairs(scripts)) {
782
+ const pair = [tokens[i], tokens[i + 1]];
783
+ for (const t of pair) {
784
+ delete t.breakPoints;
785
+ delete t.hyphenWidth;
786
+ delete t.bareBreaks;
787
+ }
788
+ const sub = pair[0].script === 'sub' ? pair[0] : pair[1];
789
+ sub.baselineShift = scriptMetrics(pickSpanFont(sub.bold, sub.italic, normalFont, boldFont, italicFont, boldItalicFont), 'sub', true).baselineShift;
790
+ pair[1].width = Math.max(pair[0].width, pair[1].width);
791
+ pair[0].width = 0;
792
+ pair[0].stacked = 'first';
793
+ pair[1].stacked = 'second';
794
+ }
795
+ }
796
+ /** Ragged hyphenation: at most this many lines in a row end on a
797
+ * dictionary syllable (a "ladder" of hyphens down the edge). */
798
+ const MAX_RAGGED_HYPHEN_RUN = 2;
799
+ /** Width of the spaces a line's tokens end with (trimmed when it is set). */
800
+ function trailingSpaceWidth(tokens) {
801
+ let w = 0;
802
+ for (let k = tokens.length - 1; k >= 0 && tokens[k].kind === 'space'; k--)
803
+ w += tokens[k].width;
804
+ return w;
805
+ }
806
+ /** How many of a line's last tokens touch the next one with no space in
807
+ * between (two runs of one word, "**Nota**:"): the line may not break
808
+ * inside that group. */
809
+ function gluedTailLength(tokens) {
810
+ let k = 0;
811
+ for (let i = tokens.length - 1; i >= 0 && tokens[i].kind !== 'space'; i--)
812
+ k++;
813
+ return k;
814
+ }
815
+ /** A token the emergency division may cut: a word, not an atomic box nor
816
+ * one of two stacked scripts. */
817
+ function isDivisible(token) {
818
+ return token.kind === 'text' && !token.mathRender && !token.swatch && !token.chip && token.refResourceId === undefined && !token.stacked;
819
+ }
820
+ /** Cut a word at one of its break points: the head ends the line (with
821
+ * `mark`, `markWidth` px wide, appended), the tail keeps the break points
822
+ * after the cut. */
823
+ function splitToken(token, bp, mark, markWidth) {
824
+ const flags = { bold: token.bold, italic: token.italic, captionLabel: token.captionLabel, ...scriptOf(token) };
825
+ const residual = (token.breakPoints ?? [])
826
+ .filter((b) => b.charIndex > bp.charIndex)
827
+ .map((b) => ({ ...b, charIndex: b.charIndex - bp.charIndex, widthBefore: b.widthBefore - bp.widthBefore }));
828
+ return {
829
+ head: { ...flags, text: token.text.slice(0, bp.charIndex) + mark, kind: 'text', width: bp.widthBefore + markWidth },
830
+ tail: {
831
+ ...flags,
832
+ text: token.text.slice(bp.charIndex),
833
+ kind: 'text',
834
+ width: token.width - bp.widthBefore,
835
+ ...(residual.length > 0 ? { breakPoints: residual, hyphenWidth: token.hyphenWidth } : {}),
836
+ ...(token.bareBreaks ? { bareBreaks: true } : {}),
837
+ ...(token.dashJoin ? { dashJoin: true } : {}),
838
+ },
839
+ };
840
+ }
841
+ /** `token` (the tail of a compound broken after its hyphen) opening with
842
+ * that hyphen repeated, `hyphenWidth` px wide; its break points move with
843
+ * it. */
844
+ function withLeadingHyphen(token, hyphenWidth) {
845
+ return {
846
+ ...token,
847
+ text: `-${token.text}`,
848
+ width: token.width + hyphenWidth,
849
+ ...(token.breakPoints
850
+ ? { breakPoints: token.breakPoints.map((bp) => ({ ...bp, charIndex: bp.charIndex + 1, widthBefore: bp.widthBefore + hyphenWidth })) }
851
+ : {}),
852
+ };
853
+ }
854
+ /** The latest break inside a line's last `glued` tokens that adds nothing
855
+ * to the line — between ideographs, after a dash, a hard hyphen, a URL
856
+ * joint — with the token's position in the line. `join`: the break falls
857
+ * after that whole token, at a dash that closes it (`dashJoin`); the
858
+ * group's last token joins the token that did not fit. */
859
+ function lastPlainBreakInGroup(lineTokens, glued) {
860
+ for (let at = lineTokens.length - 1; at >= lineTokens.length - glued; at--) {
861
+ const token = lineTokens[at];
862
+ if (token.dashJoin)
863
+ return { at, join: true };
864
+ const points = token.breakPoints ?? [];
865
+ for (let k = points.length - 1; k >= 0; k--) {
866
+ const bp = points[k];
867
+ if (token.bareBreaks || bp.bare || bp.free)
868
+ return { at, token, bp };
869
+ }
870
+ }
871
+ return null;
872
+ }
873
+ /** The latest syllable (the dictionary's or the author's soft hyphen)
874
+ * inside a line's last `glued` tokens where the line, with the hyphen it
875
+ * adds, still fits `lineMaxWidth`, with the token's position in the
876
+ * line. */
877
+ function lastSyllableInGroup(lineTokens, glued, lineMaxWidth) {
878
+ let before = 0;
879
+ for (let k = 0; k < lineTokens.length - glued; k++)
880
+ before += lineTokens[k].width;
881
+ const widthsBefore = [];
882
+ for (let at = lineTokens.length - glued; at < lineTokens.length; at++) {
883
+ widthsBefore[at] = before;
884
+ before += lineTokens[at].width;
885
+ }
886
+ for (let at = lineTokens.length - 1; at >= lineTokens.length - glued; at--) {
887
+ const token = lineTokens[at];
888
+ if (!isDivisible(token) || token.bareBreaks)
889
+ continue;
890
+ const points = token.breakPoints ?? [];
891
+ for (let k = points.length - 1; k >= 0; k--) {
892
+ const bp = points[k];
893
+ if (bp.bare || bp.free || bp.greedyOnly)
894
+ continue;
895
+ if (widthsBefore[at] + bp.widthBefore + (token.hyphenWidth ?? 0) <= lineMaxWidth)
896
+ return { at, token, bp };
897
+ }
898
+ }
899
+ return null;
900
+ }
378
901
  /**
379
902
  * Measure a rich text block with mixed font weights.
380
903
  * Uses canvas measureText for per-token measurement and greedy line-breaking.
904
+ * A text of nothing but whitespace, no-break spaces included, sets no line.
381
905
  */
382
906
  export function measureRichBlock(spans, normalFont, boldFont, italicFont, boldItalicFont, maxWidthPx, lineHeightPx, options) {
383
907
  const plainText = spans.map((s) => s.text).join('');
384
908
  if (plainText.trim() === '') {
385
909
  return { lines: [], totalHeight: 0 };
386
910
  }
911
+ return measureRichText(spans, plainText, normalFont, boldFont, italicFont, boldItalicFont, maxWidthPx, lineHeightPx, options);
912
+ }
913
+ /**
914
+ * {@link measureRichBlock} for a paragraph of a table cell, or a piece of a
915
+ * caption or a note: a text of nothing but no-break spaces sets a line of
916
+ * them, as CommonMark reads a line holding U+00A0 (EF-154). Ordinary
917
+ * whitespace, and a lone zero-width U+FEFF, still set none (see
918
+ * {@link isBlankText}). The body keeps {@link measureRichBlock}'s rule, as
919
+ * its parser drops such a paragraph too.
920
+ */
921
+ export function measureRichSnippet(spans, normalFont, boldFont, italicFont, boldItalicFont, maxWidthPx, lineHeightPx, options) {
922
+ const plainText = spans.map((s) => s.text).join('');
923
+ if (isBlankText(plainText)) {
924
+ return { lines: [], totalHeight: 0 };
925
+ }
926
+ return measureRichText(spans, plainText, normalFont, boldFont, italicFont, boldItalicFont, maxWidthPx, lineHeightPx, options);
927
+ }
928
+ function measureRichText(spans, plainText, normalFont, boldFont, italicFont, boldItalicFont, maxWidthPx, lineHeightPx, options) {
387
929
  const shouldHyphenate = options?.hyphenate ?? false;
388
930
  const indentPx = options?.firstLineIndentPx ?? 0;
389
931
  const hanging = options?.hangingIndent ?? false;
390
932
  const textAlign = options?.textAlign ?? 'left';
391
933
  const letterSpacingPx = options?.letterSpacingPx ?? 0;
392
- const tokens = tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont, shouldHyphenate, letterSpacingPx);
934
+ const hyphenationZonePx = shouldHyphenate ? options?.hyphenationZonePx : undefined;
935
+ const tokens = tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont, shouldHyphenate, letterSpacingPx, options?.breakAfterDashes === true, options?.hyphenateCompounds === false);
936
+ const repeatHyphen = options?.repeatHyphen === true;
937
+ const hasSmallCaps = tokens.some((t) => t.smallCaps);
393
938
  const normalSpaceWidth = textAlign === 'justify' ? normalSpaceWidthFor(normalFont) + letterSpacingPx : 0;
394
939
  if (tokens.length === 0) {
395
940
  return { lines: [], totalHeight: 0 };
396
941
  }
397
- // Knuth-Plass optimal line breaking path
398
- if (options?.optimal && textAlign === 'justify') {
399
- const maxStretchRatio = options.maxStretchRatio ?? 1.5;
400
- const minShrinkRatio = options.minShrinkRatio ?? 0.8;
401
- const items = richTokensToItems(tokens, normalSpaceWidth, maxStretchRatio, minShrinkRatio);
942
+ // Knuth-Plass optimal line breaking path. Not for words set without
943
+ // spaces (a run of ideographs or kana): a line of them has no spaces to
944
+ // stretch, so it is set first-fit, breaking between ideographs, as the
945
+ // plain path does. A lone CJK bracket or fullwidth sign is no reason.
946
+ // Ragged text takes it too with `optimalRagged`: its word spaces keep
947
+ // their width and each line gets the ragged stretch instead.
948
+ const ragged = textAlign !== 'justify';
949
+ if (options?.optimal && (!ragged || options.optimalRagged) && !hasCJKRun(plainText)) {
950
+ const maxStretchRatio = ragged ? 1 : options.maxStretchRatio ?? 1.5;
951
+ const minShrinkRatio = ragged ? 1 : options.minShrinkRatio ?? 0.8;
952
+ // The runt threshold counts word spaces on ragged text too.
953
+ const spaceWidth = ragged ? normalSpaceWidthFor(normalFont) + letterSpacingPx : normalSpaceWidth;
954
+ const items = richTokensToItems(tokens, spaceWidth, maxStretchRatio, minShrinkRatio, repeatHyphen);
402
955
  const lineWidthFn = (li) => {
403
956
  const isFirst = li === 0;
404
957
  const indent = indentPx > 0
405
958
  ? (hanging ? (isFirst ? 0 : indentPx) : (isFirst ? indentPx : 0))
406
959
  : 0;
407
- return maxWidthPx - indent;
960
+ return lineMeasure(maxWidthPx, options.restWidths, li) - indent;
408
961
  };
409
962
  const lineIndentFn = (li) => {
410
963
  const isFirst = li === 0;
@@ -414,45 +967,76 @@ export function measureRichBlock(spans, normalFont, boldFont, italicFont, boldIt
414
967
  };
415
968
  const runtPenalty = options.runtPenalty ?? 0;
416
969
  const runtMinWidth = runtPenalty > 0
417
- ? (options.runtMinCharacters ?? 0) * normalSpaceWidth
970
+ ? (options.runtMinCharacters ?? 0) * spaceWidth
418
971
  : 0;
972
+ const trackingPerChar = ragged ? 0 : options.justifyTrackingPx ?? 0;
419
973
  const breaks = computeBreakpoints(items, {
420
974
  lineWidth: lineWidthFn,
421
- normalSpaceWidth,
975
+ normalSpaceWidth: spaceWidth,
422
976
  maxStretchRatio,
423
977
  minShrinkRatio,
424
978
  runtPenalty,
425
979
  runtMinWidth,
980
+ runtGraded: options.runtGraded === true,
981
+ ...(options.avoidHyphenAtLines ? { avoidHyphenAtLines: options.avoidHyphenAtLines } : {}),
982
+ ...(options.keepBreaks?.path === 'rich' ? { fixedBreaks: options.keepBreaks.at } : {}),
426
983
  looseness: options.looseness ?? 0,
427
- lineWidthUniformFrom: 1,
984
+ lineWidthUniformFrom: uniformMeasureFrom(options.restWidths),
985
+ trackingPerChar,
986
+ ...(ragged ? { raggedStretch: raggedStretchPx(normalFont) } : {}),
987
+ ...(ragged && hyphenationZonePx !== undefined ? { hyphenationZone: hyphenationZonePx } : {}),
428
988
  });
429
989
  if (breaks.length > 0) {
430
- const kpLines = reconstructRichLines(items, breaks, tokens, lineHeightPx, lineWidthFn, lineIndentFn, normalSpaceWidth, textAlign);
431
- return {
432
- lines: kpLines,
433
- totalHeight: kpLines.length * lineHeightPx,
434
- ...(isRuntLastLine(kpLines, runtMinWidth) ? { lastLineRunt: true } : {}),
435
- };
990
+ const kpLines = reconstructRichLines(items, breaks, tokens, lineHeightPx, lineWidthFn, lineIndentFn, normalSpaceWidth, textAlign, trackingPerChar);
991
+ if (!hasOverfullLine(kpLines, lineWidthFn, ragged)) {
992
+ if (hasSmallCaps)
993
+ expandSmallCaps(kpLines, normalFont, boldFont, italicFont, boldItalicFont, letterSpacingPx);
994
+ return {
995
+ lines: kpLines,
996
+ totalHeight: kpLines.length * lineHeightPx,
997
+ ...(isRuntLastLine(kpLines, runtMinWidth) ? { lastLineRunt: true } : {}),
998
+ breaks: { path: 'rich', at: breaks },
999
+ };
1000
+ }
436
1001
  }
437
- // Fallback to greedy if K-P produced no breaks
1002
+ // Fallback to greedy if K-P produced no breaks, or a line past the
1003
+ // measure (a word wider than it: the greedy breaker divides it)
438
1004
  }
439
1005
  const lines = [];
440
1006
  let y = 0;
441
1007
  let tokenIdx = 0;
442
1008
  let lineIndex = 0;
1009
+ // Lines in a row that ended on a dictionary syllable (ragged hyphenation).
1010
+ let syllableRun = 0;
1011
+ // The line before broke after a compound's hyphen, which this one repeats
1012
+ // (`repeatHyphen`).
1013
+ let repeatPending = false;
443
1014
  while (tokenIdx < tokens.length) {
444
1015
  const isFirstLine = lineIndex === 0;
445
1016
  const lineIndent = indentPx > 0
446
1017
  ? (hanging ? (isFirstLine ? 0 : indentPx) : (isFirstLine ? indentPx : 0))
447
1018
  : 0;
448
- const lineMaxWidth = maxWidthPx - lineIndent;
1019
+ const lineMaxWidth = lineMeasure(maxWidthPx, options?.restWidths, lineIndex) - lineIndent;
449
1020
  const lineTokens = [];
450
1021
  let lineWidth = 0;
451
1022
  let lineHyphenated = false;
1023
+ let lineSyllable = false;
1024
+ // The line ends after a hyphen the word carries (EF-140).
1025
+ let lineHardHyphen = false;
452
1026
  // Consume leading spaces at line start (skip them)
453
1027
  while (tokenIdx < tokens.length && tokens[tokenIdx].kind === 'space') {
454
1028
  tokenIdx++;
455
1029
  }
1030
+ // The compound's hyphen, repeated: the tail it broke from opens the
1031
+ // line with it, measured.
1032
+ const lineRepeated = repeatPending && tokens[tokenIdx]?.kind === 'text';
1033
+ if (lineRepeated) {
1034
+ const tail = tokens[tokenIdx];
1035
+ tokens[tokenIdx] = withLeadingHyphen(tail, tail.hyphenWidth ?? measureTextWidth('-', tokenFont(tail, normalFont, boldFont, italicFont, boldItalicFont)) + letterSpacingPx);
1036
+ }
1037
+ repeatPending = false;
1038
+ // This line ends after a compound's hyphen the next one repeats.
1039
+ let lineRepeatNext = false;
456
1040
  // Greedy: add tokens until we overflow
457
1041
  while (tokenIdx < tokens.length) {
458
1042
  const token = tokens[tokenIdx];
@@ -463,65 +1047,150 @@ export function measureRichBlock(spans, normalFont, boldFont, italicFont, boldIt
463
1047
  continue;
464
1048
  }
465
1049
  // Doesn't fit. Try to split at a break point (a soft hyphen, a hard
466
- // hyphen inside the word, a URL joint).
1050
+ // hyphen inside the word, a URL joint, a dash, between ideographs).
467
1051
  if (token.kind === 'text' && token.breakPoints && token.breakPoints.length > 0) {
468
1052
  const remaining = lineMaxWidth - lineWidth;
469
- const markW = (bp) => (token.bareBreaks || bp.bare ? 0 : (token.hyphenWidth ?? 0));
1053
+ const plainBreak = (bp) => token.bareBreaks === true || bp.bare === true || bp.free === true;
1054
+ const markW = (bp) => (plainBreak(bp) ? 0 : (token.hyphenWidth ?? 0));
1055
+ // Hyphenation zone (ragged text): a dictionary syllable is taken only
1056
+ // when the word, sent whole to the next line, would leave more than
1057
+ // the zone empty at the end of this one, and never on a third line
1058
+ // in a row. The word's own joints (a hard hyphen, a URL's, a dash),
1059
+ // breaks between ideographs and the author's soft hyphens are always
1060
+ // candidates.
1061
+ const syllables = hyphenationZonePx === undefined
1062
+ || (syllableRun < MAX_RAGGED_HYPHEN_RUN
1063
+ && lineMaxWidth - (lineWidth - trailingSpaceWidth(lineTokens)) > hyphenationZonePx);
470
1064
  let chosen = null;
471
1065
  for (const bp of token.breakPoints) {
1066
+ if (!syllables && !plainBreak(bp) && !bp.author)
1067
+ continue;
472
1068
  if (bp.widthBefore + markW(bp) <= remaining)
473
1069
  chosen = bp;
474
1070
  else
475
1071
  break;
476
1072
  }
477
1073
  if (chosen) {
478
- const hyphenW = markW(chosen);
479
- const mark = token.bareBreaks || chosen.bare ? '' : '-';
480
- lineTokens.push({
481
- text: token.text.slice(0, chosen.charIndex) + mark,
482
- bold: token.bold,
483
- italic: token.italic,
484
- captionLabel: token.captionLabel,
485
- ...scriptOf(token),
486
- kind: 'text',
487
- width: chosen.widthBefore + hyphenW,
488
- });
489
- lineWidth += chosen.widthBefore + hyphenW;
1074
+ const mark = plainBreak(chosen) ? '' : '-';
1075
+ const split = splitToken(token, chosen, mark, markW(chosen));
1076
+ lineTokens.push(split.head);
1077
+ lineWidth += split.head.width;
490
1078
  lineHyphenated = true;
491
- const chosenIdx = chosen.charIndex;
492
- const chosenWidth = chosen.widthBefore;
493
- const residualBreakPoints = token.breakPoints
494
- .filter((bp) => bp.charIndex > chosenIdx)
495
- .map((bp) => ({ ...bp, charIndex: bp.charIndex - chosenIdx, widthBefore: bp.widthBefore - chosenWidth }));
496
- tokens[tokenIdx] = {
497
- text: token.text.slice(chosenIdx),
498
- bold: token.bold,
499
- italic: token.italic,
500
- captionLabel: token.captionLabel,
501
- ...scriptOf(token),
502
- kind: 'text',
503
- width: token.width - chosenWidth,
504
- ...(residualBreakPoints.length > 0
505
- ? { breakPoints: residualBreakPoints, hyphenWidth: token.hyphenWidth }
506
- : {}),
507
- ...(token.bareBreaks ? { bareBreaks: true } : {}),
508
- };
1079
+ lineSyllable = mark !== '' && !chosen.author;
1080
+ lineHardHyphen = chosen.bare === true;
1081
+ lineRepeatNext = repeatHyphen && chosen.bare === true && !token.bareBreaks;
1082
+ tokens[tokenIdx] = split.tail;
509
1083
  break;
510
1084
  }
511
1085
  }
512
1086
  // A word wider than the whole line: divide it rather than let it run
513
1087
  // past the measure (syllable first, then character).
514
- if (lineTokens.length === 0 && token.kind === 'text' && !token.mathRender && !token.swatch && !token.chip && token.refResourceId === undefined && token.width > lineMaxWidth) {
1088
+ if (lineTokens.length === 0 && isDivisible(token) && token.width > lineMaxWidth) {
515
1089
  const font = tokenFont(token, normalFont, boldFont, italicFont, boldItalicFont);
516
1090
  const split = emergencySplit(token, font, letterSpacingPx, lineMaxWidth);
517
1091
  if (split) {
518
1092
  lineTokens.push(split.head);
519
1093
  lineWidth += split.head.width;
520
1094
  lineHyphenated = true;
1095
+ lineHardHyphen = split.hard === true;
1096
+ lineRepeatNext = repeatHyphen && split.hard === true && !token.bareBreaks;
521
1097
  tokens[tokenIdx] = split.tail;
522
1098
  break;
523
1099
  }
524
1100
  }
1101
+ // The token touches the line's last one with no space between (a word
1102
+ // set in two runs, a parenthesis before a bold word): the line may not
1103
+ // break there, except between two ideographs.
1104
+ const glued = token.kind !== 'space' ? gluedTailLength(lineTokens) : 0;
1105
+ if (glued > 0) {
1106
+ const prev = lineTokens[lineTokens.length - 1];
1107
+ const font = tokenFont(token, normalFont, boldFont, italicFont, boldItalicFont);
1108
+ if (token.stacked !== 'second' && cjkJoinBreaks(prev.text, token.text, font)) {
1109
+ // The line ends inside the run: no space is consumed.
1110
+ lineHyphenated = true;
1111
+ break;
1112
+ }
1113
+ // The group's latest plain break (between ideographs, a dash, a
1114
+ // hard hyphen) ends the line: kinsoku keeps 。 off the next line's
1115
+ // start by taking the ideograph before it along.
1116
+ const back = lastPlainBreakInGroup(lineTokens, glued);
1117
+ if (back && 'join' in back) {
1118
+ // After the dash that closes a run: the runs after it go down.
1119
+ const keep = back.at + 1;
1120
+ tokenIdx -= lineTokens.length - keep;
1121
+ while (lineTokens.length > keep)
1122
+ lineWidth -= lineTokens.pop().width;
1123
+ lineHyphenated = true;
1124
+ break;
1125
+ }
1126
+ if (back) {
1127
+ const origIdx = tokenIdx - (lineTokens.length - back.at);
1128
+ while (lineTokens.length > back.at)
1129
+ lineWidth -= lineTokens.pop().width;
1130
+ const split = splitToken(back.token, back.bp, '', 0);
1131
+ lineTokens.push(split.head);
1132
+ lineWidth += split.head.width;
1133
+ tokens[origIdx] = split.tail;
1134
+ tokenIdx = origIdx;
1135
+ lineHyphenated = true;
1136
+ lineHardHyphen = back.bp.bare === true;
1137
+ lineRepeatNext = repeatHyphen && back.bp.bare === true && !back.token.bareBreaks;
1138
+ break;
1139
+ }
1140
+ if (glued < lineTokens.length) {
1141
+ // Send the whole group down: the line ends at the space before it.
1142
+ for (let k = 0; k < glued; k++)
1143
+ lineWidth -= lineTokens.pop().width;
1144
+ tokenIdx -= glued;
1145
+ break;
1146
+ }
1147
+ // The group opens the line, so it is wider than the line: divide this
1148
+ // word at a syllable where the line ends.
1149
+ if (isDivisible(token)) {
1150
+ const split = emergencySplit(token, font, letterSpacingPx, lineMaxWidth - lineWidth, true);
1151
+ if (split) {
1152
+ lineTokens.push(split.head);
1153
+ lineWidth += split.head.width;
1154
+ lineHyphenated = true;
1155
+ lineHardHyphen = split.hard === true;
1156
+ lineRepeatNext = repeatHyphen && split.hard === true && !token.bareBreaks;
1157
+ tokens[tokenIdx] = split.tail;
1158
+ break;
1159
+ }
1160
+ }
1161
+ // Or at the last syllable of the group's own words, so the tail goes
1162
+ // down with what touches it: the full stop after **osmosis** never
1163
+ // opens a line alone (EF-73). When there is none, the line ends where
1164
+ // the runs meet, as before.
1165
+ const syllable = lastSyllableInGroup(lineTokens, glued, lineMaxWidth);
1166
+ if (syllable) {
1167
+ const origIdx = tokenIdx - (lineTokens.length - syllable.at);
1168
+ while (lineTokens.length > syllable.at)
1169
+ lineWidth -= lineTokens.pop().width;
1170
+ const split = splitToken(syllable.token, syllable.bp, '-', syllable.token.hyphenWidth ?? 0);
1171
+ lineTokens.push(split.head);
1172
+ lineWidth += split.head.width;
1173
+ tokens[origIdx] = split.tail;
1174
+ tokenIdx = origIdx;
1175
+ lineHyphenated = true;
1176
+ lineSyllable = true;
1177
+ break;
1178
+ }
1179
+ }
1180
+ // Two stacked scripts never part (EF-80): the line ends before the
1181
+ // pair, or takes it whole when the pair opens it.
1182
+ if (token.stacked === 'second' && lineTokens[lineTokens.length - 1]?.stacked === 'first') {
1183
+ if (lineTokens.length > 1) {
1184
+ lineWidth -= lineTokens.pop().width;
1185
+ tokenIdx--;
1186
+ }
1187
+ else {
1188
+ lineTokens.push(token);
1189
+ lineWidth += token.width;
1190
+ tokenIdx++;
1191
+ }
1192
+ break;
1193
+ }
525
1194
  // No viable split. If line is empty, force-fit this token; else break to next line.
526
1195
  if (lineTokens.length === 0) {
527
1196
  lineTokens.push(token);
@@ -532,6 +1201,8 @@ export function measureRichBlock(spans, normalFont, boldFont, italicFont, boldIt
532
1201
  }
533
1202
  if (lineTokens.length === 0)
534
1203
  break;
1204
+ syllableRun = lineSyllable ? syllableRun + 1 : 0;
1205
+ repeatPending = lineRepeatNext;
535
1206
  // Trim trailing spaces from line tokens
536
1207
  while (lineTokens.length > 0 && lineTokens[lineTokens.length - 1].kind === 'space') {
537
1208
  lineWidth -= lineTokens[lineTokens.length - 1].width;
@@ -557,6 +1228,8 @@ export function measureRichBlock(spans, normalFont, boldFont, italicFont, boldIt
557
1228
  ...(t.refResourceId !== undefined ? { refResourceId: t.refResourceId } : {}),
558
1229
  ...(t.captionLabel ? { captionLabel: true } : {}),
559
1230
  ...(t.script ? { script: t.script, fontString: t.scriptFont, baselineShift: t.baselineShift } : {}),
1231
+ ...(t.stacked === 'first' ? { stacked: true } : {}),
1232
+ ...(t.smallCaps ? { smallCaps: true } : {}),
560
1233
  })));
561
1234
  const lineText = lineTokens.map((t) => cleanSoftHyphens(t.text)).join('');
562
1235
  const contentWidth = segments.reduce((sum, t) => sum + t.width, 0);
@@ -566,6 +1239,8 @@ export function measureRichBlock(spans, normalFont, boldFont, italicFont, boldIt
566
1239
  bbox: createBoundingBox(lineIndent, y, contentWidth, lineHeightPx),
567
1240
  baseline: y + lineHeightPx * 0.8,
568
1241
  hyphenated: lineHyphenated,
1242
+ ...(lineHyphenated && lineHardHyphen ? { hardHyphen: true } : {}),
1243
+ ...(lineRepeated && lineText.startsWith('-') ? { repeatedHyphen: true } : {}),
569
1244
  segments,
570
1245
  isLastLine,
571
1246
  ...(justifiedSpaceRatio !== undefined ? { justifiedSpaceRatio } : {}),
@@ -573,6 +1248,8 @@ export function measureRichBlock(spans, normalFont, boldFont, italicFont, boldIt
573
1248
  y += lineHeightPx;
574
1249
  lineIndex++;
575
1250
  }
1251
+ if (hasSmallCaps)
1252
+ expandSmallCaps(lines, normalFont, boldFont, italicFont, boldItalicFont, letterSpacingPx);
576
1253
  return { lines, totalHeight: y };
577
1254
  }
578
1255
  //# sourceMappingURL=rich.js.map