editor-svg 1.0.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 (472) hide show
  1. package/.editorconfig +9 -0
  2. package/.eslintrc +46 -0
  3. package/.prettierrc +8 -0
  4. package/AGENTS.md +186 -0
  5. package/CHANGELOG.md +2543 -0
  6. package/CLAUDE.md +110 -0
  7. package/LICENSE +21 -0
  8. package/README.md +110 -0
  9. package/cypress/e2e/control/checkbox.cy.ts +46 -0
  10. package/cypress/e2e/control/select.cy.ts +56 -0
  11. package/cypress/e2e/control/text.cy.ts +43 -0
  12. package/cypress/e2e/editor.cy.ts +67 -0
  13. package/cypress/e2e/menus/block.cy.ts +38 -0
  14. package/cypress/e2e/menus/checkbox.cy.ts +33 -0
  15. package/cypress/e2e/menus/codeblock.cy.ts +34 -0
  16. package/cypress/e2e/menus/date.cy.ts +28 -0
  17. package/cypress/e2e/menus/format.cy.ts +40 -0
  18. package/cypress/e2e/menus/hyperlink.cy.ts +39 -0
  19. package/cypress/e2e/menus/image.cy.ts +25 -0
  20. package/cypress/e2e/menus/latex.cy.ts +34 -0
  21. package/cypress/e2e/menus/pagebreak.cy.ts +21 -0
  22. package/cypress/e2e/menus/painter.cy.ts +53 -0
  23. package/cypress/e2e/menus/print.cy.ts +25 -0
  24. package/cypress/e2e/menus/row.cy.ts +103 -0
  25. package/cypress/e2e/menus/search.cy.ts +112 -0
  26. package/cypress/e2e/menus/separator.cy.ts +32 -0
  27. package/cypress/e2e/menus/table.cy.ts +25 -0
  28. package/cypress/e2e/menus/text.cy.ts +304 -0
  29. package/cypress/e2e/menus/title.cy.ts +43 -0
  30. package/cypress/e2e/menus/undoRedo.cy.ts +49 -0
  31. package/cypress/e2e/menus/watermark.cy.ts +64 -0
  32. package/cypress/fixtures/example.json +3 -0
  33. package/cypress/fixtures/test.png +0 -0
  34. package/cypress/global.d.ts +13 -0
  35. package/cypress/support/commands.ts +5 -0
  36. package/cypress/support/e2e.ts +1 -0
  37. package/cypress/tsconfig.json +21 -0
  38. package/cypress.config.ts +10 -0
  39. package/docs/.vitepress/config.ts +191 -0
  40. package/docs/.vitepress/theme/components/DeepWikiBadge.vue +21 -0
  41. package/docs/.vitepress/theme/components/ZreadBadge.vue +21 -0
  42. package/docs/.vitepress/theme/index.ts +27 -0
  43. package/docs/en/guide/api-common.md +49 -0
  44. package/docs/en/guide/api-instance.md +34 -0
  45. package/docs/en/guide/command-execute.md +1167 -0
  46. package/docs/en/guide/command-get.md +355 -0
  47. package/docs/en/guide/contextmenu-custom.md +44 -0
  48. package/docs/en/guide/contextmenu-internal.md +61 -0
  49. package/docs/en/guide/eventbus.md +260 -0
  50. package/docs/en/guide/i18n.md +112 -0
  51. package/docs/en/guide/listener.md +126 -0
  52. package/docs/en/guide/option.md +214 -0
  53. package/docs/en/guide/override.md +57 -0
  54. package/docs/en/guide/plugin-custom.md +25 -0
  55. package/docs/en/guide/plugin-internal.md +125 -0
  56. package/docs/en/guide/schema.md +237 -0
  57. package/docs/en/guide/shortcut-custom.md +22 -0
  58. package/docs/en/guide/shortcut-internal.md +189 -0
  59. package/docs/en/guide/start.md +97 -0
  60. package/docs/en/index.md +43 -0
  61. package/docs/guide/api-common.md +49 -0
  62. package/docs/guide/api-instance.md +34 -0
  63. package/docs/guide/command-execute.md +1157 -0
  64. package/docs/guide/command-get.md +353 -0
  65. package/docs/guide/contextmenu-custom.md +44 -0
  66. package/docs/guide/contextmenu-internal.md +61 -0
  67. package/docs/guide/eventbus.md +260 -0
  68. package/docs/guide/i18n.md +111 -0
  69. package/docs/guide/listener.md +126 -0
  70. package/docs/guide/option.md +214 -0
  71. package/docs/guide/override.md +57 -0
  72. package/docs/guide/plugin-custom.md +25 -0
  73. package/docs/guide/plugin-internal.md +125 -0
  74. package/docs/guide/schema.md +237 -0
  75. package/docs/guide/shortcut-custom.md +22 -0
  76. package/docs/guide/shortcut-internal.md +189 -0
  77. package/docs/guide/start.md +97 -0
  78. package/docs/index.md +43 -0
  79. package/docs/public/favicon.png +0 -0
  80. package/favicon.png +0 -0
  81. package/index.html +435 -0
  82. package/package.json +55 -0
  83. package/pnpm-lock.yaml +4113 -0
  84. package/scripts/release.js +41 -0
  85. package/scripts/verifyCommit.js +19 -0
  86. package/src/assets/images/alignment.svg +1 -0
  87. package/src/assets/images/arrow-left.svg +1 -0
  88. package/src/assets/images/arrow-right.svg +1 -0
  89. package/src/assets/images/block.svg +1 -0
  90. package/src/assets/images/bold.svg +1 -0
  91. package/src/assets/images/catalog.svg +1 -0
  92. package/src/assets/images/center.svg +1 -0
  93. package/src/assets/images/checkbox.svg +1 -0
  94. package/src/assets/images/close.svg +1 -0
  95. package/src/assets/images/codeblock.svg +1 -0
  96. package/src/assets/images/color.svg +1 -0
  97. package/src/assets/images/control.svg +1 -0
  98. package/src/assets/images/date.svg +1 -0
  99. package/src/assets/images/exit-fullscreen.svg +1 -0
  100. package/src/assets/images/format.svg +1 -0
  101. package/src/assets/images/highlight.svg +1 -0
  102. package/src/assets/images/hyperlink.svg +1 -0
  103. package/src/assets/images/image.svg +1 -0
  104. package/src/assets/images/italic.svg +1 -0
  105. package/src/assets/images/justify.svg +7 -0
  106. package/src/assets/images/latex.svg +1 -0
  107. package/src/assets/images/left.svg +1 -0
  108. package/src/assets/images/line-dash-dot-dot.svg +1 -0
  109. package/src/assets/images/line-dash-dot.svg +1 -0
  110. package/src/assets/images/line-dash-large-gap.svg +1 -0
  111. package/src/assets/images/line-dash-small-gap.svg +1 -0
  112. package/src/assets/images/line-dot.svg +1 -0
  113. package/src/assets/images/line-double.svg +1 -0
  114. package/src/assets/images/line-single.svg +1 -0
  115. package/src/assets/images/line-wavy.svg +1 -0
  116. package/src/assets/images/list.svg +1 -0
  117. package/src/assets/images/option.svg +1 -0
  118. package/src/assets/images/page-break.svg +1 -0
  119. package/src/assets/images/page-mode.svg +1 -0
  120. package/src/assets/images/page-scale-add.svg +1 -0
  121. package/src/assets/images/page-scale-minus.svg +1 -0
  122. package/src/assets/images/painter.svg +1 -0
  123. package/src/assets/images/paper-direction.svg +1 -0
  124. package/src/assets/images/paper-margin.svg +1 -0
  125. package/src/assets/images/paper-size.svg +1 -0
  126. package/src/assets/images/print.svg +1 -0
  127. package/src/assets/images/radio.svg +4 -0
  128. package/src/assets/images/redo.svg +1 -0
  129. package/src/assets/images/request-fullscreen.svg +1 -0
  130. package/src/assets/images/right.svg +1 -0
  131. package/src/assets/images/row-margin.svg +1 -0
  132. package/src/assets/images/search.svg +1 -0
  133. package/src/assets/images/separator.svg +1 -0
  134. package/src/assets/images/signature-undo.svg +1 -0
  135. package/src/assets/images/signature.svg +1 -0
  136. package/src/assets/images/size-add.svg +1 -0
  137. package/src/assets/images/size-minus.svg +1 -0
  138. package/src/assets/images/strikeout.svg +1 -0
  139. package/src/assets/images/subscript.svg +1 -0
  140. package/src/assets/images/superscript.svg +1 -0
  141. package/src/assets/images/table.svg +1 -0
  142. package/src/assets/images/title.svg +1 -0
  143. package/src/assets/images/trash.svg +1 -0
  144. package/src/assets/images/underline.svg +1 -0
  145. package/src/assets/images/undo.svg +1 -0
  146. package/src/assets/images/watermark.svg +1 -0
  147. package/src/assets/images/word-tool.svg +1 -0
  148. package/src/assets/snapshots/main_v0.2.1.png +0 -0
  149. package/src/assets/snapshots/main_v0.2.2.png +0 -0
  150. package/src/assets/snapshots/main_v0.3.0.png +0 -0
  151. package/src/assets/snapshots/main_v0.3.1.png +0 -0
  152. package/src/assets/snapshots/main_v0.5.0.png +0 -0
  153. package/src/assets/snapshots/main_v0.5.1.png +0 -0
  154. package/src/assets/snapshots/main_v0.6.0.png +0 -0
  155. package/src/assets/snapshots/main_v0.6.1.png +0 -0
  156. package/src/assets/snapshots/main_v0.7.0.png +0 -0
  157. package/src/assets/snapshots/main_v0.7.1.png +0 -0
  158. package/src/assets/snapshots/main_v0.7.2.png +0 -0
  159. package/src/assets/snapshots/main_v0.7.3.png +0 -0
  160. package/src/assets/snapshots/main_v0.7.4.png +0 -0
  161. package/src/assets/snapshots/main_v0.7.6.png +0 -0
  162. package/src/assets/snapshots/main_v0.7.7.png +0 -0
  163. package/src/assets/snapshots/main_v0.8.0.png +0 -0
  164. package/src/assets/snapshots/main_v0.8.5.png +0 -0
  165. package/src/assets/snapshots/main_v0.8.6.png +0 -0
  166. package/src/assets/snapshots/main_v0.8.7.png +0 -0
  167. package/src/assets/snapshots/main_v0.8.8.png +0 -0
  168. package/src/assets/snapshots/main_v0.9.0.png +0 -0
  169. package/src/assets/snapshots/main_v0.9.1.png +0 -0
  170. package/src/assets/snapshots/main_v0.9.2.png +0 -0
  171. package/src/assets/snapshots/main_v0.9.23.png +0 -0
  172. package/src/assets/snapshots/main_v0.9.28.png +0 -0
  173. package/src/assets/snapshots/main_v0.9.29.png +0 -0
  174. package/src/assets/snapshots/main_v0.9.3.png +0 -0
  175. package/src/assets/snapshots/main_v0.9.30.png +0 -0
  176. package/src/assets/snapshots/main_v0.9.32.png +0 -0
  177. package/src/assets/snapshots/main_v0.9.35.png +0 -0
  178. package/src/assets/snapshots/main_v0.9.4.png +0 -0
  179. package/src/assets/snapshots/main_v0.9.5.png +0 -0
  180. package/src/assets/snapshots/main_v0.9.6.png +0 -0
  181. package/src/assets/snapshots/main_v0.9.8.png +0 -0
  182. package/src/components/dialog/Dialog.ts +171 -0
  183. package/src/components/dialog/dialog.css +131 -0
  184. package/src/components/signature/Signature.ts +340 -0
  185. package/src/components/signature/signature.css +132 -0
  186. package/src/editor/assets/css/block/block.css +21 -0
  187. package/src/editor/assets/css/contextmenu/contextmenu.css +196 -0
  188. package/src/editor/assets/css/control/calculator.css +85 -0
  189. package/src/editor/assets/css/control/select.css +44 -0
  190. package/src/editor/assets/css/date/datePicker.css +233 -0
  191. package/src/editor/assets/css/hyperlink/hyperlink.css +26 -0
  192. package/src/editor/assets/css/index.css +78 -0
  193. package/src/editor/assets/css/previewer/previewer.css +122 -0
  194. package/src/editor/assets/css/resizer/resizer.css +74 -0
  195. package/src/editor/assets/css/table/table.css +155 -0
  196. package/src/editor/assets/css/zone/zone.css +61 -0
  197. package/src/editor/assets/images/close.svg +1 -0
  198. package/src/editor/assets/images/delete-col.svg +1 -0
  199. package/src/editor/assets/images/delete-row-col.svg +1 -0
  200. package/src/editor/assets/images/delete-row.svg +1 -0
  201. package/src/editor/assets/images/delete-table.svg +1 -0
  202. package/src/editor/assets/images/image-change.svg +1 -0
  203. package/src/editor/assets/images/image-download.svg +1 -0
  204. package/src/editor/assets/images/image-next.svg +1 -0
  205. package/src/editor/assets/images/image-pre.svg +1 -0
  206. package/src/editor/assets/images/image.svg +1 -0
  207. package/src/editor/assets/images/insert-bottom-row.svg +1 -0
  208. package/src/editor/assets/images/insert-left-col.svg +1 -0
  209. package/src/editor/assets/images/insert-right-col.svg +1 -0
  210. package/src/editor/assets/images/insert-row-col.svg +1 -0
  211. package/src/editor/assets/images/insert-top-row.svg +1 -0
  212. package/src/editor/assets/images/merge-cancel-cell.svg +1 -0
  213. package/src/editor/assets/images/merge-cell.svg +1 -0
  214. package/src/editor/assets/images/original-size.svg +1 -0
  215. package/src/editor/assets/images/print.svg +1 -0
  216. package/src/editor/assets/images/rotate.svg +1 -0
  217. package/src/editor/assets/images/submenu-dropdown.svg +1 -0
  218. package/src/editor/assets/images/table-border-all.svg +1 -0
  219. package/src/editor/assets/images/table-border-dash.svg +1 -0
  220. package/src/editor/assets/images/table-border-empty.svg +1 -0
  221. package/src/editor/assets/images/table-border-external.svg +1 -0
  222. package/src/editor/assets/images/table-border-internal.svg +1 -0
  223. package/src/editor/assets/images/table-border-td-back.svg +1 -0
  224. package/src/editor/assets/images/table-border-td-bottom.svg +1 -0
  225. package/src/editor/assets/images/table-border-td-forward.svg +1 -0
  226. package/src/editor/assets/images/table-border-td-left.svg +1 -0
  227. package/src/editor/assets/images/table-border-td-right.svg +1 -0
  228. package/src/editor/assets/images/table-border-td-top.svg +1 -0
  229. package/src/editor/assets/images/table-border-td.svg +1 -0
  230. package/src/editor/assets/images/vertical-align-bottom.svg +1 -0
  231. package/src/editor/assets/images/vertical-align-middle.svg +1 -0
  232. package/src/editor/assets/images/vertical-align-top.svg +1 -0
  233. package/src/editor/assets/images/vertical-align.svg +1 -0
  234. package/src/editor/assets/images/zoom-in.svg +1 -0
  235. package/src/editor/assets/images/zoom-out.svg +1 -0
  236. package/src/editor/core/actuator/Actuator.ts +21 -0
  237. package/src/editor/core/actuator/handlers/positionContextChange.ts +13 -0
  238. package/src/editor/core/command/Command.ts +312 -0
  239. package/src/editor/core/command/CommandAdapt.ts +2733 -0
  240. package/src/editor/core/contextmenu/ContextMenu.ts +363 -0
  241. package/src/editor/core/contextmenu/menus/controlMenus.ts +25 -0
  242. package/src/editor/core/contextmenu/menus/globalMenus.ts +66 -0
  243. package/src/editor/core/contextmenu/menus/hyperlinkMenus.ts +58 -0
  244. package/src/editor/core/contextmenu/menus/imageMenus.ts +134 -0
  245. package/src/editor/core/contextmenu/menus/tableMenus.ts +331 -0
  246. package/src/editor/core/cursor/Cursor.ts +248 -0
  247. package/src/editor/core/cursor/CursorAgent.ts +75 -0
  248. package/src/editor/core/draw/Draw.ts +2934 -0
  249. package/src/editor/core/draw/control/Control.ts +1767 -0
  250. package/src/editor/core/draw/control/checkbox/CheckboxControl.ts +154 -0
  251. package/src/editor/core/draw/control/date/DateControl.ts +363 -0
  252. package/src/editor/core/draw/control/interactive/ControlSearch.ts +214 -0
  253. package/src/editor/core/draw/control/number/Calculator.ts +183 -0
  254. package/src/editor/core/draw/control/number/NumberControl.ts +183 -0
  255. package/src/editor/core/draw/control/radio/RadioControl.ts +68 -0
  256. package/src/editor/core/draw/control/richtext/Border.ts +52 -0
  257. package/src/editor/core/draw/control/select/SelectControl.ts +567 -0
  258. package/src/editor/core/draw/control/text/TextControl.ts +280 -0
  259. package/src/editor/core/draw/frame/Background.ts +117 -0
  260. package/src/editor/core/draw/frame/Badge.ts +88 -0
  261. package/src/editor/core/draw/frame/Footer.ts +155 -0
  262. package/src/editor/core/draw/frame/Header.ts +158 -0
  263. package/src/editor/core/draw/frame/LineNumber.ts +43 -0
  264. package/src/editor/core/draw/frame/Margin.ts +53 -0
  265. package/src/editor/core/draw/frame/PageBorder.ts +47 -0
  266. package/src/editor/core/draw/frame/PageNumber.ts +88 -0
  267. package/src/editor/core/draw/frame/Placeholder.ts +114 -0
  268. package/src/editor/core/draw/frame/Watermark.ts +188 -0
  269. package/src/editor/core/draw/graffiti/Graffiti.ts +125 -0
  270. package/src/editor/core/draw/interactive/Area.ts +312 -0
  271. package/src/editor/core/draw/interactive/Group.ts +198 -0
  272. package/src/editor/core/draw/interactive/Search.ts +527 -0
  273. package/src/editor/core/draw/particle/CheckboxParticle.ts +111 -0
  274. package/src/editor/core/draw/particle/HyperlinkParticle.ts +86 -0
  275. package/src/editor/core/draw/particle/ImageParticle.ts +280 -0
  276. package/src/editor/core/draw/particle/LabelParticle.ts +79 -0
  277. package/src/editor/core/draw/particle/LineBreakParticle.ts +55 -0
  278. package/src/editor/core/draw/particle/ListParticle.ts +255 -0
  279. package/src/editor/core/draw/particle/PageBreakParticle.ts +54 -0
  280. package/src/editor/core/draw/particle/RadioParticle.ts +99 -0
  281. package/src/editor/core/draw/particle/SeparatorParticle.ts +37 -0
  282. package/src/editor/core/draw/particle/SubscriptParticle.ts +23 -0
  283. package/src/editor/core/draw/particle/SuperscriptParticle.ts +23 -0
  284. package/src/editor/core/draw/particle/TextParticle.ts +174 -0
  285. package/src/editor/core/draw/particle/WhiteSpaceParticle.ts +32 -0
  286. package/src/editor/core/draw/particle/block/BlockParticle.ts +76 -0
  287. package/src/editor/core/draw/particle/block/modules/BaseBlock.ts +280 -0
  288. package/src/editor/core/draw/particle/block/modules/IFrameBlock.ts +47 -0
  289. package/src/editor/core/draw/particle/block/modules/VideoBlock.ts +61 -0
  290. package/src/editor/core/draw/particle/date/DateParticle.ts +111 -0
  291. package/src/editor/core/draw/particle/date/DatePicker.ts +577 -0
  292. package/src/editor/core/draw/particle/latex/LaTexParticle.ts +43 -0
  293. package/src/editor/core/draw/particle/latex/utils/LaTexUtils.ts +1196 -0
  294. package/src/editor/core/draw/particle/latex/utils/hershey.ts +1632 -0
  295. package/src/editor/core/draw/particle/latex/utils/symbols.ts +318 -0
  296. package/src/editor/core/draw/particle/previewer/Previewer.ts +582 -0
  297. package/src/editor/core/draw/particle/table/TableOperate.ts +988 -0
  298. package/src/editor/core/draw/particle/table/TableParticle.ts +558 -0
  299. package/src/editor/core/draw/particle/table/TableTool.ts +551 -0
  300. package/src/editor/core/draw/richtext/AbstractRichText.ts +59 -0
  301. package/src/editor/core/draw/richtext/Highlight.ts +24 -0
  302. package/src/editor/core/draw/richtext/Strikeout.ts +28 -0
  303. package/src/editor/core/draw/richtext/Underline.ts +106 -0
  304. package/src/editor/core/event/CanvasEvent.ts +215 -0
  305. package/src/editor/core/event/GlobalEvent.ts +173 -0
  306. package/src/editor/core/event/eventbus/EventBus.ts +50 -0
  307. package/src/editor/core/event/handlers/click.ts +234 -0
  308. package/src/editor/core/event/handlers/composition.ts +45 -0
  309. package/src/editor/core/event/handlers/copy.ts +72 -0
  310. package/src/editor/core/event/handlers/cut.ts +47 -0
  311. package/src/editor/core/event/handlers/drag.ts +66 -0
  312. package/src/editor/core/event/handlers/drop.ts +28 -0
  313. package/src/editor/core/event/handlers/input.ts +129 -0
  314. package/src/editor/core/event/handlers/keydown/backspace.ts +161 -0
  315. package/src/editor/core/event/handlers/keydown/delete.ts +119 -0
  316. package/src/editor/core/event/handlers/keydown/end.ts +69 -0
  317. package/src/editor/core/event/handlers/keydown/enter.ts +126 -0
  318. package/src/editor/core/event/handlers/keydown/home.ts +69 -0
  319. package/src/editor/core/event/handlers/keydown/index.ts +85 -0
  320. package/src/editor/core/event/handlers/keydown/left.ts +162 -0
  321. package/src/editor/core/event/handlers/keydown/right.ts +178 -0
  322. package/src/editor/core/event/handlers/keydown/tab.ts +41 -0
  323. package/src/editor/core/event/handlers/keydown/updown.ts +342 -0
  324. package/src/editor/core/event/handlers/mousedown.ts +262 -0
  325. package/src/editor/core/event/handlers/mouseleave.ts +14 -0
  326. package/src/editor/core/event/handlers/mousemove.ts +133 -0
  327. package/src/editor/core/event/handlers/mouseup.ts +341 -0
  328. package/src/editor/core/event/handlers/paste.ts +231 -0
  329. package/src/editor/core/history/HistoryManager.ts +61 -0
  330. package/src/editor/core/i18n/I18n.ts +51 -0
  331. package/src/editor/core/i18n/lang/en.json +92 -0
  332. package/src/editor/core/i18n/lang/zh-CN.json +92 -0
  333. package/src/editor/core/listener/Listener.ts +41 -0
  334. package/src/editor/core/observer/ImageObserver.ts +19 -0
  335. package/src/editor/core/observer/MouseObserver.ts +56 -0
  336. package/src/editor/core/observer/ScrollObserver.ts +88 -0
  337. package/src/editor/core/observer/SelectionObserver.ts +143 -0
  338. package/src/editor/core/override/Override.ts +14 -0
  339. package/src/editor/core/plugin/Plugin.ts +17 -0
  340. package/src/editor/core/position/Position.ts +870 -0
  341. package/src/editor/core/range/RangeManager.ts +723 -0
  342. package/src/editor/core/register/Register.ts +28 -0
  343. package/src/editor/core/shortcut/Shortcut.ts +80 -0
  344. package/src/editor/core/shortcut/keys/listKeys.ts +22 -0
  345. package/src/editor/core/shortcut/keys/richtextKeys.ts +102 -0
  346. package/src/editor/core/shortcut/keys/titleKeys.ts +62 -0
  347. package/src/editor/core/worker/WorkerManager.ts +96 -0
  348. package/src/editor/core/worker/works/catalog.ts +189 -0
  349. package/src/editor/core/worker/works/group.ts +34 -0
  350. package/src/editor/core/worker/works/value.ts +32 -0
  351. package/src/editor/core/worker/works/wordCount.ts +132 -0
  352. package/src/editor/core/zone/Zone.ts +183 -0
  353. package/src/editor/core/zone/ZoneTip.ts +108 -0
  354. package/src/editor/dataset/constant/Background.ts +10 -0
  355. package/src/editor/dataset/constant/Badge.ts +6 -0
  356. package/src/editor/dataset/constant/Checkbox.ts +12 -0
  357. package/src/editor/dataset/constant/Common.ts +44 -0
  358. package/src/editor/dataset/constant/ContextMenu.ts +61 -0
  359. package/src/editor/dataset/constant/Control.ts +14 -0
  360. package/src/editor/dataset/constant/Cursor.ts +11 -0
  361. package/src/editor/dataset/constant/Editor.ts +19 -0
  362. package/src/editor/dataset/constant/Element.ts +173 -0
  363. package/src/editor/dataset/constant/Footer.ts +10 -0
  364. package/src/editor/dataset/constant/Graffiti.ts +6 -0
  365. package/src/editor/dataset/constant/Group.ts +10 -0
  366. package/src/editor/dataset/constant/Header.ts +10 -0
  367. package/src/editor/dataset/constant/ImgCaption.ts +8 -0
  368. package/src/editor/dataset/constant/Label.ts +8 -0
  369. package/src/editor/dataset/constant/LineBreak.ts +7 -0
  370. package/src/editor/dataset/constant/LineNumber.ts +11 -0
  371. package/src/editor/dataset/constant/List.ts +26 -0
  372. package/src/editor/dataset/constant/PageBorder.ts +8 -0
  373. package/src/editor/dataset/constant/PageBreak.ts +7 -0
  374. package/src/editor/dataset/constant/PageNumber.ts +22 -0
  375. package/src/editor/dataset/constant/Placeholder.ts +9 -0
  376. package/src/editor/dataset/constant/Radio.ts +12 -0
  377. package/src/editor/dataset/constant/Regular.ts +23 -0
  378. package/src/editor/dataset/constant/Separator.ts +6 -0
  379. package/src/editor/dataset/constant/Shortcut.ts +3 -0
  380. package/src/editor/dataset/constant/Table.ts +9 -0
  381. package/src/editor/dataset/constant/Title.ts +38 -0
  382. package/src/editor/dataset/constant/Watermark.ts +17 -0
  383. package/src/editor/dataset/constant/WhiteSpace.ts +7 -0
  384. package/src/editor/dataset/constant/Zone.ts +5 -0
  385. package/src/editor/dataset/enum/Area.ts +5 -0
  386. package/src/editor/dataset/enum/Background.ts +11 -0
  387. package/src/editor/dataset/enum/Block.ts +4 -0
  388. package/src/editor/dataset/enum/Common.ts +30 -0
  389. package/src/editor/dataset/enum/Control.ts +39 -0
  390. package/src/editor/dataset/enum/Editor.ts +51 -0
  391. package/src/editor/dataset/enum/Element.ts +21 -0
  392. package/src/editor/dataset/enum/ElementStyle.ts +12 -0
  393. package/src/editor/dataset/enum/Event.ts +5 -0
  394. package/src/editor/dataset/enum/KeyMap.ts +85 -0
  395. package/src/editor/dataset/enum/LineNumber.ts +4 -0
  396. package/src/editor/dataset/enum/List.ts +23 -0
  397. package/src/editor/dataset/enum/Observer.ts +6 -0
  398. package/src/editor/dataset/enum/Row.ts +7 -0
  399. package/src/editor/dataset/enum/Text.ts +13 -0
  400. package/src/editor/dataset/enum/Title.ts +8 -0
  401. package/src/editor/dataset/enum/VerticalAlign.ts +5 -0
  402. package/src/editor/dataset/enum/Watermark.ts +4 -0
  403. package/src/editor/dataset/enum/table/Table.ts +19 -0
  404. package/src/editor/dataset/enum/table/TableTool.ts +4 -0
  405. package/src/editor/index.ts +241 -0
  406. package/src/editor/interface/Area.ts +68 -0
  407. package/src/editor/interface/Background.ts +9 -0
  408. package/src/editor/interface/Badge.ts +17 -0
  409. package/src/editor/interface/Block.ts +18 -0
  410. package/src/editor/interface/Catalog.ts +11 -0
  411. package/src/editor/interface/Checkbox.ts +17 -0
  412. package/src/editor/interface/Command.ts +3 -0
  413. package/src/editor/interface/Common.ts +43 -0
  414. package/src/editor/interface/Control.ts +250 -0
  415. package/src/editor/interface/Cursor.ts +7 -0
  416. package/src/editor/interface/Draw.ts +86 -0
  417. package/src/editor/interface/Editor.ts +172 -0
  418. package/src/editor/interface/Element.ts +273 -0
  419. package/src/editor/interface/Event.ts +27 -0
  420. package/src/editor/interface/EventBus.ts +46 -0
  421. package/src/editor/interface/Footer.ts +9 -0
  422. package/src/editor/interface/Graffiti.ts +15 -0
  423. package/src/editor/interface/Group.ts +8 -0
  424. package/src/editor/interface/Header.ts +9 -0
  425. package/src/editor/interface/Label.ts +8 -0
  426. package/src/editor/interface/LineBreak.ts +5 -0
  427. package/src/editor/interface/LineNumber.ts +10 -0
  428. package/src/editor/interface/Listener.ts +88 -0
  429. package/src/editor/interface/Margin.ts +1 -0
  430. package/src/editor/interface/PageBorder.ts +8 -0
  431. package/src/editor/interface/PageBreak.ts +5 -0
  432. package/src/editor/interface/PageNumber.ts +16 -0
  433. package/src/editor/interface/Placeholder.ts +7 -0
  434. package/src/editor/interface/Plugin.ts +8 -0
  435. package/src/editor/interface/Position.ts +113 -0
  436. package/src/editor/interface/Previewer.ts +15 -0
  437. package/src/editor/interface/Radio.ts +17 -0
  438. package/src/editor/interface/Range.ts +61 -0
  439. package/src/editor/interface/Row.ts +25 -0
  440. package/src/editor/interface/Search.ts +36 -0
  441. package/src/editor/interface/Separator.ts +4 -0
  442. package/src/editor/interface/Text.ts +15 -0
  443. package/src/editor/interface/Title.ts +32 -0
  444. package/src/editor/interface/Watermark.ts +16 -0
  445. package/src/editor/interface/WhiteSpace.ts +5 -0
  446. package/src/editor/interface/Zone.ts +3 -0
  447. package/src/editor/interface/contextmenu/ContextMenu.ts +76 -0
  448. package/src/editor/interface/i18n/I18n.ts +7 -0
  449. package/src/editor/interface/shortcut/Shortcut.ts +14 -0
  450. package/src/editor/interface/table/Colgroup.ts +4 -0
  451. package/src/editor/interface/table/Table.ts +9 -0
  452. package/src/editor/interface/table/Td.ts +36 -0
  453. package/src/editor/interface/table/Tr.ts +11 -0
  454. package/src/editor/types/index.d.ts +5 -0
  455. package/src/editor/utils/clipboard.ts +94 -0
  456. package/src/editor/utils/element.ts +1877 -0
  457. package/src/editor/utils/hotkey.ts +5 -0
  458. package/src/editor/utils/index.ts +445 -0
  459. package/src/editor/utils/option.ts +253 -0
  460. package/src/editor/utils/paragraph.ts +28 -0
  461. package/src/editor/utils/print.ts +99 -0
  462. package/src/editor/utils/ua.ts +13 -0
  463. package/src/main.ts +2053 -0
  464. package/src/mock.ts +611 -0
  465. package/src/plugins/copy/index.ts +30 -0
  466. package/src/plugins/markdown/index.ts +118 -0
  467. package/src/style.css +1079 -0
  468. package/src/utils/index.ts +45 -0
  469. package/src/utils/prism.ts +89 -0
  470. package/src/vite-env.d.ts +1 -0
  471. package/tsconfig.json +25 -0
  472. package/vite.config.ts +46 -0
