postext 1.8.5 → 1.9.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 (565) hide show
  1. package/dist/__bench__/cjkChapter.bench.test.d.ts +2 -0
  2. package/dist/__bench__/cjkChapter.bench.test.d.ts.map +1 -0
  3. package/dist/__bench__/cjkChapter.bench.test.js +71 -0
  4. package/dist/__bench__/cjkChapter.bench.test.js.map +1 -0
  5. package/dist/__tests__/bundle.test.js +16 -0
  6. package/dist/__tests__/bundle.test.js.map +1 -1
  7. package/dist/__tests__/canvasDirection.test.d.ts +2 -0
  8. package/dist/__tests__/canvasDirection.test.d.ts.map +1 -0
  9. package/dist/__tests__/canvasDirection.test.js +45 -0
  10. package/dist/__tests__/canvasDirection.test.js.map +1 -0
  11. package/dist/__tests__/chineseLocale.test.d.ts +2 -0
  12. package/dist/__tests__/chineseLocale.test.d.ts.map +1 -0
  13. package/dist/__tests__/chineseLocale.test.js +253 -0
  14. package/dist/__tests__/chineseLocale.test.js.map +1 -0
  15. package/dist/__tests__/chineseNumbering.test.d.ts +2 -0
  16. package/dist/__tests__/chineseNumbering.test.d.ts.map +1 -0
  17. package/dist/__tests__/chineseNumbering.test.js +376 -0
  18. package/dist/__tests__/chineseNumbering.test.js.map +1 -0
  19. package/dist/__tests__/cjk/annotations.test.d.ts +2 -0
  20. package/dist/__tests__/cjk/annotations.test.d.ts.map +1 -0
  21. package/dist/__tests__/cjk/annotations.test.js +483 -0
  22. package/dist/__tests__/cjk/annotations.test.js.map +1 -0
  23. package/dist/__tests__/cjk/annotationsRender.test.d.ts +2 -0
  24. package/dist/__tests__/cjk/annotationsRender.test.d.ts.map +1 -0
  25. package/dist/__tests__/cjk/annotationsRender.test.js +263 -0
  26. package/dist/__tests__/cjk/annotationsRender.test.js.map +1 -0
  27. package/dist/__tests__/cjk/composer.test.d.ts +2 -0
  28. package/dist/__tests__/cjk/composer.test.d.ts.map +1 -0
  29. package/dist/__tests__/cjk/composer.test.js +237 -0
  30. package/dist/__tests__/cjk/composer.test.js.map +1 -0
  31. package/dist/__tests__/cjk/composerEdges.test.d.ts +2 -0
  32. package/dist/__tests__/cjk/composerEdges.test.d.ts.map +1 -0
  33. package/dist/__tests__/cjk/composerEdges.test.js +352 -0
  34. package/dist/__tests__/cjk/composerEdges.test.js.map +1 -0
  35. package/dist/__tests__/cjk/dashRule.test.d.ts +2 -0
  36. package/dist/__tests__/cjk/dashRule.test.d.ts.map +1 -0
  37. package/dist/__tests__/cjk/dashRule.test.js +261 -0
  38. package/dist/__tests__/cjk/dashRule.test.js.map +1 -0
  39. package/dist/__tests__/cjk/fuzz.test.d.ts +2 -0
  40. package/dist/__tests__/cjk/fuzz.test.d.ts.map +1 -0
  41. package/dist/__tests__/cjk/fuzz.test.js +102 -0
  42. package/dist/__tests__/cjk/fuzz.test.js.map +1 -0
  43. package/dist/__tests__/cjk/grid.test.d.ts +2 -0
  44. package/dist/__tests__/cjk/grid.test.d.ts.map +1 -0
  45. package/dist/__tests__/cjk/grid.test.js +261 -0
  46. package/dist/__tests__/cjk/grid.test.js.map +1 -0
  47. package/dist/__tests__/cjk/justifyRender.test.d.ts +2 -0
  48. package/dist/__tests__/cjk/justifyRender.test.d.ts.map +1 -0
  49. package/dist/__tests__/cjk/justifyRender.test.js +139 -0
  50. package/dist/__tests__/cjk/justifyRender.test.js.map +1 -0
  51. package/dist/__tests__/cjk/latinFastPath.test.d.ts +2 -0
  52. package/dist/__tests__/cjk/latinFastPath.test.d.ts.map +1 -0
  53. package/dist/__tests__/cjk/latinFastPath.test.js +208 -0
  54. package/dist/__tests__/cjk/latinFastPath.test.js.map +1 -0
  55. package/dist/__tests__/cjk/markCutsLatin.test.d.ts +2 -0
  56. package/dist/__tests__/cjk/markCutsLatin.test.d.ts.map +1 -0
  57. package/dist/__tests__/cjk/markCutsLatin.test.js +69 -0
  58. package/dist/__tests__/cjk/markCutsLatin.test.js.map +1 -0
  59. package/dist/__tests__/cjk/markRuns.test.d.ts +2 -0
  60. package/dist/__tests__/cjk/markRuns.test.d.ts.map +1 -0
  61. package/dist/__tests__/cjk/markRuns.test.js +347 -0
  62. package/dist/__tests__/cjk/markRuns.test.js.map +1 -0
  63. package/dist/__tests__/cjk/punctuation.test.d.ts +2 -0
  64. package/dist/__tests__/cjk/punctuation.test.d.ts.map +1 -0
  65. package/dist/__tests__/cjk/punctuation.test.js +440 -0
  66. package/dist/__tests__/cjk/punctuation.test.js.map +1 -0
  67. package/dist/__tests__/cjk/punctuationRender.test.d.ts +2 -0
  68. package/dist/__tests__/cjk/punctuationRender.test.d.ts.map +1 -0
  69. package/dist/__tests__/cjk/punctuationRender.test.js +135 -0
  70. package/dist/__tests__/cjk/punctuationRender.test.js.map +1 -0
  71. package/dist/__tests__/cjk/rubyDescenders.test.d.ts +2 -0
  72. package/dist/__tests__/cjk/rubyDescenders.test.d.ts.map +1 -0
  73. package/dist/__tests__/cjk/rubyDescenders.test.js +77 -0
  74. package/dist/__tests__/cjk/rubyDescenders.test.js.map +1 -0
  75. package/dist/__tests__/cjk/runt.test.d.ts +2 -0
  76. package/dist/__tests__/cjk/runt.test.d.ts.map +1 -0
  77. package/dist/__tests__/cjk/runt.test.js +103 -0
  78. package/dist/__tests__/cjk/runt.test.js.map +1 -0
  79. package/dist/__tests__/cjk/sharedMarks.test.d.ts +2 -0
  80. package/dist/__tests__/cjk/sharedMarks.test.d.ts.map +1 -0
  81. package/dist/__tests__/cjk/sharedMarks.test.js +347 -0
  82. package/dist/__tests__/cjk/sharedMarks.test.js.map +1 -0
  83. package/dist/__tests__/cjk/uprightDots.test.d.ts +2 -0
  84. package/dist/__tests__/cjk/uprightDots.test.d.ts.map +1 -0
  85. package/dist/__tests__/cjk/uprightDots.test.js +47 -0
  86. package/dist/__tests__/cjk/uprightDots.test.js.map +1 -0
  87. package/dist/__tests__/cjk/wordJoiner.test.d.ts +2 -0
  88. package/dist/__tests__/cjk/wordJoiner.test.d.ts.map +1 -0
  89. package/dist/__tests__/cjk/wordJoiner.test.js +47 -0
  90. package/dist/__tests__/cjk/wordJoiner.test.js.map +1 -0
  91. package/dist/__tests__/cjk/zhuyinTones.test.d.ts +2 -0
  92. package/dist/__tests__/cjk/zhuyinTones.test.d.ts.map +1 -0
  93. package/dist/__tests__/cjk/zhuyinTones.test.js +72 -0
  94. package/dist/__tests__/cjk/zhuyinTones.test.js.map +1 -0
  95. package/dist/__tests__/contentLocale.test.d.ts +2 -0
  96. package/dist/__tests__/contentLocale.test.d.ts.map +1 -0
  97. package/dist/__tests__/contentLocale.test.js +167 -0
  98. package/dist/__tests__/contentLocale.test.js.map +1 -0
  99. package/dist/__tests__/defaults/cjk.test.d.ts +2 -0
  100. package/dist/__tests__/defaults/cjk.test.d.ts.map +1 -0
  101. package/dist/__tests__/defaults/cjk.test.js +70 -0
  102. package/dist/__tests__/defaults/cjk.test.js.map +1 -0
  103. package/dist/__tests__/design/designTextRender.test.js +31 -0
  104. package/dist/__tests__/design/designTextRender.test.js.map +1 -1
  105. package/dist/__tests__/design/imageAltText.test.d.ts +2 -0
  106. package/dist/__tests__/design/imageAltText.test.d.ts.map +1 -0
  107. package/dist/__tests__/design/imageAltText.test.js +126 -0
  108. package/dist/__tests__/design/imageAltText.test.js.map +1 -0
  109. package/dist/__tests__/exports.test.js +61 -0
  110. package/dist/__tests__/exports.test.js.map +1 -1
  111. package/dist/__tests__/headingLetterSpacing.test.js +1 -1
  112. package/dist/__tests__/headingLetterSpacing.test.js.map +1 -1
  113. package/dist/__tests__/indexChinese.test.d.ts +2 -0
  114. package/dist/__tests__/indexChinese.test.d.ts.map +1 -0
  115. package/dist/__tests__/indexChinese.test.js +190 -0
  116. package/dist/__tests__/indexChinese.test.js.map +1 -0
  117. package/dist/__tests__/parse/annotations.test.d.ts +2 -0
  118. package/dist/__tests__/parse/annotations.test.d.ts.map +1 -0
  119. package/dist/__tests__/parse/annotations.test.js +175 -0
  120. package/dist/__tests__/parse/annotations.test.js.map +1 -0
  121. package/dist/__tests__/parse/attrQuoting.test.js +10 -8
  122. package/dist/__tests__/parse/attrQuoting.test.js.map +1 -1
  123. package/dist/__tests__/parse/chineseText.test.d.ts +2 -0
  124. package/dist/__tests__/parse/chineseText.test.d.ts.map +1 -0
  125. package/dist/__tests__/parse/chineseText.test.js +352 -0
  126. package/dist/__tests__/parse/chineseText.test.js.map +1 -0
  127. package/dist/__tests__/parts.test.js +25 -0
  128. package/dist/__tests__/parts.test.js.map +1 -1
  129. package/dist/__tests__/pipeline/colonListRoom.test.js +20 -0
  130. package/dist/__tests__/pipeline/colonListRoom.test.js.map +1 -1
  131. package/dist/__tests__/presets/hongloumeng.test.d.ts +2 -0
  132. package/dist/__tests__/presets/hongloumeng.test.d.ts.map +1 -0
  133. package/dist/__tests__/presets/hongloumeng.test.js +484 -0
  134. package/dist/__tests__/presets/hongloumeng.test.js.map +1 -0
  135. package/dist/__tests__/vertical/canvasPaint.test.d.ts +2 -0
  136. package/dist/__tests__/vertical/canvasPaint.test.d.ts.map +1 -0
  137. package/dist/__tests__/vertical/canvasPaint.test.js +229 -0
  138. package/dist/__tests__/vertical/canvasPaint.test.js.map +1 -0
  139. package/dist/__tests__/vertical/compositionPaint.test.d.ts +2 -0
  140. package/dist/__tests__/vertical/compositionPaint.test.d.ts.map +1 -0
  141. package/dist/__tests__/vertical/compositionPaint.test.js +538 -0
  142. package/dist/__tests__/vertical/compositionPaint.test.js.map +1 -0
  143. package/dist/__tests__/vertical/geometry.test.d.ts +2 -0
  144. package/dist/__tests__/vertical/geometry.test.d.ts.map +1 -0
  145. package/dist/__tests__/vertical/geometry.test.js +276 -0
  146. package/dist/__tests__/vertical/geometry.test.js.map +1 -0
  147. package/dist/__tests__/vertical/htmlSmoke.test.d.ts +2 -0
  148. package/dist/__tests__/vertical/htmlSmoke.test.d.ts.map +1 -0
  149. package/dist/__tests__/vertical/htmlSmoke.test.js +25 -0
  150. package/dist/__tests__/vertical/htmlSmoke.test.js.map +1 -0
  151. package/dist/__tests__/vertical/htmlTurnedCells.test.d.ts +2 -0
  152. package/dist/__tests__/vertical/htmlTurnedCells.test.d.ts.map +1 -0
  153. package/dist/__tests__/vertical/htmlTurnedCells.test.js +99 -0
  154. package/dist/__tests__/vertical/htmlTurnedCells.test.js.map +1 -0
  155. package/dist/__tests__/vertical/htmlVertical.test.d.ts +2 -0
  156. package/dist/__tests__/vertical/htmlVertical.test.d.ts.map +1 -0
  157. package/dist/__tests__/vertical/htmlVertical.test.js +145 -0
  158. package/dist/__tests__/vertical/htmlVertical.test.js.map +1 -0
  159. package/dist/__tests__/vertical/lineAxis.test.d.ts +2 -0
  160. package/dist/__tests__/vertical/lineAxis.test.d.ts.map +1 -0
  161. package/dist/__tests__/vertical/lineAxis.test.js +128 -0
  162. package/dist/__tests__/vertical/lineAxis.test.js.map +1 -0
  163. package/dist/__tests__/vertical/measurePaint.test.d.ts +2 -0
  164. package/dist/__tests__/vertical/measurePaint.test.d.ts.map +1 -0
  165. package/dist/__tests__/vertical/measurePaint.test.js +259 -0
  166. package/dist/__tests__/vertical/measurePaint.test.js.map +1 -0
  167. package/dist/__tests__/vertical/orientation.test.d.ts +2 -0
  168. package/dist/__tests__/vertical/orientation.test.d.ts.map +1 -0
  169. package/dist/__tests__/vertical/orientation.test.js +153 -0
  170. package/dist/__tests__/vertical/orientation.test.js.map +1 -0
  171. package/dist/__tests__/vertical/stub.d.ts +8 -0
  172. package/dist/__tests__/vertical/stub.d.ts.map +1 -0
  173. package/dist/__tests__/vertical/stub.js +37 -0
  174. package/dist/__tests__/vertical/stub.js.map +1 -0
  175. package/dist/__tests__/vertical/tateChuYoko.test.d.ts +2 -0
  176. package/dist/__tests__/vertical/tateChuYoko.test.d.ts.map +1 -0
  177. package/dist/__tests__/vertical/tateChuYoko.test.js +270 -0
  178. package/dist/__tests__/vertical/tateChuYoko.test.js.map +1 -0
  179. package/dist/__tests__/vertical/uprightResources.test.d.ts +2 -0
  180. package/dist/__tests__/vertical/uprightResources.test.d.ts.map +1 -0
  181. package/dist/__tests__/vertical/uprightResources.test.js +182 -0
  182. package/dist/__tests__/vertical/uprightResources.test.js.map +1 -0
  183. package/dist/__tests__/vertical/verticalDesignText.test.d.ts +2 -0
  184. package/dist/__tests__/vertical/verticalDesignText.test.d.ts.map +1 -0
  185. package/dist/__tests__/vertical/verticalDesignText.test.js +190 -0
  186. package/dist/__tests__/vertical/verticalDesignText.test.js.map +1 -0
  187. package/dist/__tests__/vertical/verticalSpans.d.ts +25 -0
  188. package/dist/__tests__/vertical/verticalSpans.d.ts.map +1 -0
  189. package/dist/__tests__/vertical/verticalSpans.js +39 -0
  190. package/dist/__tests__/vertical/verticalSpans.js.map +1 -0
  191. package/dist/__tests__/vertical/verticalTwins.test.d.ts +2 -0
  192. package/dist/__tests__/vertical/verticalTwins.test.d.ts.map +1 -0
  193. package/dist/__tests__/vertical/verticalTwins.test.js +71 -0
  194. package/dist/__tests__/vertical/verticalTwins.test.js.map +1 -0
  195. package/dist/bundle/adapters.d.ts +14 -5
  196. package/dist/bundle/adapters.d.ts.map +1 -1
  197. package/dist/bundle/adapters.js +4 -3
  198. package/dist/bundle/adapters.js.map +1 -1
  199. package/dist/bundle/codec.d.ts.map +1 -1
  200. package/dist/bundle/codec.js +27 -4
  201. package/dist/bundle/codec.js.map +1 -1
  202. package/dist/bundle/index.d.ts +1 -1
  203. package/dist/bundle/index.d.ts.map +1 -1
  204. package/dist/bundle/manifest.d.ts +6 -4
  205. package/dist/bundle/manifest.d.ts.map +1 -1
  206. package/dist/bundle/manifest.js +31 -32
  207. package/dist/bundle/manifest.js.map +1 -1
  208. package/dist/bundle/types.d.ts +7 -2
  209. package/dist/bundle/types.d.ts.map +1 -1
  210. package/dist/canvas-backend/annotations.d.ts +31 -0
  211. package/dist/canvas-backend/annotations.d.ts.map +1 -0
  212. package/dist/canvas-backend/annotations.js +120 -0
  213. package/dist/canvas-backend/annotations.js.map +1 -0
  214. package/dist/canvas-backend/blockRender.d.ts.map +1 -1
  215. package/dist/canvas-backend/blockRender.js +195 -15
  216. package/dist/canvas-backend/blockRender.js.map +1 -1
  217. package/dist/canvas-backend/decorations.d.ts +5 -0
  218. package/dist/canvas-backend/decorations.d.ts.map +1 -1
  219. package/dist/canvas-backend/decorations.js +27 -0
  220. package/dist/canvas-backend/decorations.js.map +1 -1
  221. package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
  222. package/dist/canvas-backend/headerFooter.js +32 -16
  223. package/dist/canvas-backend/headerFooter.js.map +1 -1
  224. package/dist/canvas-backend/index.d.ts +2 -0
  225. package/dist/canvas-backend/index.d.ts.map +1 -1
  226. package/dist/canvas-backend/index.js +62 -2
  227. package/dist/canvas-backend/index.js.map +1 -1
  228. package/dist/canvas-backend/renderResourceBlock.d.ts.map +1 -1
  229. package/dist/canvas-backend/renderResourceBlock.js +42 -5
  230. package/dist/canvas-backend/renderResourceBlock.js.map +1 -1
  231. package/dist/canvas-backend/segmentText.d.ts +23 -0
  232. package/dist/canvas-backend/segmentText.d.ts.map +1 -0
  233. package/dist/canvas-backend/segmentText.js +41 -0
  234. package/dist/canvas-backend/segmentText.js.map +1 -0
  235. package/dist/canvas-backend/verticalText.d.ts +113 -0
  236. package/dist/canvas-backend/verticalText.d.ts.map +1 -0
  237. package/dist/canvas-backend/verticalText.js +437 -0
  238. package/dist/canvas-backend/verticalText.js.map +1 -0
  239. package/dist/chineseNumerals.d.ts +39 -0
  240. package/dist/chineseNumerals.d.ts.map +1 -0
  241. package/dist/chineseNumerals.js +192 -0
  242. package/dist/chineseNumerals.js.map +1 -0
  243. package/dist/cjkMarks.d.ts +61 -0
  244. package/dist/cjkMarks.d.ts.map +1 -0
  245. package/dist/cjkMarks.js +441 -0
  246. package/dist/cjkMarks.js.map +1 -0
  247. package/dist/columnClip.d.ts +13 -4
  248. package/dist/columnClip.d.ts.map +1 -1
  249. package/dist/columnClip.js +33 -5
  250. package/dist/columnClip.js.map +1 -1
  251. package/dist/configWarnings.d.ts.map +1 -1
  252. package/dist/configWarnings.js +18 -3
  253. package/dist/configWarnings.js.map +1 -1
  254. package/dist/defaults/bodyText.d.ts +4 -1
  255. package/dist/defaults/bodyText.d.ts.map +1 -1
  256. package/dist/defaults/bodyText.js +27 -5
  257. package/dist/defaults/bodyText.js.map +1 -1
  258. package/dist/defaults/calloutStyles.js +1 -1
  259. package/dist/defaults/calloutStyles.js.map +1 -1
  260. package/dist/defaults/captionStyle.d.ts.map +1 -1
  261. package/dist/defaults/captionStyle.js +14 -0
  262. package/dist/defaults/captionStyle.js.map +1 -1
  263. package/dist/defaults/cjk.d.ts +33 -0
  264. package/dist/defaults/cjk.d.ts.map +1 -0
  265. package/dist/defaults/cjk.js +234 -0
  266. package/dist/defaults/cjk.js.map +1 -0
  267. package/dist/defaults/headerFooter.d.ts.map +1 -1
  268. package/dist/defaults/headerFooter.js +2 -0
  269. package/dist/defaults/headerFooter.js.map +1 -1
  270. package/dist/defaults/headingStyles.d.ts.map +1 -1
  271. package/dist/defaults/headingStyles.js +4 -0
  272. package/dist/defaults/headingStyles.js.map +1 -1
  273. package/dist/defaults/headings.d.ts.map +1 -1
  274. package/dist/defaults/headings.js +13 -6
  275. package/dist/defaults/headings.js.map +1 -1
  276. package/dist/defaults/index.d.ts +1 -0
  277. package/dist/defaults/index.d.ts.map +1 -1
  278. package/dist/defaults/index.js +10 -1
  279. package/dist/defaults/index.js.map +1 -1
  280. package/dist/defaults/indexConfig.d.ts +2 -1
  281. package/dist/defaults/indexConfig.d.ts.map +1 -1
  282. package/dist/defaults/indexConfig.js +5 -0
  283. package/dist/defaults/indexConfig.js.map +1 -1
  284. package/dist/defaults/layout.d.ts.map +1 -1
  285. package/dist/defaults/layout.js +7 -0
  286. package/dist/defaults/layout.js.map +1 -1
  287. package/dist/defaults/orderedLists.d.ts +5 -2
  288. package/dist/defaults/orderedLists.d.ts.map +1 -1
  289. package/dist/defaults/orderedLists.js +20 -5
  290. package/dist/defaults/orderedLists.js.map +1 -1
  291. package/dist/defaults/page.d.ts +8 -2
  292. package/dist/defaults/page.d.ts.map +1 -1
  293. package/dist/defaults/page.js +24 -7
  294. package/dist/defaults/page.js.map +1 -1
  295. package/dist/defaults/resourceTypes.d.ts +3 -3
  296. package/dist/defaults/resourceTypes.d.ts.map +1 -1
  297. package/dist/defaults/resourceTypes.js +23 -9
  298. package/dist/defaults/resourceTypes.js.map +1 -1
  299. package/dist/defaults/tableStyle.d.ts.map +1 -1
  300. package/dist/defaults/tableStyle.js +8 -5
  301. package/dist/defaults/tableStyle.js.map +1 -1
  302. package/dist/design/layout.d.ts +33 -0
  303. package/dist/design/layout.d.ts.map +1 -1
  304. package/dist/design/layout.js +124 -18
  305. package/dist/design/layout.js.map +1 -1
  306. package/dist/design/placeholders.d.ts.map +1 -1
  307. package/dist/design/placeholders.js +5 -1
  308. package/dist/design/placeholders.js.map +1 -1
  309. package/dist/design/richText.d.ts +24 -4
  310. package/dist/design/richText.d.ts.map +1 -1
  311. package/dist/design/richText.js +77 -16
  312. package/dist/design/richText.js.map +1 -1
  313. package/dist/html-backend.d.ts.map +1 -1
  314. package/dist/html-backend.js +635 -25
  315. package/dist/html-backend.js.map +1 -1
  316. package/dist/htmlAnnotations.d.ts +29 -0
  317. package/dist/htmlAnnotations.d.ts.map +1 -0
  318. package/dist/htmlAnnotations.js +86 -0
  319. package/dist/htmlAnnotations.js.map +1 -0
  320. package/dist/hyphenate.js +2 -1
  321. package/dist/hyphenate.js.map +1 -1
  322. package/dist/index.d.ts +28 -14
  323. package/dist/index.d.ts.map +1 -1
  324. package/dist/index.js +16 -8
  325. package/dist/index.js.map +1 -1
  326. package/dist/knuthPlass/pretextAdapter.d.ts +4 -1
  327. package/dist/knuthPlass/pretextAdapter.d.ts.map +1 -1
  328. package/dist/knuthPlass/pretextAdapter.js +9 -5
  329. package/dist/knuthPlass/pretextAdapter.js.map +1 -1
  330. package/dist/knuthPlass/richAdapter.d.ts +15 -2
  331. package/dist/knuthPlass/richAdapter.d.ts.map +1 -1
  332. package/dist/knuthPlass/richAdapter.js +16 -6
  333. package/dist/knuthPlass/richAdapter.js.map +1 -1
  334. package/dist/knuthPlass/tracking.d.ts +1 -1
  335. package/dist/knuthPlass/tracking.d.ts.map +1 -1
  336. package/dist/knuthPlass/tracking.js +4 -3
  337. package/dist/knuthPlass/tracking.js.map +1 -1
  338. package/dist/knuthPlass/types.d.ts +3 -0
  339. package/dist/knuthPlass/types.d.ts.map +1 -1
  340. package/dist/lineInk.d.ts +13 -0
  341. package/dist/lineInk.d.ts.map +1 -1
  342. package/dist/lineInk.js +28 -1
  343. package/dist/lineInk.js.map +1 -1
  344. package/dist/locale.d.ts +91 -3
  345. package/dist/locale.d.ts.map +1 -1
  346. package/dist/locale.js +245 -1
  347. package/dist/locale.js.map +1 -1
  348. package/dist/looseLines.d.ts +11 -1
  349. package/dist/looseLines.d.ts.map +1 -1
  350. package/dist/looseLines.js +26 -1
  351. package/dist/looseLines.js.map +1 -1
  352. package/dist/measure/cache.d.ts.map +1 -1
  353. package/dist/measure/cache.js +51 -3
  354. package/dist/measure/cache.js.map +1 -1
  355. package/dist/measure/canvas.d.ts +25 -0
  356. package/dist/measure/canvas.d.ts.map +1 -1
  357. package/dist/measure/canvas.js +90 -1
  358. package/dist/measure/canvas.js.map +1 -1
  359. package/dist/measure/cjk.d.ts +8 -13
  360. package/dist/measure/cjk.d.ts.map +1 -1
  361. package/dist/measure/cjk.js +29 -53
  362. package/dist/measure/cjk.js.map +1 -1
  363. package/dist/measure/cjkAnnotate.d.ts +96 -0
  364. package/dist/measure/cjkAnnotate.d.ts.map +1 -0
  365. package/dist/measure/cjkAnnotate.js +237 -0
  366. package/dist/measure/cjkAnnotate.js.map +1 -0
  367. package/dist/measure/cjkClasses.d.ts +133 -0
  368. package/dist/measure/cjkClasses.d.ts.map +1 -0
  369. package/dist/measure/cjkClasses.js +273 -0
  370. package/dist/measure/cjkClasses.js.map +1 -0
  371. package/dist/measure/cjkCompose.d.ts +86 -0
  372. package/dist/measure/cjkCompose.d.ts.map +1 -0
  373. package/dist/measure/cjkCompose.js +2022 -0
  374. package/dist/measure/cjkCompose.js.map +1 -0
  375. package/dist/measure/cjkPunctuation.d.ts +248 -0
  376. package/dist/measure/cjkPunctuation.d.ts.map +1 -0
  377. package/dist/measure/cjkPunctuation.js +492 -0
  378. package/dist/measure/cjkPunctuation.js.map +1 -0
  379. package/dist/measure/graphemes.d.ts +13 -0
  380. package/dist/measure/graphemes.d.ts.map +1 -0
  381. package/dist/measure/graphemes.js +38 -0
  382. package/dist/measure/graphemes.js.map +1 -0
  383. package/dist/measure/index.d.ts +3 -0
  384. package/dist/measure/index.d.ts.map +1 -1
  385. package/dist/measure/index.js +2 -0
  386. package/dist/measure/index.js.map +1 -1
  387. package/dist/measure/links.d.ts +6 -2
  388. package/dist/measure/links.d.ts.map +1 -1
  389. package/dist/measure/links.js +15 -5
  390. package/dist/measure/links.js.map +1 -1
  391. package/dist/measure/markCuts.d.ts +37 -0
  392. package/dist/measure/markCuts.d.ts.map +1 -0
  393. package/dist/measure/markCuts.js +77 -0
  394. package/dist/measure/markCuts.js.map +1 -0
  395. package/dist/measure/plain.d.ts.map +1 -1
  396. package/dist/measure/plain.js +33 -11
  397. package/dist/measure/plain.js.map +1 -1
  398. package/dist/measure/rich.d.ts +88 -1
  399. package/dist/measure/rich.d.ts.map +1 -1
  400. package/dist/measure/rich.js +233 -111
  401. package/dist/measure/rich.js.map +1 -1
  402. package/dist/measure/rubyLift.d.ts +11 -0
  403. package/dist/measure/rubyLift.d.ts.map +1 -0
  404. package/dist/measure/rubyLift.js +57 -0
  405. package/dist/measure/rubyLift.js.map +1 -0
  406. package/dist/measure/spaces.d.ts +12 -2
  407. package/dist/measure/spaces.d.ts.map +1 -1
  408. package/dist/measure/spaces.js +21 -7
  409. package/dist/measure/spaces.js.map +1 -1
  410. package/dist/measure/types.d.ts +20 -1
  411. package/dist/measure/types.d.ts.map +1 -1
  412. package/dist/measure/types.js.map +1 -1
  413. package/dist/measure/vertical.d.ts +104 -0
  414. package/dist/measure/vertical.d.ts.map +1 -0
  415. package/dist/measure/vertical.js +184 -0
  416. package/dist/measure/vertical.js.map +1 -0
  417. package/dist/numberWords.d.ts +3 -10
  418. package/dist/numberWords.d.ts.map +1 -1
  419. package/dist/numberWords.js +21 -9
  420. package/dist/numberWords.js.map +1 -1
  421. package/dist/numbering.d.ts +23 -5
  422. package/dist/numbering.d.ts.map +1 -1
  423. package/dist/numbering.js +99 -14
  424. package/dist/numbering.js.map +1 -1
  425. package/dist/parse/annotations.d.ts +101 -0
  426. package/dist/parse/annotations.d.ts.map +1 -0
  427. package/dist/parse/annotations.js +556 -0
  428. package/dist/parse/annotations.js.map +1 -0
  429. package/dist/parse/attrs.d.ts +48 -1
  430. package/dist/parse/attrs.d.ts.map +1 -1
  431. package/dist/parse/attrs.js +121 -8
  432. package/dist/parse/attrs.js.map +1 -1
  433. package/dist/parse/blockParser.d.ts.map +1 -1
  434. package/dist/parse/blockParser.js +50 -24
  435. package/dist/parse/blockParser.js.map +1 -1
  436. package/dist/parse/index.d.ts +3 -1
  437. package/dist/parse/index.d.ts.map +1 -1
  438. package/dist/parse/index.js +1 -0
  439. package/dist/parse/index.js.map +1 -1
  440. package/dist/parse/injectSpans.d.ts +3 -1
  441. package/dist/parse/injectSpans.d.ts.map +1 -1
  442. package/dist/parse/injectSpans.js +29 -8
  443. package/dist/parse/injectSpans.js.map +1 -1
  444. package/dist/parse/inlineFormatting.d.ts +38 -6
  445. package/dist/parse/inlineFormatting.d.ts.map +1 -1
  446. package/dist/parse/inlineFormatting.js +139 -26
  447. package/dist/parse/inlineFormatting.js.map +1 -1
  448. package/dist/parse/inlineSnippet.d.ts +2 -1
  449. package/dist/parse/inlineSnippet.d.ts.map +1 -1
  450. package/dist/parse/inlineSnippet.js +6 -2
  451. package/dist/parse/inlineSnippet.js.map +1 -1
  452. package/dist/parse/orientationMarks.d.ts +49 -0
  453. package/dist/parse/orientationMarks.d.ts.map +1 -0
  454. package/dist/parse/orientationMarks.js +138 -0
  455. package/dist/parse/orientationMarks.js.map +1 -0
  456. package/dist/parse/softBreaks.d.ts +56 -0
  457. package/dist/parse/softBreaks.d.ts.map +1 -0
  458. package/dist/parse/softBreaks.js +271 -0
  459. package/dist/parse/softBreaks.js.map +1 -0
  460. package/dist/parse/sourceMapping.d.ts.map +1 -1
  461. package/dist/parse/sourceMapping.js +41 -0
  462. package/dist/parse/sourceMapping.js.map +1 -1
  463. package/dist/parse/types.d.ts +84 -0
  464. package/dist/parse/types.d.ts.map +1 -1
  465. package/dist/pipeline/annotations.d.ts +56 -0
  466. package/dist/pipeline/annotations.d.ts.map +1 -0
  467. package/dist/pipeline/annotations.js +181 -0
  468. package/dist/pipeline/annotations.js.map +1 -0
  469. package/dist/pipeline/build.d.ts.map +1 -1
  470. package/dist/pipeline/build.js +158 -47
  471. package/dist/pipeline/build.js.map +1 -1
  472. package/dist/pipeline/buildBlockKind.d.ts +3 -0
  473. package/dist/pipeline/buildBlockKind.d.ts.map +1 -1
  474. package/dist/pipeline/buildBlockKind.js +5 -3
  475. package/dist/pipeline/buildBlockKind.js.map +1 -1
  476. package/dist/pipeline/buildHelpers.d.ts +36 -6
  477. package/dist/pipeline/buildHelpers.d.ts.map +1 -1
  478. package/dist/pipeline/buildHelpers.js +55 -8
  479. package/dist/pipeline/buildHelpers.js.map +1 -1
  480. package/dist/pipeline/buildMeasurement.d.ts +4 -0
  481. package/dist/pipeline/buildMeasurement.d.ts.map +1 -1
  482. package/dist/pipeline/buildMeasurement.js +3 -1
  483. package/dist/pipeline/buildMeasurement.js.map +1 -1
  484. package/dist/pipeline/calloutLayout.d.ts.map +1 -1
  485. package/dist/pipeline/calloutLayout.js +25 -11
  486. package/dist/pipeline/calloutLayout.js.map +1 -1
  487. package/dist/pipeline/cjkGrid.d.ts +133 -0
  488. package/dist/pipeline/cjkGrid.d.ts.map +1 -0
  489. package/dist/pipeline/cjkGrid.js +191 -0
  490. package/dist/pipeline/cjkGrid.js.map +1 -0
  491. package/dist/pipeline/config.d.ts +13 -9
  492. package/dist/pipeline/config.d.ts.map +1 -1
  493. package/dist/pipeline/config.js +43 -18
  494. package/dist/pipeline/config.js.map +1 -1
  495. package/dist/pipeline/contentWarnings.d.ts +10 -0
  496. package/dist/pipeline/contentWarnings.d.ts.map +1 -1
  497. package/dist/pipeline/contentWarnings.js +174 -2
  498. package/dist/pipeline/contentWarnings.js.map +1 -1
  499. package/dist/pipeline/floatPlacement.d.ts +9 -3
  500. package/dist/pipeline/floatPlacement.d.ts.map +1 -1
  501. package/dist/pipeline/floatPlacement.js +17 -6
  502. package/dist/pipeline/floatPlacement.js.map +1 -1
  503. package/dist/pipeline/headerFooter.d.ts +5 -2
  504. package/dist/pipeline/headerFooter.d.ts.map +1 -1
  505. package/dist/pipeline/headerFooter.js +123 -28
  506. package/dist/pipeline/headerFooter.js.map +1 -1
  507. package/dist/pipeline/headingDesignCuts.d.ts.map +1 -1
  508. package/dist/pipeline/headingDesignCuts.js +3 -1
  509. package/dist/pipeline/headingDesignCuts.js.map +1 -1
  510. package/dist/pipeline/headingStyles.d.ts +9 -3
  511. package/dist/pipeline/headingStyles.d.ts.map +1 -1
  512. package/dist/pipeline/headingStyles.js +23 -5
  513. package/dist/pipeline/headingStyles.js.map +1 -1
  514. package/dist/pipeline/indexDirective.d.ts.map +1 -1
  515. package/dist/pipeline/indexDirective.js +64 -20
  516. package/dist/pipeline/indexDirective.js.map +1 -1
  517. package/dist/pipeline/indexGroups.d.ts +55 -0
  518. package/dist/pipeline/indexGroups.d.ts.map +1 -0
  519. package/dist/pipeline/indexGroups.js +151 -0
  520. package/dist/pipeline/indexGroups.js.map +1 -0
  521. package/dist/pipeline/lists.d.ts +17 -0
  522. package/dist/pipeline/lists.d.ts.map +1 -1
  523. package/dist/pipeline/lists.js +43 -51
  524. package/dist/pipeline/lists.js.map +1 -1
  525. package/dist/pipeline/measureContentBlock.d.ts +3 -0
  526. package/dist/pipeline/measureContentBlock.d.ts.map +1 -1
  527. package/dist/pipeline/measureContentBlock.js +31 -4
  528. package/dist/pipeline/measureContentBlock.js.map +1 -1
  529. package/dist/pipeline/outline.d.ts.map +1 -1
  530. package/dist/pipeline/outline.js +13 -8
  531. package/dist/pipeline/outline.js.map +1 -1
  532. package/dist/pipeline/parts.d.ts +6 -3
  533. package/dist/pipeline/parts.d.ts.map +1 -1
  534. package/dist/pipeline/parts.js +28 -5
  535. package/dist/pipeline/parts.js.map +1 -1
  536. package/dist/pipeline/placeholders.d.ts +11 -0
  537. package/dist/pipeline/placeholders.d.ts.map +1 -1
  538. package/dist/pipeline/placeholders.js +48 -18
  539. package/dist/pipeline/placeholders.js.map +1 -1
  540. package/dist/pipeline/placement.d.ts +10 -6
  541. package/dist/pipeline/placement.d.ts.map +1 -1
  542. package/dist/pipeline/placement.js +33 -16
  543. package/dist/pipeline/placement.js.map +1 -1
  544. package/dist/pipeline/resourceLayout.d.ts +18 -1
  545. package/dist/pipeline/resourceLayout.d.ts.map +1 -1
  546. package/dist/pipeline/resourceLayout.js +109 -21
  547. package/dist/pipeline/resourceLayout.js.map +1 -1
  548. package/dist/pipeline/toc.d.ts.map +1 -1
  549. package/dist/pipeline/toc.js +6 -5
  550. package/dist/pipeline/toc.js.map +1 -1
  551. package/dist/pipeline/verticalMetrics.d.ts +14 -0
  552. package/dist/pipeline/verticalMetrics.d.ts.map +1 -0
  553. package/dist/pipeline/verticalMetrics.js +154 -0
  554. package/dist/pipeline/verticalMetrics.js.map +1 -0
  555. package/dist/types.d.ts +344 -13
  556. package/dist/types.d.ts.map +1 -1
  557. package/dist/vdt.d.ts +396 -6
  558. package/dist/vdt.d.ts.map +1 -1
  559. package/dist/vdt.js +49 -0
  560. package/dist/vdt.js.map +1 -1
  561. package/dist/writingMode.d.ts +156 -0
  562. package/dist/writingMode.d.ts.map +1 -0
  563. package/dist/writingMode.js +291 -0
  564. package/dist/writingMode.js.map +1 -0
  565. package/package.json +1 -1