@@ -0,0 +1,1196 @@
1
+ import { HERSHEY } from './hershey'
2
+ import { SYMB, Symb, asciiMap } from './symbols'
3
+
4
+ const CONFIG: Record<string, number> = {
5
+ SUB_SUP_SCALE: 0.5,
6
+ SQRT_MAG_SCALE: 0.5,
7
+ FRAC_SCALE: 0.85,
8
+ LINE_SPACING: 0.5,
9
+ FRAC_SPACING: 0.4
10
+ }
11
+
12
+ function tokenize(str: string): string[] {
13
+ str = str.replace(/\n/g, ' ')
14
+ let i = 0
15
+ const tokens: string[] = []
16
+ let curr = ''
17
+ while (i < str.length) {
18
+ if (str[i] == ' ') {
19
+ if (curr.length) {
20
+ tokens.push(curr)
21
+ curr = ''
22
+ }
23
+ } else if (str[i] == '\\') {
24
+ if (curr.length == 1 && curr[0] == '\\') {
25
+ curr += str[i]
26
+ tokens.push(curr)
27
+ curr = ''
28
+ } else {
29
+ if (curr.length) {
30
+ tokens.push(curr)
31
+ }
32
+ curr = str[i]
33
+ }
34
+ } else if (/[A-Za-z0-9\.]/.test(str[i])) {
35
+ curr += str[i]
36
+ } else {
37
+ if (curr.length && curr != '\\') {
38
+ tokens.push(curr)
39
+ curr = ''
40
+ }
41
+ curr += str[i]
42
+ tokens.push(curr)
43
+ curr = ''
44
+ }
45
+ i++
46
+ }
47
+ if (curr.length) tokens.push(curr)
48
+ return tokens
49
+ }
50
+
51
+ interface Bbox {
52
+ x: number
53
+ y: number
54
+ w: number
55
+ h: number
56
+ }
57
+
58
+ interface Expr {
59
+ type: string
60
+ text: string
61
+ mode: string
62
+ chld: Expr[]
63
+ bbox: Bbox
64
+ }
65
+
66
+ function parseAtom(x: string): Expr {
67
+ return {
68
+ type: SYMB[x] ? 'symb' : 'char',
69
+ mode: 'math',
70
+ text: x,
71
+ chld: [],
72
+ // @ts-ignore
73
+ bbox: null
74
+ }
75
+ }
76
+
77
+ function parse(tokens: string[]): Expr {
78
+ let i = 0
79
+ let expr: Expr = {
80
+ type: 'node',
81
+ text: '',
82
+ mode: 'math',
83
+ chld: [],
84
+ // @ts-ignore
85
+ bbox: null
86
+ }
87
+
88
+ function takeOpt(): Expr | null {
89
+ if (tokens[i] != '[') {
90
+ return null
91
+ }
92
+ let lvl = 0
93
+ let j = i
94
+ while (j < tokens.length) {
95
+ if (tokens[j] == '[') {
96
+ lvl++
97
+ } else if (tokens[j] == ']') {
98
+ lvl--
99
+ if (!lvl) {
100
+ break
101
+ }
102
+ }
103
+ j++
104
+ }
105
+ const ret: Expr = parse(tokens.slice(i + 1, j))
106
+ i = j
107
+ return ret
108
+ }
109
+
110
+ function takeN(n: number): Expr[] {
111
+ let j: number = i
112
+ let j0: number = j
113
+ let lvl = 0
114
+ let cnt = 0
115
+ const ret: Expr[] = []
116
+ while (j < tokens.length) {
117
+ if (tokens[j] == '{') {
118
+ if (!lvl) {
119
+ j0 = j
120
+ }
121
+ lvl++
122
+ } else if (tokens[j] == '}') {
123
+ lvl--
124
+ if (!lvl) {
125
+ ret.push(parse(tokens.slice(j0 + 1, j)))
126
+ cnt++
127
+ if (cnt == n) {
128
+ break
129
+ }
130
+ }
131
+ } else {
132
+ if (lvl == 0) {
133
+ ret.push(parseAtom(tokens[j]))
134
+ cnt++
135
+ if (cnt == n) {
136
+ break
137
+ }
138
+ }
139
+ }
140
+ j++
141
+ }
142
+ i = j
143
+ return ret
144
+ }
145
+
146
+ for (i = 0; i < tokens.length; i++) {
147
+ const s: Symb = SYMB[tokens[i]]
148
+ const e: Expr = {
149
+ type: '',
150
+ text: tokens[i],
151
+ mode: 'math',
152
+ chld: [],
153
+ // @ts-ignore
154
+ bbox: null
155
+ }
156
+ if (s) {
157
+ if (s.arity) {
158
+ i++
159
+ e.type = 'func'
160
+ let opt: Expr | null = null
161
+ if (s.flags.opt) {
162
+ opt = takeOpt()
163
+ if (opt) i++
164
+ }
165
+ const chld: Expr[] = takeN(s.arity)
166
+ e.chld = chld
167
+ if (opt) {
168
+ e.chld.push(opt)
169
+ }
170
+ } else {
171
+ e.type = 'symb'
172
+ }
173
+ } else {
174
+ if (tokens[i] == '{') {
175
+ e.type = 'node'
176
+ e.text = ''
177
+ e.chld = takeN(1)
178
+ } else {
179
+ e.type = 'char'
180
+ }
181
+ }
182
+ expr.chld.push(e)
183
+ }
184
+ if (expr.chld.length == 1) {
185
+ expr = expr.chld[0]
186
+ }
187
+ return expr
188
+ }
189
+
190
+ function environments(exprs: Expr[]) {
191
+ let i = 0
192
+ while (i < exprs.length) {
193
+ if (exprs[i].text == '\\begin') {
194
+ let j: number
195
+ for (j = i; j < exprs.length; j++) {
196
+ if (exprs[j].text == '\\end') {
197
+ break
198
+ }
199
+ }
200
+ const es: Expr[] = exprs.splice(i + 1, j - (i + 1))
201
+ environments(es)
202
+ exprs[i].text = exprs[i].chld[0].text
203
+ exprs[i].chld = es
204
+ exprs.splice(i + 1, 1)
205
+ }
206
+ i++
207
+ }
208
+ }
209
+
210
+ function transform(
211
+ expr: Expr,
212
+ sclx: number,
213
+ scly: number,
214
+ x: number,
215
+ y: number,
216
+ notFirst?: boolean
217
+ ) {
218
+ if (scly == null) {
219
+ scly = sclx
220
+ }
221
+ if (!expr.bbox) return
222
+ if (notFirst) {
223
+ expr.bbox.x *= sclx
224
+ expr.bbox.y *= scly
225
+ }
226
+ expr.bbox.w *= sclx
227
+ expr.bbox.h *= scly
228
+ for (let i = 0; i < expr.chld.length; i++) {
229
+ transform(expr.chld[i], sclx, scly, 0, 0, true)
230
+ }
231
+ expr.bbox.x += x
232
+ expr.bbox.y += y
233
+ }
234
+
235
+ function computeBbox(exprs: Expr[]): Bbox {
236
+ let xmin = Infinity
237
+ let xmax = -Infinity
238
+ let ymin = Infinity
239
+ let ymax = -Infinity
240
+ for (let i = 0; i < exprs.length; i++) {
241
+ if (!exprs[i].bbox) {
242
+ continue
243
+ }
244
+ xmin = Math.min(xmin, exprs[i].bbox.x)
245
+ ymin = Math.min(ymin, exprs[i].bbox.y)
246
+ xmax = Math.max(xmax, exprs[i].bbox.x + exprs[i].bbox.w)
247
+ ymax = Math.max(ymax, exprs[i].bbox.y + exprs[i].bbox.h)
248
+ }
249
+ return { x: xmin, y: ymin, w: xmax - xmin, h: ymax - ymin }
250
+ }
251
+
252
+ function group(exprs: Expr[]): Expr {
253
+ if (!exprs.length) {
254
+ // @ts-ignore
255
+ return null
256
+ }
257
+ const bbox: Bbox = computeBbox(exprs)
258
+ // console.log(exprs,bbox);
259
+ for (let i = 0; i < exprs.length; i++) {
260
+ if (!exprs[i].bbox) {
261
+ continue
262
+ }
263
+ exprs[i].bbox.x -= bbox.x
264
+ exprs[i].bbox.y -= bbox.y
265
+ }
266
+ const expr: Expr = {
267
+ type: 'node',
268
+ text: '',
269
+ mode: 'math',
270
+ chld: exprs,
271
+ bbox
272
+ }
273
+ return expr
274
+ }
275
+
276
+ function align(exprs: Expr[], alignment = 'center'): void {
277
+ for (let i = 0; i < exprs.length; i++) {
278
+ if (exprs[i].text == '^' || exprs[i].text == '\'') {
279
+ let h = 0
280
+ let j = i
281
+ while (
282
+ j > 0 &&
283
+ (exprs[j].text == '^' || exprs[j].text == '_' || exprs[j].text == '\'')
284
+ ) {
285
+ j--
286
+ }
287
+ h = exprs[j].bbox.y
288
+ if (exprs[i].text == '\'') {
289
+ exprs[i].bbox.y = h
290
+ } else {
291
+ // @ts-ignore
292
+ transform(exprs[i], CONFIG.SUB_SUP_SCALE, null, 0, 0)
293
+ if (SYMB[exprs[j].text] && SYMB[exprs[j].text].flags.big) {
294
+ exprs[i].bbox.y = h - exprs[i].bbox.h
295
+ } else if (exprs[j].text == '\\int') {
296
+ exprs[i].bbox.y = h
297
+ } else {
298
+ exprs[i].bbox.y = h - exprs[i].bbox.h / 2
299
+ }
300
+ }
301
+ } else if (exprs[i].text == '_') {
302
+ let h = 1
303
+ let j = i
304
+ while (
305
+ j > 0 &&
306
+ (exprs[j].text == '^' || exprs[j].text == '_' || exprs[j].text == '\'')
307
+ ) {
308
+ j--
309
+ }
310
+ h = exprs[j].bbox.y + exprs[j].bbox.h
311
+ // @ts-ignore
312
+ transform(exprs[i], CONFIG.SUB_SUP_SCALE, null, 0, 0)
313
+ if (SYMB[exprs[j].text] && SYMB[exprs[j].text].flags.big) {
314
+ exprs[i].bbox.y = h
315
+ } else if (exprs[j].text == '\\int') {
316
+ exprs[i].bbox.y = h - exprs[i].bbox.h
317
+ } else {
318
+ exprs[i].bbox.y = h - exprs[i].bbox.h / 2
319
+ }
320
+ }
321
+ }
322
+ function searchHigh(
323
+ i: number,
324
+ l: string,
325
+ r: string,
326
+ dir: number,
327
+ lvl0: number
328
+ ): number[] {
329
+ let j = i
330
+ let lvl = lvl0
331
+ let ymin = Infinity
332
+ let ymax = -Infinity
333
+ while (dir > 0 ? j < exprs.length : j >= 0) {
334
+ if (exprs[j].text == l) {
335
+ lvl++
336
+ } else if (exprs[j].text == r) {
337
+ lvl--
338
+ if (lvl == 0) {
339
+ break
340
+ }
341
+ } else if (exprs[j].text == '^' || exprs[j].text == '_') {
342
+ //skip
343
+ } else if (exprs[j].bbox) {
344
+ ymin = Math.min(ymin, exprs[j].bbox.y)
345
+ ymax = Math.max(ymax, exprs[j].bbox.y + exprs[j].bbox.h)
346
+ }
347
+ j += dir
348
+ }
349
+ return [ymin, ymax]
350
+ }
351
+ for (let i = 0; i < exprs.length; i++) {
352
+ if (exprs[i].text == '\\left') {
353
+ const [ymin, ymax] = searchHigh(i, '\\left', '\\right', 1, 0)
354
+ if (ymin != Infinity && ymax != -Infinity) {
355
+ exprs[i].bbox.y = ymin
356
+ transform(exprs[i], 1, (ymax - ymin) / exprs[i].bbox.h, 0, 0)
357
+ }
358
+ } else if (exprs[i].text == '\\right') {
359
+ const [ymin, ymax] = searchHigh(i, '\\right', '\\left', -1, 0)
360
+ if (ymin != Infinity && ymax != -Infinity) {
361
+ exprs[i].bbox.y = ymin
362
+ transform(exprs[i], 1, (ymax - ymin) / exprs[i].bbox.h, 0, 0)
363
+ }
364
+ } else if (exprs[i].text == '\\middle') {
365
+ const [lmin, lmax] = searchHigh(i, '\\right', '\\left', -1, 1)
366
+ const [rmin, rmax] = searchHigh(i, '\\left', '\\right', 1, 1)
367
+ const ymin = Math.min(lmin, rmin)
368
+ const ymax = Math.max(lmax, rmax)
369
+ if (ymin != Infinity && ymax != -Infinity) {
370
+ exprs[i].bbox.y = ymin
371
+ transform(exprs[i], 1, (ymax - ymin) / exprs[i].bbox.h, 0, 0)
372
+ }
373
+ }
374
+ }
375
+
376
+ if (!exprs.some(x => x.text == '&' || x.text == '\\\\')) {
377
+ return
378
+ }
379
+
380
+ const rows: Expr[][][] = []
381
+ let row: Expr[][] = []
382
+ let cell: Expr[] = []
383
+
384
+ for (let i = 0; i < exprs.length; i++) {
385
+ if (exprs[i].text == '&') {
386
+ row.push(cell)
387
+ cell = []
388
+ } else if (exprs[i].text == '\\\\') {
389
+ if (cell.length) {
390
+ row.push(cell)
391
+ cell = []
392
+ }
393
+ rows.push(row)
394
+ row = []
395
+ } else {
396
+ cell.push(exprs[i])
397
+ }
398
+ }
399
+ if (cell.length) {
400
+ row.push(cell)
401
+ }
402
+ if (row.length) {
403
+ rows.push(row)
404
+ }
405
+ const colws: number[] = []
406
+ const erows: Expr[][] = []
407
+ for (let i = 0; i < rows.length; i++) {
408
+ const erow: Expr[] = []
409
+ for (let j = 0; j < rows[i].length; j++) {
410
+ const e: Expr = group(rows[i][j])
411
+ if (e) {
412
+ colws[j] = colws[j] || 0
413
+ colws[j] = Math.max(e.bbox.w + 1, colws[j])
414
+ }
415
+ erow[j] = e
416
+ }
417
+ erows.push(erow)
418
+ }
419
+
420
+ const ybds: number[][] = []
421
+ for (let i = 0; i < erows.length; i++) {
422
+ let ymin = Infinity
423
+ let ymax = -Infinity
424
+ for (let j = 0; j < erows[i].length; j++) {
425
+ if (!erows[i][j]) {
426
+ continue
427
+ }
428
+ ymin = Math.min(ymin, erows[i][j].bbox.y)
429
+ ymax = Math.max(ymax, erows[i][j].bbox.y + erows[i][j].bbox.h)
430
+ }
431
+ ybds.push([ymin, ymax])
432
+ }
433
+
434
+ for (let i = 0; i < ybds.length; i++) {
435
+ if (ybds[i][0] == Infinity || ybds[i][1] == Infinity) {
436
+ ybds[i][0] = i == 0 ? 0 : ybds[i - 1][1]
437
+ ybds[i][1] = ybds[i][0] + 2
438
+ }
439
+ }
440
+
441
+ for (let i = 1; i < erows.length; i++) {
442
+ const shft = ybds[i - 1][1] - ybds[i][0] + CONFIG.LINE_SPACING
443
+ for (let j = 0; j < erows[i].length; j++) {
444
+ if (erows[i][j]) {
445
+ erows[i][j].bbox.y += shft
446
+ }
447
+ }
448
+ ybds[i][0] += shft
449
+ ybds[i][1] += shft
450
+ }
451
+
452
+ exprs.splice(0, exprs.length)
453
+ for (let i = 0; i < erows.length; i++) {
454
+ let dx = 0
455
+ for (let j = 0; j < erows[i].length; j++) {
456
+ const e: Expr = erows[i][j]
457
+ if (!e) {
458
+ dx += colws[j]
459
+ continue
460
+ }
461
+ e.bbox.x += dx
462
+ dx += colws[j] - e.bbox.w
463
+ // e.bbox.w = colws[j];
464
+ if (alignment == 'center') {
465
+ e.bbox.x += (colws[j] - e.bbox.w) / 2
466
+ } else if (alignment == 'left') {
467
+ //ok
468
+ } else if (alignment == 'right') {
469
+ e.bbox.x += colws[j] - e.bbox.w
470
+ } else if (alignment == 'equation') {
471
+ if (j != erows[i].length - 1) {
472
+ e.bbox.x += colws[j] - e.bbox.w
473
+ }
474
+ }
475
+ exprs.push(e)
476
+ }
477
+ }
478
+ }
479
+
480
+ function plan(expr: Expr, mode = 'math'): void {
481
+ const tmd: string =
482
+ {
483
+ '\\text': 'text',
484
+ '\\mathnormal': 'math',
485
+ '\\mathrm': 'rm',
486
+ '\\mathit': 'it',
487
+ '\\mathbf': 'bf',
488
+ '\\mathsf': 'sf',
489
+ '\\mathtt': 'tt',
490
+ '\\mathfrak': 'frak',
491
+ '\\mathcal': 'cal',
492
+ '\\mathbb': 'bb',
493
+ '\\mathscr': 'scr',
494
+ '\\rm': 'rm',
495
+ '\\it': 'it',
496
+ '\\bf': 'bf',
497
+ '\\sf': 'tt',
498
+ '\\tt': 'tt',
499
+ '\\frak': 'frak',
500
+ '\\cal': 'cal',
501
+ '\\bb': 'bb',
502
+ '\\scr': 'scr'
503
+ }[expr.text] ?? mode
504
+ if (!expr.chld.length) {
505
+ if (SYMB[expr.text]) {
506
+ if (SYMB[expr.text].flags.big) {
507
+ if (expr.text == '\\lim') {
508
+ expr.bbox = { x: 0, y: 0, w: 3.5, h: 2 }
509
+ } else {
510
+ expr.bbox = { x: 0, y: -0.5, w: 3, h: 3 }
511
+ }
512
+ } else if (SYMB[expr.text].flags.txt) {
513
+ let w = 0
514
+ for (let i = 1; i < expr.text.length; i++) {
515
+ w += HERSHEY(asciiMap(expr.text[i], 'text')).w
516
+ }
517
+ w /= 16
518
+ expr.bbox = { x: 0, y: 0, w: w, h: 2 }
519
+ } else if (SYMB[expr.text].glyph) {
520
+ let w = HERSHEY(SYMB[expr.text].glyph).w
521
+ w /= 16
522
+ if (expr.text == '\\int' || expr.text == '\\oint') {
523
+ expr.bbox = { x: 0, y: -1.5, w: w, h: 5 }
524
+ } else {
525
+ expr.bbox = { x: 0, y: 0, w: w, h: 2 }
526
+ }
527
+ } else {
528
+ expr.bbox = { x: 0, y: 0, w: 1, h: 2 }
529
+ }
530
+ } else {
531
+ let w = 0
532
+ for (let i = 0; i < expr.text.length; i++) {
533
+ if (!HERSHEY(asciiMap(expr.text[i], tmd))) {
534
+ continue
535
+ }
536
+ if (tmd == 'tt') {
537
+ w += 16
538
+ } else {
539
+ w += HERSHEY(asciiMap(expr.text[i], tmd)).w
540
+ }
541
+ }
542
+ w /= 16
543
+ expr.bbox = { x: 0, y: 0, w: w, h: 2 }
544
+ }
545
+ expr.mode = tmd
546
+ return
547
+ }
548
+ if (expr.text == '\\frac') {
549
+ const a: Expr = expr.chld[0]
550
+ const b: Expr = expr.chld[1]
551
+ const s: number = CONFIG.FRAC_SCALE
552
+ plan(a)
553
+ plan(b)
554
+ a.bbox.x = 0
555
+ a.bbox.y = 0
556
+ b.bbox.x = 0
557
+ b.bbox.y = 0
558
+ const mw: number = Math.max(a.bbox.w, b.bbox.w) * s
559
+ // @ts-ignore
560
+ transform(a, s, null, (mw - a.bbox.w * s) / 2, 0)
561
+ transform(
562
+ b,
563
+ s,
564
+ // @ts-ignore
565
+ null,
566
+ (mw - b.bbox.w * s) / 2,
567
+ a.bbox.h + CONFIG.FRAC_SPACING
568
+ )
569
+ expr.bbox = {
570
+ x: 0,
571
+ y: -a.bbox.h + 1 - CONFIG.FRAC_SPACING / 2,
572
+ w: mw,
573
+ h: a.bbox.h + b.bbox.h + CONFIG.FRAC_SPACING
574
+ }
575
+ } else if (expr.text == '\\binom') {
576
+ const a: Expr = expr.chld[0]
577
+ const b: Expr = expr.chld[1]
578
+ plan(a)
579
+ plan(b)
580
+ a.bbox.x = 0
581
+ a.bbox.y = 0
582
+ b.bbox.x = 0
583
+ b.bbox.y = 0
584
+ const mw: number = Math.max(a.bbox.w, b.bbox.w)
585
+ // @ts-ignore
586
+ transform(a, 1, null, (mw - a.bbox.w) / 2 + 1, 0)
587
+ // @ts-ignore
588
+ transform(b, 1, null, (mw - b.bbox.w) / 2 + 1, a.bbox.h)
589
+ expr.bbox = { x: 0, y: -a.bbox.h + 1, w: mw + 2, h: a.bbox.h + b.bbox.h }
590
+ } else if (expr.text == '\\sqrt') {
591
+ const e: Expr = expr.chld[0]
592
+ plan(e)
593
+ const f: Expr = expr.chld[1]
594
+ let pl = 0
595
+ if (f) {
596
+ plan(f)
597
+ pl = Math.max(f.bbox.w * CONFIG.SQRT_MAG_SCALE - 0.5, 0)
598
+ // @ts-ignore
599
+ transform(f, CONFIG.SQRT_MAG_SCALE, null, 0, 0.5)
600
+ }
601
+ // @ts-ignore
602
+ transform(e, 1, null, 1 + pl, 0.5)
603
+ expr.bbox = {
604
+ x: 0,
605
+ y: 2 - e.bbox.h - 0.5,
606
+ w: e.bbox.w + 1 + pl,
607
+ h: e.bbox.h + 0.5
608
+ }
609
+ } else if (SYMB[expr.text] && SYMB[expr.text].flags.hat) {
610
+ const e: Expr = expr.chld[0]
611
+ plan(e)
612
+ const y0 = e.bbox.y - 0.5
613
+ e.bbox.y = 0.5
614
+ expr.bbox = { x: 0, y: y0, w: e.bbox.w, h: e.bbox.h + 0.5 }
615
+ } else if (SYMB[expr.text] && SYMB[expr.text].flags.mat) {
616
+ const e: Expr = expr.chld[0]
617
+ plan(e)
618
+ expr.bbox = { x: 0, y: 0, w: e.bbox.w, h: e.bbox.h + 0.5 }
619
+ } else {
620
+ let dx = 0
621
+ let dy = 0
622
+ let mh = 1
623
+ for (let i = 0; i < expr.chld.length; i++) {
624
+ const c: Expr = expr.chld[i]
625
+ // @ts-ignore
626
+ const spac: number =
627
+ {
628
+ '\\quad': 2,
629
+ '\\,': (2 * 3) / 18,
630
+ '\\:': (2 * 4) / 18,
631
+ '\\;': (2 * 5) / 18,
632
+ '\\!': (2 * -3) / 18
633
+ }[c.text] ?? null
634
+
635
+ if (c.text == '\\\\') {
636
+ dy += mh
637
+ dx = 0
638
+ mh = 1
639
+ continue
640
+ } else if (c.text == '&') {
641
+ continue
642
+ } else if (spac != null) {
643
+ dx += spac
644
+ continue
645
+ } else {
646
+ plan(c, tmd)
647
+ // @ts-ignore
648
+ transform(c, 1, null, dx, dy)
649
+ if (c.text == '^' || c.text == '_' || c.text == '\'') {
650
+ let j: number = i
651
+ while (
652
+ j > 0 &&
653
+ (expr.chld[j].text == '^' ||
654
+ expr.chld[j].text == '_' ||
655
+ expr.chld[j].text == '\'')
656
+ ) {
657
+ j--
658
+ }
659
+ const wasBig =
660
+ SYMB[expr.chld[j].text] && SYMB[expr.chld[j].text].flags.big
661
+ if (c.text == '\'') {
662
+ let k = j + 1
663
+ let nth = 0
664
+ while (k < i) {
665
+ if (expr.chld[k].text == '\'') {
666
+ nth++
667
+ }
668
+ k++
669
+ }
670
+ c.bbox.x =
671
+ expr.chld[j].bbox.x + expr.chld[j].bbox.w + c.bbox.w * nth
672
+ dx = Math.max(dx, c.bbox.x + c.bbox.w)
673
+ } else {
674
+ if (wasBig) {
675
+ const ex =
676
+ expr.chld[j].bbox.x +
677
+ (expr.chld[j].bbox.w - c.bbox.w * CONFIG.SUB_SUP_SCALE) / 2
678
+ c.bbox.x = ex
679
+ dx = Math.max(
680
+ dx,
681
+ expr.chld[j].bbox.x +
682
+ expr.chld[j].bbox.w +
683
+ (c.bbox.w * CONFIG.SUB_SUP_SCALE - expr.chld[j].bbox.w) / 2
684
+ )
685
+ } else {
686
+ c.bbox.x = expr.chld[j].bbox.x + expr.chld[j].bbox.w
687
+ dx = Math.max(dx, c.bbox.x + c.bbox.w * CONFIG.SUB_SUP_SCALE)
688
+ }
689
+ }
690
+ } else {
691
+ dx += c.bbox.w
692
+ }
693
+ if (mode == 'text') {
694
+ dx += 1
695
+ }
696
+ mh = Math.max(c.bbox.y + c.bbox.h - dy, mh)
697
+ }
698
+ }
699
+ dy += mh
700
+ const m2s: Record<string, string[]> = {
701
+ bmatrix: ['[', ']'],
702
+ pmatrix: ['(', ')'],
703
+ Bmatrix: ['\\{', '\\}'],
704
+ cases: ['\\{']
705
+ }
706
+ const alt: string =
707
+ {
708
+ bmatrix: 'center',
709
+ pmatrix: 'center',
710
+ Bmatrix: 'center',
711
+ cases: 'left',
712
+ matrix: 'center',
713
+ aligned: 'equation'
714
+ }[expr.text] ?? 'left'
715
+
716
+ const hasLp = !!m2s[expr.text]
717
+ const hasRp = !!m2s[expr.text] && m2s[expr.text].length > 1
718
+
719
+ align(expr.chld, alt)
720
+ const bb = computeBbox(expr.chld)
721
+ if (expr.text == '\\text') {
722
+ bb.x -= 1
723
+ bb.w += 2
724
+ }
725
+
726
+ for (let i = 0; i < expr.chld.length; i++) {
727
+ // @ts-ignore
728
+ transform(expr.chld[i], 1, null, -bb.x + (hasLp ? 1.5 : 0), -bb.y)
729
+ }
730
+ expr.bbox = {
731
+ x: 0,
732
+ y: 0,
733
+ w: bb.w + 1.5 * Number(hasLp) + 1.5 * Number(hasRp),
734
+ h: bb.h
735
+ }
736
+
737
+ if (hasLp) {
738
+ expr.chld.unshift({
739
+ type: 'symb',
740
+ text: m2s[expr.text][0],
741
+ mode: expr.mode,
742
+ chld: [],
743
+ bbox: { x: 0, y: 0, w: 1, h: bb.h }
744
+ })
745
+ }
746
+ if (hasRp) {
747
+ expr.chld.push({
748
+ type: 'symb',
749
+ text: m2s[expr.text][1],
750
+ mode: expr.mode,
751
+ chld: [],
752
+ bbox: { x: bb.w + 2, y: 0, w: 1, h: bb.h }
753
+ })
754
+ }
755
+ if (hasLp || hasRp || expr.text == 'matrix') {
756
+ expr.type = 'node'
757
+ expr.text = ''
758
+ expr.bbox.y -= (expr.bbox.h - 2) / 2
759
+ }
760
+ }
761
+ }
762
+
763
+ function flatten(expr: Expr) {
764
+ function flat(expr: Expr, dx: number, dy: number): Expr[] {
765
+ const ff: Expr[] = []
766
+ if (expr.bbox) {
767
+ dx += expr.bbox.x
768
+ dy += expr.bbox.y
769
+ if (expr.text == '\\frac') {
770
+ const h: number =
771
+ expr.chld[1].bbox.y - (expr.chld[0].bbox.y + expr.chld[0].bbox.h)
772
+ const e: Expr = {
773
+ type: 'symb',
774
+ mode: expr.mode,
775
+ text: '\\bar',
776
+ bbox: {
777
+ x: dx,
778
+ y: dy + (expr.chld[1].bbox.y - h / 2) - h / 2,
779
+ w: expr.bbox.w,
780
+ h: h
781
+ },
782
+ chld: []
783
+ }
784
+ ff.push(e)
785
+ } else if (expr.text == '\\sqrt') {
786
+ const h: number = expr.chld[0].bbox.y
787
+ const xx: number = Math.max(
788
+ 0,
789
+ expr.chld[0].bbox.x - expr.chld[0].bbox.h / 2
790
+ )
791
+ const e: Expr = {
792
+ type: 'symb',
793
+ mode: expr.mode,
794
+ text: '\\sqrt',
795
+ bbox: {
796
+ x: dx + xx,
797
+ y: dy + h / 2,
798
+ w: expr.chld[0].bbox.x - xx,
799
+ h: expr.bbox.h - h / 2
800
+ },
801
+ chld: []
802
+ }
803
+ ff.push(e)
804
+ ff.push({
805
+ type: 'symb',
806
+ text: '\\bar',
807
+ mode: expr.mode,
808
+ bbox: {
809
+ x: dx + expr.chld[0].bbox.x,
810
+ y: dy,
811
+ w: expr.bbox.w - expr.chld[0].bbox.x,
812
+ h: h
813
+ },
814
+ chld: []
815
+ })
816
+ } else if (expr.text == '\\binom') {
817
+ const w = Math.min(expr.chld[0].bbox.x, expr.chld[1].bbox.x)
818
+ const e: Expr = {
819
+ type: 'symb',
820
+ mode: expr.mode,
821
+ text: '(',
822
+ bbox: {
823
+ x: dx,
824
+ y: dy,
825
+ w: w,
826
+ h: expr.bbox.h
827
+ },
828
+ chld: []
829
+ }
830
+ ff.push(e)
831
+ ff.push({
832
+ type: 'symb',
833
+ text: ')',
834
+ mode: expr.mode,
835
+ bbox: {
836
+ x: dx + expr.bbox.w - w,
837
+ y: dy,
838
+ w: w,
839
+ h: expr.bbox.h
840
+ },
841
+ chld: []
842
+ })
843
+ } else if (SYMB[expr.text] && SYMB[expr.text].flags.hat) {
844
+ const h: number = expr.chld[0].bbox.y
845
+ const e: Expr = {
846
+ type: 'symb',
847
+ mode: expr.mode,
848
+ text: expr.text,
849
+ bbox: {
850
+ x: dx,
851
+ y: dy,
852
+ w: expr.bbox.w,
853
+ h: h
854
+ },
855
+ chld: []
856
+ }
857
+ ff.push(e)
858
+ } else if (SYMB[expr.text] && SYMB[expr.text].flags.mat) {
859
+ const h: number = expr.chld[0].bbox.h
860
+ const e: Expr = {
861
+ type: 'symb',
862
+ text: expr.text,
863
+ mode: expr.mode,
864
+ bbox: {
865
+ x: dx,
866
+ y: dy + h,
867
+ w: expr.bbox.w,
868
+ h: expr.bbox.h - h
869
+ },
870
+ chld: []
871
+ }
872
+ ff.push(e)
873
+ } else if (expr.type != 'node' && expr.text != '^' && expr.text != '_') {
874
+ const e: Expr = {
875
+ type: expr.type == 'func' ? 'symb' : expr.type,
876
+ text: expr.text,
877
+ mode: expr.mode,
878
+ bbox: {
879
+ x: dx,
880
+ y: dy,
881
+ w: expr.bbox.w,
882
+ h: expr.bbox.h
883
+ },
884
+ chld: []
885
+ }
886
+ ff.push(e)
887
+ }
888
+ }
889
+ for (let i = 0; i < expr.chld.length; i++) {
890
+ const f = flat(expr.chld[i], dx, dy)
891
+ ff.push(...f)
892
+ }
893
+ return ff
894
+ }
895
+ const f = flat(expr, -expr.bbox.x, -expr.bbox.y)
896
+ expr.type = 'node'
897
+ expr.text = ''
898
+ expr.chld = f
899
+ }
900
+
901
+ function render(expr: Expr): number[][][] {
902
+ const o: number[][][] = []
903
+ for (let i = 0; i < expr.chld.length; i++) {
904
+ const e: Expr = expr.chld[i]
905
+ let s = e.bbox.h / 2
906
+ let isSmallHat = false
907
+ if (
908
+ SYMB[e.text] &&
909
+ SYMB[e.text].flags.hat &&
910
+ !SYMB[e.text].flags.xfl &&
911
+ !SYMB[e.text].flags.yfl
912
+ ) {
913
+ s *= 4
914
+ isSmallHat = true
915
+ }
916
+ if (SYMB[e.text] && SYMB[e.text].glyph) {
917
+ const d = HERSHEY(SYMB[e.text].glyph)
918
+ for (let j = 0; j < d.polylines.length; j++) {
919
+ const l: number[][] = []
920
+
921
+ for (let k = 0; k < d.polylines[j].length; k++) {
922
+ let x = d.polylines[j][k][0]
923
+ let y = d.polylines[j][k][1]
924
+
925
+ if (SYMB[e.text].flags.xfl) {
926
+ x = ((x - d.xmin) / Math.max(d.xmax - d.xmin, 1)) * e.bbox.w
927
+ x += e.bbox.x
928
+ } else if ((d.w / 16) * s > e.bbox.w) {
929
+ x = (x / Math.max(d.w, 1)) * e.bbox.w
930
+ x += e.bbox.x
931
+ } else {
932
+ x = (x / 16) * s
933
+ const p = (e.bbox.w - (d.w / 16) * s) / 2
934
+ x += e.bbox.x + p
935
+ }
936
+ if (SYMB[e.text].flags.yfl) {
937
+ y = ((y - d.ymin) / Math.max(d.ymax - d.ymin, 1)) * e.bbox.h
938
+ y += e.bbox.y
939
+ } else {
940
+ y = (y / 16) * s
941
+ if (isSmallHat) {
942
+ const p = (d.ymax + d.ymin) / 2
943
+ y -= (p / 16) * s
944
+ }
945
+ y += e.bbox.y + e.bbox.h / 2
946
+ }
947
+ l.push([x, y])
948
+ }
949
+ o.push(l)
950
+ }
951
+ } else if ((SYMB[e.text] && SYMB[e.text].flags.txt) || e.type == 'char') {
952
+ let x0 = e.bbox.x
953
+ const isVerb = !!(SYMB[e.text] && SYMB[e.text].flags.txt)
954
+ for (let n = Number(isVerb); n < e.text.length; n++) {
955
+ const d = HERSHEY(asciiMap(e.text[n], isVerb ? 'text' : e.mode))
956
+ if (!d) {
957
+ console.warn('unmapped character: ' + e.text[n])
958
+ continue
959
+ }
960
+ for (let j = 0; j < d.polylines.length; j++) {
961
+ const l: number[][] = []
962
+ for (let k = 0; k < d.polylines[j].length; k++) {
963
+ let x = d.polylines[j][k][0]
964
+ let y = d.polylines[j][k][1]
965
+ x /= 16
966
+ y /= 16
967
+ x *= s
968
+ y *= s
969
+ if (e.mode == 'tt') {
970
+ if (d.w > 16) {
971
+ x *= 16 / d.w
972
+ } else {
973
+ x += (16 - d.w) / 2 / 16
974
+ }
975
+ }
976
+ x += x0
977
+ y += e.bbox.y + e.bbox.h / 2
978
+ l.push([x, y])
979
+ }
980
+ o.push(l)
981
+ }
982
+ if (e.mode == 'tt') {
983
+ x0 += s
984
+ } else {
985
+ x0 += (d.w / 16) * s
986
+ }
987
+ }
988
+ }
989
+ }
990
+ return o
991
+ }
992
+
993
+ interface ExportOpt {
994
+ MIN_CHAR_H?: number
995
+ MAX_W?: number
996
+ MAX_H?: number
997
+ MARGIN_X?: number
998
+ MARGIN_Y?: number
999
+ SCALE_X?: number
1000
+ SCALE_Y?: number
1001
+ STROKE_W?: number
1002
+ FG_COLOR?: string
1003
+ BG_COLOR?: string
1004
+ }
1005
+
1006
+ function nf(x: number): number {
1007
+ return Math.round(x * 100) / 100
1008
+ }
1009
+
1010
+ export interface LaTexSVG {
1011
+ svg: string
1012
+ width: number
1013
+ height: number
1014
+ }
1015
+
1016
+ export class LaTexUtils {
1017
+ _latex: string
1018
+ _tree: Expr
1019
+ _tokens: string[]
1020
+ _polylines: number[][][]
1021
+
1022
+ constructor(latex: string) {
1023
+ this._latex = latex
1024
+ this._tokens = tokenize(latex)
1025
+ this._tree = parse(this._tokens)
1026
+ environments(this._tree.chld)
1027
+ plan(this._tree)
1028
+ flatten(this._tree)
1029
+ this._polylines = render(this._tree)
1030
+ }
1031
+
1032
+ private resolveScale(opt?: ExportOpt): number[] {
1033
+ if (opt == undefined) {
1034
+ return [16, 16, 16, 16]
1035
+ }
1036
+ let sclx: number = opt.SCALE_X ?? 16
1037
+ let scly: number = opt.SCALE_Y ?? 16
1038
+
1039
+ if (opt.MIN_CHAR_H != undefined) {
1040
+ let mh = 0
1041
+ for (let i = 0; i < this._tree.chld.length; i++) {
1042
+ const c: Expr = this._tree.chld[i]
1043
+ if (
1044
+ c.type == 'char' ||
1045
+ (SYMB[c.text] &&
1046
+ (SYMB[c.text].flags.txt || !Object.keys(SYMB[c.text].flags).length))
1047
+ ) {
1048
+ mh = Math.min(c.bbox.h, mh)
1049
+ }
1050
+ }
1051
+ const s: number = Math.max(1, opt.MIN_CHAR_H / mh)
1052
+ sclx *= s
1053
+ scly *= s
1054
+ }
1055
+ if (opt.MAX_W != undefined) {
1056
+ const s0 = sclx
1057
+ sclx = Math.min(sclx, opt.MAX_W / this._tree.bbox.w)
1058
+ scly *= sclx / s0
1059
+ }
1060
+ if (opt.MAX_H != undefined) {
1061
+ const s0 = scly
1062
+ scly = Math.min(scly, opt.MAX_H / this._tree.bbox.h)
1063
+ sclx *= scly / s0
1064
+ }
1065
+ const px: number = opt.MARGIN_X ?? sclx
1066
+ const py: number = opt.MARGIN_Y ?? scly
1067
+ return [px, py, sclx, scly]
1068
+ }
1069
+
1070
+ polylines(opt?: ExportOpt): number[][][] {
1071
+ if (!opt) opt = {}
1072
+ const polylines: number[][][] = []
1073
+ const [px, py, sclx, scly] = this.resolveScale(opt)
1074
+ for (let i = 0; i < this._polylines.length; i++) {
1075
+ polylines.push([])
1076
+ for (let j = 0; j < this._polylines[i].length; j++) {
1077
+ const [x, y] = this._polylines[i][j]
1078
+ polylines[polylines.length - 1].push([px + x * sclx, py + y * scly])
1079
+ }
1080
+ }
1081
+ return polylines
1082
+ }
1083
+
1084
+ pathd(opt?: ExportOpt): string {
1085
+ if (!opt) opt = {}
1086
+ let d = ''
1087
+ const [px, py, sclx, scly] = this.resolveScale(opt)
1088
+ for (let i = 0; i < this._polylines.length; i++) {
1089
+ for (let j = 0; j < this._polylines[i].length; j++) {
1090
+ const [x, y] = this._polylines[i][j]
1091
+ d += !j ? 'M' : 'L'
1092
+ d += `${nf(px + x * sclx)} ${nf(py + y * scly)}`
1093
+ }
1094
+ }
1095
+ return d
1096
+ }
1097
+
1098
+ svg(opt: ExportOpt): LaTexSVG {
1099
+ if (!opt) opt = {}
1100
+ const [px, py, sclx, scly] = this.resolveScale(opt)
1101
+ const w = nf(this._tree.bbox.w * sclx + px * 2)
1102
+ const h = nf(this._tree.bbox.h * scly + py * 2)
1103
+ let o = `<svg
1104
+ xmlns="http://www.w3.org/2000/svg"
1105
+ width="${w}" height="${h}"
1106
+ fill="none" stroke="${opt.FG_COLOR ?? 'black'}" stroke-width="${
1107
+ opt.STROKE_W ?? 1
1108
+ }"
1109
+ stroke-linecap="round" stroke-linejoin="round"
1110
+ >`
1111
+ if (opt.BG_COLOR) {
1112
+ o += `<rect x="${0}" y="${0}" width="${w}" height="${h}" fill="${
1113
+ opt.BG_COLOR
1114
+ }" stroke="none"></rect>`
1115
+ }
1116
+ o += `<path d="`
1117
+ for (let i = 0; i < this._polylines.length; i++) {
1118
+ o += 'M'
1119
+ for (let j = 0; j < this._polylines[i].length; j++) {
1120
+ const [x, y] = this._polylines[i][j]
1121
+ o += nf(px + x * sclx) + ' ' + nf(py + y * scly) + ' '
1122
+ }
1123
+ }
1124
+ o += `"/>`
1125
+ o += `</svg>`
1126
+ return {
1127
+ svg: `data:image/svg+xml;base64,${window.btoa(o)}`,
1128
+ width: Math.ceil(w),
1129
+ height: Math.ceil(h)
1130
+ }
1131
+ }
1132
+
1133
+ pdf(opt: ExportOpt): string {
1134
+ if (!opt) opt = {}
1135
+ const [px, py, sclx, scly] = this.resolveScale(opt)
1136
+
1137
+ const width = nf(this._tree.bbox.w * sclx + px * 2)
1138
+ const height = nf(this._tree.bbox.h * scly + py * 2)
1139
+ let head = `%PDF-1.1\n%%¥±ë\n1 0 obj\n<< /Type /Catalog\n/Pages 2 0 R\n>>endobj
1140
+ 2 0 obj\n<< /Type /Pages\n/Kids [3 0 R]\n/Count 1\n/MediaBox [0 0 ${width} ${height}]\n>>\nendobj
1141
+ 3 0 obj\n<< /Type /Page\n/Parent 2 0 R\n/Resources\n<< /Font\n<< /F1\n<< /Type /Font
1142
+ /Subtype /Type1\n/BaseFont /Times-Roman\n>>\n>>\n>>\n/Contents [`
1143
+ let pdf = ''
1144
+ let count = 4
1145
+ for (let i = 0; i < this._polylines.length; i++) {
1146
+ pdf += `${count} 0 obj \n<< /Length 0 >>\n stream\n 1 j 1 J ${
1147
+ opt.STROKE_W ?? 1
1148
+ } w\n`
1149
+ for (let j = 0; j < this._polylines[i].length; j++) {
1150
+ const [x, y] = this._polylines[i][j]
1151
+ pdf += `${nf(px + x * sclx)} ${nf(height - (py + y * scly))} ${
1152
+ j ? 'l' : 'm'
1153
+ } `
1154
+ }
1155
+ pdf += '\nS\nendstream\nendobj\n'
1156
+ head += `${count} 0 R `
1157
+ count++
1158
+ }
1159
+ head += ']\n>>\nendobj\n'
1160
+ pdf += '\ntrailer\n<< /Root 1 0 R \n /Size 0\n >>startxref\n\n%%EOF\n'
1161
+ return head + pdf
1162
+ }
1163
+
1164
+ boxes(opt: ExportOpt): Bbox[] {
1165
+ if (!opt) opt = {}
1166
+ const [px, py, sclx, scly] = this.resolveScale(opt)
1167
+ const bs: Bbox[] = []
1168
+ for (let i = 0; i < this._tree.chld.length; i++) {
1169
+ const { x, y, w, h } = this._tree.chld[i].bbox
1170
+ bs.push({ x: px + x * sclx, y: py + y * scly, w: w * sclx, h: h * scly })
1171
+ }
1172
+ return bs
1173
+ }
1174
+
1175
+ box(opt: ExportOpt): Bbox {
1176
+ if (!opt) opt = {}
1177
+ const [px, py, sclx, scly] = this.resolveScale(opt)
1178
+ return {
1179
+ x: px + this._tree.bbox.x * sclx,
1180
+ y: py + this._tree.bbox.y * scly,
1181
+ w: this._tree.bbox.w * sclx,
1182
+ h: this._tree.bbox.h * scly
1183
+ }
1184
+ }
1185
+ }
1186
+
1187
+ const _impl: Record<string, Function> = {
1188
+ tokenize,
1189
+ parse,
1190
+ environments,
1191
+ plan,
1192
+ flatten,
1193
+ render
1194
+ }
1195
+
1196
+ export { CONFIG, _impl }