@@ -0,0 +1,347 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { buildDocument, renderPageToCanvas } from '../../index';
3
+ import { renderToHtml } from '../../html-backend';
4
+ import { measureRichBlock } from '../../measure/rich';
5
+ import { clearTextWidthCache } from '../../measure/canvas';
6
+ import { withMeasureWritingMode } from '../../measure/vertical';
7
+ // “ ” ‘ ’ … — · are shared by Latin and Chinese text. A font may set them
8
+ // proportionally (LXGW WenKai: “ ” at 0.35 em; Noto Serif SC: the em dash
9
+ // at 0.89 em, · at a third of an em). In Chinese text they take the box of
10
+ // a Chinese mark whatever the font's advance, with the glyph where a
11
+ // Chinese font puts it; next to Western text they keep their own advance.
12
+ const EM = 16;
13
+ const SIZE_RE = /(\d*\.?\d+)px/;
14
+ /** Advances in em: the shared marks proportional, as in LXGW WenKai. */
15
+ const PROPORTIONAL = { '“': 0.35, '”': 0.35, '‘': 0.35, '’': 0.35, '…': 0.8, '—': 0.9, '·': 0.3 };
16
+ const charWidth = (ch, em) => {
17
+ if (ch in PROPORTIONAL)
18
+ return PROPORTIONAL[ch] * em;
19
+ if (ch === ' ')
20
+ return em / 4;
21
+ return ch.codePointAt(0) >= 0x2e80 ? em : em / 2;
22
+ };
23
+ /** Kerning of whole runs, em. */
24
+ const KERN = {};
25
+ const width = (s, em) => {
26
+ let w = 0;
27
+ for (const ch of s)
28
+ w += charWidth(ch, em);
29
+ for (const [pair, k] of Object.entries(KERN))
30
+ if (s.includes(pair))
31
+ w += k * em;
32
+ return w;
33
+ };
34
+ /** Whether the stub gives ink metrics (a measurer without them sets a
35
+ * 破折号 as the font sets the pair). */
36
+ let INK = true;
37
+ class StubCtx {
38
+ font = `${EM}px Test`;
39
+ letterSpacing = '0px';
40
+ measureText(s) {
41
+ const em = Number(SIZE_RE.exec(this.font)?.[1] ?? EM);
42
+ const w = width(s, em);
43
+ if (!INK)
44
+ return { width: w };
45
+ return { width: w, actualBoundingBoxAscent: em * 0.8, actualBoundingBoxDescent: em * 0.04, actualBoundingBoxLeft: 0, actualBoundingBoxRight: w };
46
+ }
47
+ }
48
+ globalThis.OffscreenCanvas = class {
49
+ getContext() {
50
+ return new StubCtx();
51
+ }
52
+ };
53
+ const FONT = `${EM}px "Test Kai"`;
54
+ const composition = (c = {}) => ({
55
+ region: 'mainland',
56
+ punctuationWidth: 'kaiming',
57
+ compressAdjacent: true,
58
+ trimLineStart: false,
59
+ hangingPunctuation: 'none',
60
+ latinSpacing: { em: 0 },
61
+ ...c,
62
+ });
63
+ const lines = (text, c = {}, measure = 40 * EM, textAlign = 'left') => measureRichBlock([{ text, bold: false, italic: false }], FONT, FONT, FONT, FONT, measure, 24, { textAlign, cjkLineBreak: 'gb', cjkComposition: composition(c) }).lines;
64
+ /** The segments holding exactly `text`, in order. */
65
+ const segs = (ls, text) => ls.flatMap((l) => l.segments ?? []).filter((s) => s.text === text);
66
+ describe('marks shared with Latin text take a Chinese box in Chinese text', () => {
67
+ it('sets proportional quotes in half-em Kaiming boxes, the opening glyph at the end of its box', () => {
68
+ const ls = lines('他说:“你来了。”她答:“好”。');
69
+ const open = segs(ls, '“');
70
+ const close = segs(ls, '”');
71
+ expect(open).toHaveLength(2);
72
+ expect(close).toHaveLength(2);
73
+ for (const s of open) {
74
+ // One em box, its half-em blank before the glyph given up (Kaiming):
75
+ // half an em, the 0.35-em glyph ending on the box's end.
76
+ expect(s.width).toBeCloseTo(EM / 2);
77
+ expect(s.inkOffset).toBeCloseTo(EM / 2 - 0.35 * EM);
78
+ expect(s.inkOffset + 0.35 * EM).toBeCloseTo(s.width);
79
+ }
80
+ // After 好 the closing quote is half an em; after 。 it holds the stop's
81
+ // half em after its glyph (。”␣), the glyph still at the start of its box.
82
+ expect(close.map((s) => s.width)).toEqual([EM, EM / 2]);
83
+ for (const s of close)
84
+ expect(s.inkOffset).toBe(0);
85
+ expect(segs(ls, '。')[0].width).toBeCloseTo(EM / 2);
86
+ });
87
+ it('sets them one em under full width, an opening quote against the text it opens', () => {
88
+ const ls = lines('他说“你来了。”', { punctuationWidth: 'fullwidth', compressAdjacent: false });
89
+ const [open] = segs(ls, '“');
90
+ const [close] = segs(ls, '”');
91
+ expect(open.width).toBeCloseTo(EM);
92
+ expect(open.inkOffset).toBeCloseTo(EM - 0.35 * EM);
93
+ expect(close.width).toBeCloseTo(EM);
94
+ expect(close.inkOffset).toBe(0);
95
+ // The line: 6 characters and two one-em quotes.
96
+ expect(ls[0].bbox.width).toBeCloseTo(8 * EM);
97
+ });
98
+ it('gives …… and —— one em per character: the ellipsis centred as the font sets it, the dash stretched over its ems', () => {
99
+ const ls = lines('忽念及当日——一一细考较去……觉其', { punctuationWidth: 'fullwidth', compressAdjacent: false });
100
+ const dashes = segs(ls, '—');
101
+ const dots = segs(ls, '…');
102
+ expect(dashes).toHaveLength(2);
103
+ expect(dots).toHaveLength(2);
104
+ for (const s of [...dashes, ...dots])
105
+ expect(s.width).toBeCloseTo(EM);
106
+ // The ellipsis meets at its middle, 0.2 em blank on its outer sides.
107
+ expect(dots[0].inkOffset).toBeCloseTo(0.2 * EM);
108
+ expect(dots[1].inkOffset).toBeCloseTo(0);
109
+ expect(dots[0].inkScale).toBeUndefined();
110
+ // Each 0.9-em dash (ink edge to edge in the stub) stretched over its em
111
+ // and 0.02 em past the join: one rule from 0 to 2 em.
112
+ const scale = 1.02 / 0.9;
113
+ for (const s of dashes)
114
+ expect(s.inkScale).toBeCloseTo(scale);
115
+ expect(dashes[0].inkOffset).toBeCloseTo(0);
116
+ expect(dashes[1].inkOffset).toBeCloseTo(-0.02 * EM);
117
+ expect(EM + dashes[1].inkOffset + 0.9 * EM * scale).toBeCloseTo(2 * EM);
118
+ expect(ls[0].bbox.width).toBeCloseTo(17 * EM);
119
+ });
120
+ it('keeps the kerning a face puts between the two dashes of a pair when the measurer gives no ink metrics', () => {
121
+ // Noto Serif SC: — 0.89 em, —— kerned 0.088 em tighter, so the two
122
+ // strokes join.
123
+ KERN['——'] = -0.088;
124
+ INK = false;
125
+ clearTextWidthCache();
126
+ try {
127
+ const ls = lines('女子——一一细考', { punctuationWidth: 'fullwidth', compressAdjacent: false });
128
+ const [a, b] = segs(ls, '—');
129
+ const pair = (2 * 0.9 - 0.088) * EM;
130
+ expect(a.width).toBeCloseTo(EM);
131
+ expect(b.width).toBeCloseTo(EM);
132
+ // The pair centred in its two ems; the second glyph starts where the
133
+ // font puts it, 0.088 em into the first one's advance.
134
+ expect(a.inkOffset).toBeCloseTo(EM - pair / 2);
135
+ expect(EM + b.inkOffset).toBeCloseTo(a.inkOffset + (0.9 - 0.088) * EM);
136
+ expect(a.inkScale).toBeUndefined();
137
+ }
138
+ finally {
139
+ delete KERN['——'];
140
+ INK = true;
141
+ clearTextWidthCache();
142
+ }
143
+ });
144
+ it('sets a single em dash and an interpunct centred; the mainland interpunct in half an em', () => {
145
+ const ls = lines('北京—上海,约翰·史密斯', { punctuationWidth: 'fullwidth', compressAdjacent: true });
146
+ const [dash] = segs(ls, '—');
147
+ expect(dash.width).toBeCloseTo(EM);
148
+ expect(dash.inkOffset).toBeCloseTo(0.05 * EM);
149
+ const [dot] = segs(ls, '·');
150
+ expect(dot.width).toBeCloseTo(EM / 2);
151
+ expect(dot.inkOffset).toBeCloseTo((EM / 2 - 0.3 * EM) / 2);
152
+ // Taiwan centres a one-em interpunct.
153
+ const [tw] = segs(lines('約翰·史密斯', { region: 'taiwan', punctuationWidth: 'fullwidth', compressAdjacent: false }), '·');
154
+ expect(tw.width).toBeCloseTo(EM);
155
+ expect(tw.inkOffset).toBeCloseTo((EM - 0.3 * EM) / 2);
156
+ });
157
+ it('compresses a shared mark against a Chinese one as a Chinese mark', () => {
158
+ // 。” under full width with compression: the stop gives up the blank
159
+ // between them, the quote keeps its em box: 1.5 em together.
160
+ const ls = lines('他说“你来了。”', { punctuationWidth: 'fullwidth', compressAdjacent: true });
161
+ const [stop] = segs(ls, '。');
162
+ const [close] = segs(ls, '”');
163
+ expect(stop.width).toBeCloseTo(EM / 2);
164
+ expect(close.width).toBeCloseTo(EM);
165
+ expect(close.inkOffset).toBe(0);
166
+ });
167
+ it('keeps their own advance next to Western text on both sides', () => {
168
+ // A Chinese paragraph (more CJK letters than word spaces) quoting an
169
+ // English sentence.
170
+ const ls = lines('他回答说:He said “yes” and left. 然后他回到家中休息了很久很久很久。');
171
+ const [open] = segs(ls, '“');
172
+ const [close] = segs(ls, '”');
173
+ expect(open.width).toBeCloseTo(0.35 * EM);
174
+ expect(open.inkOffset).toBeUndefined();
175
+ expect(close.width).toBeCloseTo(0.35 * EM);
176
+ // A quote between Chinese and Latin text is Chinese.
177
+ const mixed = lines('他说“OK”就走了。', { punctuationWidth: 'fullwidth', compressAdjacent: false });
178
+ expect(segs(mixed, '“')[0].width).toBeCloseTo(EM);
179
+ expect(segs(mixed, '”')[0].width).toBeCloseTo(EM);
180
+ });
181
+ it('leaves a mark whose glyph is one em wide as it was', () => {
182
+ PROPORTIONAL['“'] = 1;
183
+ PROPORTIONAL['”'] = 1;
184
+ clearTextWidthCache();
185
+ try {
186
+ const ls = lines('他说“你来了。”', { punctuationWidth: 'fullwidth', compressAdjacent: false });
187
+ // No box to place a glyph in: the characters share a segment.
188
+ expect(ls[0].segments.map((s) => s.text)).toEqual(['他说“你来了。”']);
189
+ }
190
+ finally {
191
+ PROPORTIONAL['“'] = 0.35;
192
+ PROPORTIONAL['”'] = 0.35;
193
+ clearTextWidthCache();
194
+ }
195
+ });
196
+ it('leaves vertical text to its cells', () => {
197
+ const ls = withMeasureWritingMode('vertical-rl', () => lines('他说“你来了。”', { punctuationWidth: 'fullwidth', compressAdjacent: false }));
198
+ for (const s of ls.flatMap((l) => l.segments ?? []))
199
+ expect(s.inkOffset).toBeUndefined();
200
+ expect(ls[0].bbox.width).toBeCloseTo(8 * EM);
201
+ });
202
+ it('sets the mainland interpunct in half an em under a composition that changes nothing else, as vertical text does', () => {
203
+ // Full width, no compression, no trims, no Han–Latin space: the plain
204
+ // composition. GB/T 15834 sets · and ・ in half an em whatever the
205
+ // punctuation style, in both writing modes.
206
+ const plain = { punctuationWidth: 'fullwidth', compressAdjacent: false, trimLineStart: false, latinSpacing: { em: 0 } };
207
+ for (const name of ['列夫·托尔斯泰', '列夫・托尔斯泰']) {
208
+ const across = lines(name, plain);
209
+ const down = withMeasureWritingMode('vertical-rl', () => lines(name, plain));
210
+ expect(across[0].bbox.width, name).toBeCloseTo(6.5 * EM);
211
+ expect(down[0].bbox.width, name).toBeCloseTo(6.5 * EM);
212
+ }
213
+ // The glyph centred in its half em: · (0.3 em) a tenth of an em in,
214
+ // ・ (one em) a quarter em before its box.
215
+ expect(segs(lines('列夫·托尔斯泰', plain), '·')[0].inkOffset).toBeCloseTo(0.1 * EM);
216
+ expect(segs(lines('列夫・托尔斯泰', plain), '・')[0].inkOffset).toBeCloseTo(-0.25 * EM);
217
+ // Taiwan keeps its one-em interpunct.
218
+ expect(lines('約翰・史密斯', { ...plain, region: 'taiwan' })[0].bbox.width).toBeCloseTo(6 * EM);
219
+ });
220
+ it('keeps their own advance in Japanese and Korean text', () => {
221
+ const ko = '그는 “안녕하세요”라고 말했다. 김철수·이영희 두 사람은 서울에서 부산까지…… 먼 길을 걸었다—정말로.';
222
+ const ja = '彼は“こんにちは”と言った。山田·田中の二人は東京から大阪まで……歩いた。';
223
+ const own = (ls) => {
224
+ const marks = ls.flatMap((l) => l.segments ?? []).filter((s) => /[“”·…—]/.test(s.text));
225
+ expect(marks.length).toBeGreaterThan(3);
226
+ for (const s of marks) {
227
+ expect(s.width, s.text).toBeCloseTo(width(s.text, EM));
228
+ expect(s.inkOffset, s.text).toBeUndefined();
229
+ }
230
+ };
231
+ own(lines(ko, { language: 'ko' }));
232
+ own(lines(ja, { language: 'ja' }));
233
+ // A paragraph with kana or hangul in a document of another language.
234
+ own(lines(ja, { language: 'en' }));
235
+ own(lines(ja));
236
+ // Chinese text in such a document routes them.
237
+ expect(segs(lines('他说“你来了。”', { language: 'en', punctuationWidth: 'fullwidth', compressAdjacent: false }), '“')[0].width).toBeCloseTo(EM);
238
+ // The document language reaches the composer through the locale.
239
+ const ragged = (locale) => {
240
+ const cfg = config(locale);
241
+ return { ...cfg, bodyText: { ...cfg.bodyText, textAlign: 'left' } };
242
+ };
243
+ for (const locale of ['ko', 'ja']) {
244
+ const doc = buildDocument({ markdown: locale === 'ko' ? ko : ja }, ragged(locale));
245
+ own(doc.blocks.filter((b) => b.type === 'paragraph').flatMap((b) => b.lines));
246
+ }
247
+ const zh = buildDocument({ markdown: '他说“你来了。”山田·田中' }, ragged('zh-Hans'));
248
+ const zhMarks = zh.blocks.filter((b) => b.type === 'paragraph').flatMap((b) => b.lines.flatMap((l) => l.segments ?? [])).filter((s) => /[“·]/.test(s.text));
249
+ expect(zhMarks.map((s) => s.inkOffset !== undefined)).toEqual([true, true]);
250
+ });
251
+ it('routes a long run of shared marks in linear time', () => {
252
+ const clock = globalThis.process;
253
+ const cpuMs = () => {
254
+ const usage = clock.threadCpuUsage?.() ?? clock.cpuUsage();
255
+ return (usage.user + usage.system) / 1000;
256
+ };
257
+ const time = (n) => {
258
+ const text = `他说${'“”'.repeat(n)}。`;
259
+ let best = Infinity;
260
+ for (let run = 0; run < 5; run++) {
261
+ clearTextWidthCache();
262
+ const t0 = cpuMs();
263
+ lines(text, {}, 30 * EM, 'justify');
264
+ best = Math.min(best, cpuMs() - t0);
265
+ }
266
+ return best;
267
+ };
268
+ time(500);
269
+ const small = Math.max(time(1000), 1);
270
+ const large = time(8000);
271
+ // Eight times the marks: linear is ~8×, quadratic ~64×.
272
+ expect(large / small).toBeLessThan(30);
273
+ });
274
+ });
275
+ const pt = (value) => ({ value, unit: 'pt' });
276
+ const config = (locale, cjk = {}) => ({
277
+ locale,
278
+ page: { width: pt(400), height: pt(400), dpi: 72, margins: { top: pt(20), bottom: pt(20), left: pt(20), right: pt(20) } },
279
+ layout: { layoutType: 'single' },
280
+ header: { elements: [] },
281
+ footer: { elements: [] },
282
+ bodyText: { fontFamily: 'Test Kai', fontSize: pt(EM), lineHeight: pt(24), textAlign: 'justify', firstLineIndent: pt(0), hyphenation: { enabled: false } },
283
+ cjk,
284
+ });
285
+ describe('renderers paint a shared mark in its Chinese box', () => {
286
+ it('canvas and HTML put each glyph at its box plus its ink offset', () => {
287
+ const doc = buildDocument({ markdown: '作者自云:因曾历过一番梦幻之后,故将真事隐去,而借“通灵”之说,撰此《石头记》一书也。忽念及当日所有之女子——一一细考较去……“风月宝鉴”。' }, config('zh-Hans'));
288
+ const block = doc.blocks.find((b) => b.type === 'paragraph');
289
+ const texts = [];
290
+ const target = { letterSpacing: '0px', font: FONT };
291
+ // The pen's horizontal transform: a stretched dash is painted at the
292
+ // origin of a translated, scaled context.
293
+ let tx = 0;
294
+ let sx = 1;
295
+ const saved = [];
296
+ const ctx = new Proxy(target, {
297
+ get(t, key) {
298
+ if (key === 'fillText')
299
+ return (text, x) => { texts.push({ text, x: tx + sx * x }); };
300
+ if (key === 'save')
301
+ return () => { saved.push([tx, sx]); };
302
+ if (key === 'restore')
303
+ return () => { [tx, sx] = saved.pop() ?? [0, 1]; };
304
+ if (key === 'translate')
305
+ return (x) => { tx += sx * x; };
306
+ if (key === 'scale')
307
+ return (x) => { sx *= x; };
308
+ if (key === 'measureText')
309
+ return (s) => ({ width: width(s, EM) });
310
+ if (key in t)
311
+ return t[key];
312
+ return () => undefined;
313
+ },
314
+ set(t, key, value) { t[key] = value; return true; },
315
+ });
316
+ renderPageToCanvas(doc.pages[0], doc, { width: 0, height: 0, getContext: () => ctx });
317
+ const html = renderToHtml(doc);
318
+ let checked = 0;
319
+ for (const line of block.lines) {
320
+ let x = line.bbox.x;
321
+ for (const s of line.segments ?? []) {
322
+ if (s.kind === 'text' && s.text.length === 1 && s.text in PROPORTIONAL) {
323
+ const at = x + s.inkOffset;
324
+ expect(texts.some((t) => t.text === s.text && Math.abs(t.x - at) < 1e-6), `${s.text} at ${at}`).toBe(true);
325
+ expect(html).toContain(`left:${(at - line.bbox.x).toFixed(3)}px;`);
326
+ if (s.inkScale !== undefined)
327
+ expect(html).toContain(`transform:scaleX(${s.inkScale.toFixed(4)})`);
328
+ checked++;
329
+ }
330
+ x += s.width;
331
+ }
332
+ }
333
+ // “通灵”, ——, ……, “风月宝鉴”.
334
+ expect(checked).toBe(8);
335
+ });
336
+ it('leaves a Latin paragraph quoting Chinese to the font', () => {
337
+ const doc = buildDocument({ markdown: 'The novel “紅樓夢” — also called “石頭記” — was written… by Cao Xueqin.' }, config('en'));
338
+ const block = doc.blocks.find((b) => b.type === 'paragraph');
339
+ const segments = block.lines.flatMap((l) => l.segments ?? []);
340
+ expect(segments.some((s) => s.inkOffset !== undefined)).toBe(false);
341
+ // Every word at the stub's own advances.
342
+ for (const s of segments)
343
+ if (s.kind === 'text')
344
+ expect(s.width).toBeCloseTo(width(s.text, EM));
345
+ });
346
+ });
347
+ //# sourceMappingURL=sharedMarks.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sharedMarks.test.js","sourceRoot":"","sources":["../../../src/__tests__/cjk/sharedMarks.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=uprightDots.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uprightDots.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/cjk/uprightDots.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,47 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { buildDocument } from '../../index';
3
+ import { SizedStubCtx, stubCharWidth } from '../vertical/stub';
4
+ // Emphasis dots over an `:upright[…]` run down a vertical line (#190 with
5
+ // #193): each letter stands in a cell of one em, so each dot is centred on
6
+ // its cell, whatever the letter's horizontal width. The stub is the sized
7
+ // one (CJK 1 em) with proportional Latin letters: W a full em, i a quarter,
8
+ // l three tenths, anything else half an em.
9
+ const LATIN = { W: 1, i: 0.25, l: 0.3 };
10
+ class ProportionalCtx extends SizedStubCtx {
11
+ measureText(s) {
12
+ const m = super.measureText(s);
13
+ const em = Number(/(\d*\.?\d+)px/.exec(this.font)?.[1] ?? 10);
14
+ let w = 0;
15
+ for (const ch of s)
16
+ w += LATIN[ch] !== undefined ? LATIN[ch] * em : stubCharWidth(ch, em);
17
+ return { ...m, width: w, actualBoundingBoxRight: w };
18
+ }
19
+ }
20
+ globalThis.OffscreenCanvas = class {
21
+ getContext() {
22
+ return new ProportionalCtx();
23
+ }
24
+ };
25
+ const pt = (value) => ({ value, unit: 'pt' });
26
+ const config = {
27
+ locale: 'zh-Hant',
28
+ page: { width: pt(440), height: pt(600), dpi: 72, margins: { top: pt(20), bottom: pt(20), left: pt(20), right: pt(20) } },
29
+ layout: { layoutType: 'single', writingMode: 'vertical-rl' },
30
+ header: { elements: [] },
31
+ footer: { elements: [] },
32
+ bodyText: { fontFamily: 'Proportional Test', fontSize: pt(20), lineHeight: pt(30), textAlign: 'left', firstLineIndent: pt(0), hyphenation: { enabled: false } },
33
+ cjk: { latinSpacing: { value: 0, unit: 'em' } },
34
+ };
35
+ const firstLine = (markdown) => buildDocument({ markdown }, config).blocks.find((b) => b.type === 'paragraph').lines[0];
36
+ describe('emphasis dots over upright letters in vertical text', () => {
37
+ it('centres a dot on each letter’s cell', () => {
38
+ const line = firstLine('甲:dots[:upright[Wil]]乙');
39
+ // 甲 takes 0–20 px; W, i and l a cell each after it.
40
+ expect(line.marks.filter((m) => m.kind === 'dot').map((m) => m.x)).toEqual([30, 50, 70]);
41
+ });
42
+ it('does the same with capitals and with digits', () => {
43
+ expect(firstLine('甲:dots[:upright[GDP]]乙').marks.map((m) => m.x)).toEqual([30, 50, 70]);
44
+ expect(firstLine('甲:dots[:upright[W1]]乙').marks.map((m) => m.x)).toEqual([30, 50]);
45
+ });
46
+ });
47
+ //# sourceMappingURL=uprightDots.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uprightDots.test.js","sourceRoot":"","sources":["../../../src/__tests__/cjk/uprightDots.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=wordJoiner.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wordJoiner.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/cjk/wordJoiner.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,47 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { buildDocument } from '../../index';
3
+ import { installSizedStub } from '../vertical/stub';
4
+ // The word joiner U+2060 glues in Chinese text too, as the docs say it does
5
+ // (found on Nº 086: a line still ended on a sense number ① with a joiner
6
+ // after it, and 《說文》 still broke after 說). The stub measures a Han
7
+ // character 1 em (20 px), ① ½ em.
8
+ installSizedStub();
9
+ const pt = (value) => ({ value, unit: 'pt' });
10
+ const config = (chars) => ({
11
+ locale: 'zh-Hant',
12
+ page: { width: pt(chars * 20 + 40), height: pt(600), dpi: 72, margins: { top: pt(20), bottom: pt(20), left: pt(20), right: pt(20) } },
13
+ layout: { layoutType: 'single' },
14
+ header: { elements: [] },
15
+ footer: { elements: [] },
16
+ bodyText: { fontSize: pt(20), lineHeight: pt(30), textAlign: 'justify', firstLineIndent: pt(0), hyphenation: { enabled: false } },
17
+ });
18
+ const linesOf = (doc) => doc.blocks.filter((b) => b.type === 'paragraph').flatMap((b) => b.lines.map((l) => l.text));
19
+ const WJ = '⁠';
20
+ describe('word joiner in Chinese text', () => {
21
+ it('keeps two characters on one line', () => {
22
+ // Seven characters to the line: 也 ends the first, 作 opens the second
23
+ // (and 歷 goes down to 過, which would end the paragraph alone: 孤字).
24
+ expect(linesOf(buildDocument({ markdown: '此開卷第一回也作者自云因曾歷過' }, config(7))))
25
+ .toEqual(['此開卷第一回也', '作者自云因曾', '歷過']);
26
+ const glued = linesOf(buildDocument({ markdown: `此開卷第一回也${WJ}作者自云因曾歷過` }, config(7)));
27
+ expect(glued).toEqual(['此開卷第一回', '也作者自云因曾', '歷過']);
28
+ });
29
+ it('keeps a two-character title whole', () => {
30
+ const md = (t) => `甲乙丙丁戊己《${t}》說也。`;
31
+ expect(linesOf(buildDocument({ markdown: md('說文') }, config(8)))[0]).toBe('甲乙丙丁戊己《說');
32
+ expect(linesOf(buildDocument({ markdown: md(`說${WJ}文`) }, config(8)))[0]).toBe('甲乙丙丁戊己');
33
+ });
34
+ it('keeps a bold sense number with the character after it, across the span', () => {
35
+ // ① is half an em: 此開卷第一回 and ① fill 6.5 of the 7 ems, and the
36
+ // line broke after the number.
37
+ const plain = linesOf(buildDocument({ markdown: '此開卷第一回**①**作者自云' }, config(7)));
38
+ expect(plain[0]).toBe('此開卷第一回①');
39
+ for (const md of [`此開卷第一回**①**${WJ}作者自云`, `此開卷第一回**①${WJ}**作者自云`]) {
40
+ expect(linesOf(buildDocument({ markdown: md }, config(7)))).toEqual(['此開卷第一回', '①作者自云']);
41
+ }
42
+ });
43
+ it('a space after the joiner still breaks', () => {
44
+ expect(linesOf(buildDocument({ markdown: `此開卷第一回${WJ} 作者自云因曾歷過` }, config(7)))[0]).toBe('此開卷第一回');
45
+ });
46
+ });
47
+ //# sourceMappingURL=wordJoiner.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wordJoiner.test.js","sourceRoot":"","sources":["../../../src/__tests__/cjk/wordJoiner.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=zhuyinTones.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zhuyinTones.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/cjk/zhuyinTones.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,72 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { buildDocument } from '../../index';
3
+ import { SizedStubCtx } from '../vertical/stub';
4
+ // Zhuyin tone marks placed by their ink (T8 review): fonts set ˊ ˇ ˋ high
5
+ // in their em box (Noto Serif TC's ˇ inks 0.484–0.826 em over its
6
+ // baseline), so centring the em box on the last symbol's top put the ink
7
+ // beside the symbol before it. This stub inks the tone marks there.
8
+ class ToneInkCtx extends SizedStubCtx {
9
+ measureText(s) {
10
+ const m = super.measureText(s);
11
+ if (!/^[ˊˇˋ˙]$/.test(s))
12
+ return m;
13
+ const em = Number(/(\d*\.?\d+)px/.exec(this.font)?.[1] ?? 10);
14
+ return { ...m, actualBoundingBoxAscent: 0.826 * em, actualBoundingBoxDescent: -0.484 * em };
15
+ }
16
+ }
17
+ globalThis.OffscreenCanvas = class {
18
+ getContext() {
19
+ return new ToneInkCtx();
20
+ }
21
+ };
22
+ const pt = (value) => ({ value, unit: 'pt' });
23
+ const config = (extra = {}) => ({
24
+ locale: 'zh-Hant-TW',
25
+ page: { width: pt(440), height: pt(600), dpi: 72, margins: { top: pt(20), bottom: pt(20), left: pt(20), right: pt(20) } },
26
+ layout: { layoutType: 'single' },
27
+ header: { elements: [] },
28
+ footer: { elements: [] },
29
+ bodyText: { fontSize: pt(20), lineHeight: pt(40), textAlign: 'justify', firstLineIndent: pt(0), hyphenation: { enabled: false } },
30
+ ...extra,
31
+ });
32
+ const runsOf = (md, extra = {}) => {
33
+ const doc = buildDocument({ markdown: md }, config(extra));
34
+ return doc.blocks.flatMap((b) => b.lines).flatMap((l) => l.segments ?? []).find((s) => s.ruby).ruby.runs;
35
+ };
36
+ /** The zhuyin size: 60 % of the 10 px ruby. */
37
+ const Z = 6;
38
+ /** Where the stub's tone ink is centred over its baseline. */
39
+ const INK_MID = ((0.826 + 0.484) / 2) * Z;
40
+ describe('zhuyin tone marks by their ink', () => {
41
+ it('right of horizontal text: the ink is centred on the last symbol’s top, right of the column', () => {
42
+ for (const reading of ['ㄇㄢˇ', 'ㄊㄤˊ', 'ㄧㄢˊ', 'ㄓˋ']) {
43
+ const runs = runsOf(`:ruby[滿]{rt="${reading}"}紙`);
44
+ const tone = runs.find((r) => /[ˊˇˋ]/.test(r.text));
45
+ const symbols = runs.filter((r) => r !== tone);
46
+ const last = symbols[symbols.length - 1];
47
+ // The last symbol's em box top (0.88 em over its baseline).
48
+ const lastTop = last.dy - 0.88 * Z;
49
+ expect(tone.dy - INK_MID).toBeCloseTo(lastTop, 9);
50
+ expect(tone.dx).toBeGreaterThanOrEqual(last.dx + Z / 2);
51
+ }
52
+ });
53
+ it('the neutral-tone dot sits just over the first symbol, the column centred with it', () => {
54
+ const runs = runsOf(':ruby[麼]{rt="˙ㄇㄜ"}紙');
55
+ const dot = runs.find((r) => r.text === '˙');
56
+ const first = runs.find((r) => r.text === 'ㄇ');
57
+ const firstTop = first.dy - 0.88 * Z;
58
+ // In a tenth of an em (2 px) over the symbols.
59
+ expect(dot.dy - INK_MID).toBeCloseTo(firstTop - 1, 9);
60
+ });
61
+ it('over vertical text: the tone mark stands upright, its ink centred on the last symbol’s top', () => {
62
+ const runs = runsOf(':ruby[滿]{rt="ㄇㄢˇ"}紙', { layout: { layoutType: 'single', writingMode: 'vertical-rl' } });
63
+ const [symbols, tone] = runs;
64
+ expect(tone).toMatchObject({ text: 'ˇ', upright: true });
65
+ // An upright cell stands its glyph on the central axis: the ink centre
66
+ // is 0.38 em past the cell's centre less the ink's height over the
67
+ // baseline.
68
+ const inkAt = tone.dx + Z / 2 + 0.38 * Z - INK_MID;
69
+ expect(inkAt).toBeCloseTo(symbols.dx + Z, 9);
70
+ });
71
+ });
72
+ //# sourceMappingURL=zhuyinTones.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zhuyinTones.test.js","sourceRoot":"","sources":["../../../src/__tests__/cjk/zhuyinTones.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=contentLocale.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contentLocale.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/contentLocale.test.ts"],"names":[],"mappings":""}