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
package/CLAUDE.md ADDED
@@ -0,0 +1,110 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Development Commands
6
+
7
+ - `npm run dev` - Start development server
8
+ - `npm run lib` - Build library (runs lint, type check, and builds library)
9
+ - `npm run build` - Build app (runs lint, type check, and builds app)
10
+ - `npm run lint` - Run ESLint
11
+ - `npm run type:check` - Run TypeScript type checking without emitting
12
+ - `npm run cypress:open` - Open Cypress test runner GUI
13
+ - `npm run cypress:run` - Run Cypress tests headlessly
14
+ - `npm run docs:dev` - Start VitePress documentation server
15
+ - `npm run docs:build` - Build VitePress documentation
16
+ - `npm run release` - Run release script
17
+
18
+ To run a single Cypress test file: `npx cypress run --spec cypress/e2e/<test-file>.cy.ts`
19
+
20
+ ## Git Hooks
21
+
22
+ Pre-commit hooks run `npm run lint` and `npm run type:check`. Commit message must follow Conventional Commits format: `feat:`, `fix:`, `docs:`, `refactor:`, etc.
23
+
24
+ ## Architecture Overview
25
+
26
+ This is a canvas-based rich text editor built with TypeScript. The core architecture follows a modular, layered design:
27
+
28
+ ### Core Components
29
+
30
+ **Editor Class** (`src/editor/index.ts`)
31
+ - Main entry point that orchestrates all subsystems
32
+ - Exposes public API via the `command` property (e.g., `editor.command.executeBold()`)
33
+ - Manages lifecycle through `destroy()` method
34
+
35
+ **Draw Class** (`src/editor/core/draw/Draw.ts`)
36
+ - Central rendering engine (~96KB) responsible for canvas drawing
37
+ - Manages pages, rows, elements, and cursor rendering
38
+ - Coordinates all particle types and frame elements
39
+
40
+ **Command Pattern** (`src/editor/core/command/`)
41
+ - `Command.ts`: Facade exposing all execute methods (e.g., `executeBold`, `executeUndo`)
42
+ - `CommandAdapt.ts`: Adapter that bridges commands to Draw context
43
+ - All commands follow `execute*` naming convention
44
+
45
+ ### Element System
46
+
47
+ The editor uses a hierarchical element model defined in `src/editor/interface/Element.ts`:
48
+
49
+ **IElement** - Base interface for all content elements with:
50
+ - Basic properties: `id`, `type`, `value`, `extension`, `externalId`
51
+ - Style: `font`, `size`, `bold`, `color`, etc. (IElementStyle)
52
+ - Rules: `hide` (IElementRule)
53
+ - Groups: `groupIds` (IElementGroup)
54
+
55
+ **Element Types** (ElementType enum):
56
+ - Text particles: TextParticle, ListParticle, HyperlinkParticle, etc.
57
+ - Block particles: ImageParticle, TableParticle, LaTexParticle, etc.
58
+ - Control particles: CheckboxParticle, RadioParticle, etc.
59
+ - Frame elements: Margin, Background, PageNumber, etc.
60
+
61
+ ### Directory Structure
62
+
63
+ ```
64
+ src/editor/
65
+ ├── core/
66
+ │ ├── draw/ # Rendering engine
67
+ │ │ ├── particle/ # Element rendering (text, image, table, latex, etc.)
68
+ │ │ ├── control/ # Control component rendering
69
+ │ │ ├── frame/ # Frame elements (margin, background, borders)
70
+ │ │ ├── richtext/ # Rich text decorations (underline, highlight)
71
+ │ │ └── interactive/ # Interactive features (search, graffiti)
72
+ │ ├── command/ # Command pattern implementation
73
+ │ ├── event/ # Canvas and global event handling
74
+ │ ├── observer/ # Mouse, selection, image observers
75
+ │ ├── worker/ # Web workers for async operations
76
+ │ └── [other subsystems]
77
+ ├── interface/ # TypeScript interfaces (40+ files)
78
+ ├── dataset/ # Enums and constants
79
+ └── utils/ # Utility functions
80
+ ```
81
+
82
+ ### Web Workers
83
+
84
+ Async operations use Web Workers managed by `WorkerManager.ts`:
85
+ - WordCountWorker - Count words in element list
86
+ - CatalogWorker - Generate document catalog/TOC
87
+ - GroupWorker - Extract group IDs from elements
88
+ - ValueWorker - Get document value asynchronously
89
+
90
+ ### Event System
91
+
92
+ **EventBus** (`src/editor/core/event/eventbus/`) - Pub/sub system for editor events
93
+ **Listener** (`src/editor/core/listener/`) - Callback system for change notifications
94
+ **CanvasEvent** and **GlobalEvent** - Handle mouse, keyboard, and drag events
95
+
96
+ ### Plugin System
97
+
98
+ Plugins extend functionality through `editor.use(plugin)` pattern. See `src/editor/core/plugin/Plugin.ts`.
99
+
100
+ ## Key Patterns
101
+
102
+ **Command-Draw Separation**: Commands access Draw functionality through CommandAdapt, not directly. This prevents exposing internal Draw context to external consumers.
103
+
104
+ **Element Formatting**: Elements are formatted via `formatElementList()` utility which applies defaults and compensates missing properties.
105
+
106
+ **Zone-Based Layout**: Documents support header/main/footer zones managed through the Zone system.
107
+
108
+ **Position-Range Model**: Cursor positions and selections are tracked through Position and RangeManager classes.
109
+
110
+ **History Management**: Undo/redo functionality via HistoryManager with command history stack.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021-present, hufe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,110 @@
1
+ <h1 align="center">canvas-editor</h1>
2
+
3
+ <p align="center">
4
+ <a href="https://trendshift.io/repositories/8401" target="_blank"><img src="https://trendshift.io/api/badge/repositories/8401" alt="Hufe921%2Fcanvas-editor | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/@hufe921/canvas-editor" target="_blank"><img src="https://img.shields.io/npm/v/@hufe921/canvas-editor.svg?sanitize=true" alt="Version"></a>
9
+ <a href="https://github.com/hufe921/canvas-editor/actions" target="_blank">
10
+ <img alt="Cypress Passing" src="https://github.com/hufe921/canvas-editor/workflows/cypress/badge.svg" />
11
+ </a>
12
+ <a href="https://github.com/hufe921/canvas-editor/graphs/contributors" target="_blank">
13
+ <img alt="GitHub Contributors" src="https://img.shields.io/github/contributors/hufe921/canvas-editor" />
14
+ </a>
15
+ <a href="https://www.npmjs.com/package/@hufe921/canvas-editor" target="_blank"><img src="https://img.shields.io/npm/l/@hufe921/canvas-editor.svg?sanitize=true" alt="License"></a>
16
+ <a href="https://github.com/Hufe921/canvas-editor/issues/new/choose" target="_blank"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs"></a>
17
+ <a href="https://zread.ai/Hufe921/canvas-editor" target="_blank"><img src="https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff" alt="zread"/></a>
18
+ <a href="https://deepwiki.com/Hufe921/canvas-editor" target="_blank"><img src="https://img.shields.io/badge/Ask_DeepWiki-_.svg?style=flat&color=0094de&labelColor=000000&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJzaXplLTQgdHJhbnNmb3JtIHRyYW5zaXRpb24tdHJhbnNmb3JtIGR1cmF0aW9uLTcwMCBncm91cC1ob3Zlcjpyb3RhdGUtMTgwIFsmYW1wO19wYXRoXTpzdHJva2UtMCIgdmlld0JveD0iMTEwIDExMCA0NjAgNTAwIj48cGF0aCBkPSJNNDE5IDMzMnExNi03IDMyIDBsMjUgMTUgMyAxIDMgMSAzLTEgMy0xIDUxLTI5cTYtMyA2LTExdi01OHEwLTgtNi0xMWwtNTEtMjlxLTYtMy0xMiAwbC01MSAyOXYxbC0yIDEtMiAydjFsLTEgMnYxbC0xIDN2MjlhMzIgMzIgMCAwIDEtNDggMjhsLTI1LTE1LTMtMS0zLTEtMyAxLTMgMS01MSAyOXEtNSAzLTYgMTF2NThxMSA4IDYgMTFsNTEgMjkgMyAxIDMgMSAzLTEgMy0xIDI1LTE1YTMyIDMyIDAgMCAxIDQ4IDI4djI5bDEgM3YxbDEgMnYxbDIgMiAyIDIgNTEgMjkgNiAyIDYtMiA1MS0yOXE2LTMgNi0xMXYtNThxMC04LTYtMTFsLTUxLTI5LTMtMS0zLTEtMyAxLTMgMS0yNSAxNWEzMiAzMiAwIDAgMS00OC0yOHExLTE4IDE2LTI4IiBzdHlsZT0iZmlsbDojMjFjMTlhIi8+PHBhdGggZD0ibTE0MSAzMTggNTEgMjkgNiAyIDYtMiA1MS0yOXYtMWwyLTEgMi0ydi0xbDEtMnYtMWwxLTN2LTI5YTMyIDMyIDAgMCAxIDQ4LTI4bDI1IDE1IDMgMSAzIDEgMy0xIDMtMSA1MS0yOXE2LTMgNi0xMXYtNThxMC04LTYtMTFsLTUxLTI5cS02LTMtMTIgMGwtNTEgMjktMiAyaC0xbC0xIDJ2MWwtMSAydjFsLTEgM3YyOWEzMiAzMiAwIDAgMS00OCAyOGwtMjUtMTUtMy0xLTMtMS0zIDEtMyAxLTUxIDI5cS02IDMtNiAxMXY1OHEwIDggNiAxMSIgc3R5bGU9ImZpbGw6IzM5NjljYSIvPjxwYXRoIGQ9Im0zOTcgNDg0LTUxLTI5LTMtMS0zLTEtMyAxLTMgMS0yNSAxNWEzMiAzMiAwIDAgMS00OC0yOHYtMjlsLTEtM3YtMWwtMS0ydi0xbC0yLTItMi0xdi0xbC01MS0yOXEtNi0zLTEyIDBsLTUxIDI5cS02IDMtNiAxMXY1OHEwIDggNiAxMWw1MSAyOSAzIDEgMyAxIDMtMSAzLTEgMjUtMTVhMzIgMzIgMCAwIDEgNDggMjh2MjlsMSAzdjFsMSAydjFsMiAyIDIgMiA1MSAyOSA2IDIgNi0yIDUxLTI5cTYtMyA2LTExdi01OHEwLTgtNi0xMSIgc3R5bGU9ImZpbGw6IzAyOTRkZSIvPjwvc3ZnPg==&logoColor=ffffff" alt="DeepWiki"/></a>
19
+ </p>
20
+
21
+ <p align="center"> a rich text editor by canvas/svg</p>
22
+
23
+ <p align="center">
24
+ <a href="https://hufe.club/canvas-editor" target="_blank">View Demo</a>
25
+ ·
26
+ <a href="https://hufe.club/canvas-editor-docs" target="_blank">View Docs</a>
27
+ ·
28
+ <a href="https://github.com/Hufe921/canvas-editor/issues/new?assignees=&labels=&projects=&template=bug_report.yml" target="_blank">Report Bug</a>
29
+ ·
30
+ <a href="https://github.com/Hufe921/canvas-editor/issues/new?assignees=&labels=%3Asparkles%3A+feature+request&projects=&template=feature_request.yml" target="_blank">Request Feature</a>
31
+ ·
32
+ <a href="https://github.com/Hufe921/canvas-editor/discussions" target="_blank">FAQ</a>
33
+ </p>
34
+
35
+ <p align="center">Love the project? Please consider <a href="https://hufe.club/donate.jpg" target="_blank">donating(赞助)</a> to help it improve!</p>
36
+
37
+ ## Tips
38
+
39
+ 1. Official plugin: [canvas-editor-plugin](https://github.com/Hufe921/canvas-editor-plugin)
40
+ 2. The render layer by svg is under development, see [feature/svg](https://github.com/Hufe921/canvas-editor/tree/feature/svg)
41
+ 3. The export pdf feature is available now, see [feature/pdf](https://github.com/Hufe921/canvas-editor/tree/feature/pdf)
42
+ 4. The AI-powered text processing demo, see [feature/ai](https://github.com/Hufe921/canvas-editor/tree/feature/ai)
43
+ 5. Table pagination [#41](https://github.com/Hufe921/canvas-editor/issues/41) is under active development, see: [poc/table-paging](https://github.com/Hufe921/canvas-editor/tree/poc/table-paging) · [demo](https://hufe.club/canvas-editor-table/)
44
+
45
+ ## Basic usage
46
+
47
+ ```bash
48
+ npm i @hufe921/canvas-editor --save
49
+ ```
50
+
51
+ ```html
52
+ <div class="canvas-editor"></div>
53
+ ```
54
+
55
+ ```javascript
56
+ import Editor from '@hufe921/canvas-editor'
57
+
58
+ new Editor(document.querySelector('.canvas-editor'), {
59
+ main: [
60
+ {
61
+ value: 'Hello World'
62
+ }
63
+ ]
64
+ })
65
+ ```
66
+
67
+ ## Features
68
+
69
+ - Rich text operations (Undo, Redo, Font, Size, Bold, Italic, Underline, Strikeout, Superscript, Alignment, Title, List, ...)
70
+ - Insert elements (Table, Image, Link, Code Block, Page Break, Math Formula, Date Picker, Block, ...)
71
+ - Print (Based on canvas to picture, pdf drawing)
72
+ - Controls (Select, Text, Date, Radio, Checkbox)
73
+ - Contextmenu (Internal, Custom)
74
+ - Shortcut keys (Internal, Custom)
75
+ - Drag and Drop(Text, Element, Control)
76
+ - Header, Footer, Page Number
77
+ - Page Margin
78
+ - Watermark
79
+ - Pagination
80
+ - Comment
81
+ - Catalog
82
+
83
+ ## Roadmap
84
+
85
+ 1. Table paging
86
+ 2. Control rules
87
+ 3. Improve performance
88
+ 4. [CRDT](https://github.com/Hufe921/canvas-editor/tree/feature/CRDT)
89
+
90
+ ## Snapshot
91
+
92
+ ![image](https://github.com/Hufe921/canvas-editor/blob/main/src/assets/snapshots/main_v0.9.35.png)
93
+
94
+ ## Install
95
+
96
+ `yarn`
97
+
98
+ ## Dev
99
+
100
+ `npm run dev`
101
+
102
+ ## Build
103
+
104
+ #### app
105
+
106
+ `npm run build`
107
+
108
+ #### lib
109
+
110
+ `npm run lib`
@@ -0,0 +1,46 @@
1
+ import Editor, { ControlType, ElementType } from '../../../src/editor'
2
+
3
+ describe('控件-复选框', () => {
4
+ beforeEach(() => {
5
+ cy.visit('http://localhost:3000/canvas-editor/')
6
+
7
+ cy.get('canvas').first().as('canvas').should('have.length', 1)
8
+ })
9
+
10
+ const elementType: ElementType = <ElementType>'control'
11
+ const controlType: ControlType = <ControlType>'checkbox'
12
+
13
+ it('复选框', () => {
14
+ cy.getEditor().then((editor: Editor) => {
15
+ editor.command.executeSelectAll()
16
+
17
+ editor.command.executeBackspace()
18
+
19
+ editor.command.executeInsertElementList([
20
+ {
21
+ type: elementType,
22
+ value: '',
23
+ control: {
24
+ code: '98175',
25
+ type: controlType,
26
+ value: null,
27
+ valueSets: [
28
+ {
29
+ value: '有',
30
+ code: '98175'
31
+ },
32
+ {
33
+ value: '无',
34
+ code: '98176'
35
+ }
36
+ ]
37
+ }
38
+ }
39
+ ])
40
+
41
+ const data = editor.command.getValue().data.main[0]
42
+
43
+ expect(data.control!.code).to.be.eq('98175')
44
+ })
45
+ })
46
+ })
@@ -0,0 +1,56 @@
1
+ import Editor, { ControlType, ElementType } from '../../../src/editor'
2
+
3
+ describe('控件-列举型', () => {
4
+ beforeEach(() => {
5
+ cy.visit('http://localhost:3000/canvas-editor/')
6
+
7
+ cy.get('canvas').first().as('canvas').should('have.length', 1)
8
+ })
9
+
10
+ const text = `有`
11
+ const elementType: ElementType = <ElementType>'control'
12
+ const controlType: ControlType = <ControlType>'select'
13
+
14
+ it('列举型', () => {
15
+ cy.getEditor().then((editor: Editor) => {
16
+ editor.command.executeSelectAll()
17
+
18
+ editor.command.executeBackspace()
19
+
20
+ editor.command.executeInsertElementList([
21
+ {
22
+ type: elementType,
23
+ value: '',
24
+ control: {
25
+ type: controlType,
26
+ value: null,
27
+ placeholder: '列举型',
28
+ valueSets: [
29
+ {
30
+ value: '有',
31
+ code: '98175'
32
+ },
33
+ {
34
+ value: '无',
35
+ code: '98176'
36
+ }
37
+ ]
38
+ }
39
+ }
40
+ ])
41
+
42
+ cy.get('@canvas').type(`{leftArrow}`)
43
+
44
+ cy.get('.ce-select-control-popup li')
45
+ .eq(0)
46
+ .click()
47
+ .then(() => {
48
+ const data = editor.command.getValue().data.main[0]
49
+
50
+ expect(data.control!.value![0].value).to.be.eq(text)
51
+
52
+ expect(data.control!.code).to.be.eq('98175')
53
+ })
54
+ })
55
+ })
56
+ })
@@ -0,0 +1,43 @@
1
+ import Editor, { ControlType, ElementType } from '../../../src/editor'
2
+
3
+ describe('控件-文本型', () => {
4
+ beforeEach(() => {
5
+ cy.visit('http://localhost:3000/canvas-editor/')
6
+
7
+ cy.get('canvas').first().as('canvas').should('have.length', 1)
8
+ })
9
+
10
+ const text = `canvas-editor`
11
+ const elementType: ElementType = <ElementType>'control'
12
+ const controlType: ControlType = <ControlType>'text'
13
+
14
+ it('文本型', () => {
15
+ cy.getEditor().then((editor: Editor) => {
16
+ editor.command.executeSelectAll()
17
+
18
+ editor.command.executeBackspace()
19
+
20
+ editor.command.executeInsertElementList([
21
+ {
22
+ type: elementType,
23
+ value: '',
24
+ control: {
25
+ type: controlType,
26
+ value: null,
27
+ placeholder: '文本型'
28
+ }
29
+ }
30
+ ])
31
+
32
+ cy.get('@canvas').type(`{leftArrow}`)
33
+
34
+ cy.get('.ce-inputarea')
35
+ .type(text)
36
+ .then(() => {
37
+ const data = editor.command.getValue().data.main[0]
38
+
39
+ expect(data.control!.value![0].value).to.be.eq(text)
40
+ })
41
+ })
42
+ })
43
+ })
@@ -0,0 +1,67 @@
1
+ import Editor from '../../src/editor'
2
+
3
+ describe('基础功能', () => {
4
+ beforeEach(() => {
5
+ cy.visit('http://localhost:3000/canvas-editor/')
6
+
7
+ cy.get('canvas').first().as('canvas').should('have.length', 1)
8
+ })
9
+
10
+ const text = 'canvas-editor'
11
+
12
+ it('编辑保存', () => {
13
+ cy.getEditor().then((editor: Editor) => {
14
+ editor.command.executeSelectAll()
15
+
16
+ editor.command.executeBackspace()
17
+
18
+ cy.get('@canvas')
19
+ .type(text)
20
+ .then(() => {
21
+ const data = editor.command.getValue().data.main
22
+
23
+ expect(data[0].value).to.eq(text)
24
+ })
25
+ })
26
+ })
27
+
28
+ it('模式切换', () => {
29
+ cy.get('@canvas').click()
30
+
31
+ cy.get('.ce-cursor').should('have.css', 'display', 'block')
32
+
33
+ cy.get('.editor-mode').click().click()
34
+
35
+ cy.get('.editor-mode').contains('只读')
36
+
37
+ cy.get('@canvas').click()
38
+
39
+ cy.get('.ce-cursor').should('have.css', 'display', 'none')
40
+ })
41
+
42
+ it('页面缩放', () => {
43
+ cy.get('.page-scale-add').click()
44
+
45
+ cy.get('.page-scale-percentage').contains('110%')
46
+
47
+ cy.get('.page-scale-minus').click().click()
48
+
49
+ cy.get('.page-scale-percentage').contains('90%')
50
+ })
51
+
52
+ it('字数统计', () => {
53
+ cy.getEditor().then((editor: Editor) => {
54
+ editor.command.executeSelectAll()
55
+
56
+ editor.command.executeBackspace()
57
+
58
+ editor.command.executeInsertElementList([
59
+ {
60
+ value: 'canvas-editor 2022 编辑器'
61
+ }
62
+ ])
63
+
64
+ cy.get('.word-count').contains('7')
65
+ })
66
+ })
67
+ })
@@ -0,0 +1,38 @@
1
+ import Editor from '../../../src/editor'
2
+
3
+ describe('菜单-内容块', () => {
4
+ const url = 'http://localhost:3000/canvas-editor/'
5
+
6
+ beforeEach(() => {
7
+ cy.visit(url)
8
+
9
+ cy.get('canvas').first().as('canvas').should('have.length', 1)
10
+ })
11
+
12
+ it('内容块', () => {
13
+ cy.getEditor().then((editor: Editor) => {
14
+ editor.command.executeSelectAll()
15
+
16
+ editor.command.executeBackspace()
17
+
18
+ cy.get('.menu-item__block').click()
19
+
20
+ cy.get('.dialog-option__item [name="width"]').type('500')
21
+
22
+ cy.get('.dialog-option__item [name="height"]').type('300')
23
+
24
+ cy.get('.dialog-option__item [name="src"]').type(url)
25
+
26
+ cy.get('.dialog-menu button')
27
+ .eq(1)
28
+ .click()
29
+ .then(() => {
30
+ const data = editor.command.getValue().data.main
31
+
32
+ expect(data[0].type).to.eq('block')
33
+
34
+ expect(data[0].block?.iframeBlock?.src).to.eq(url)
35
+ })
36
+ })
37
+ })
38
+ })
@@ -0,0 +1,33 @@
1
+ import Editor, { ElementType } from '../../../src/editor'
2
+
3
+ describe('菜单-复选框', () => {
4
+ beforeEach(() => {
5
+ cy.visit('http://localhost:3000/canvas-editor/')
6
+
7
+ cy.get('canvas').first().as('canvas').should('have.length', 1)
8
+ })
9
+
10
+ const type: ElementType = <ElementType>'checkbox'
11
+
12
+ it('代码块', () => {
13
+ cy.getEditor().then((editor: Editor) => {
14
+ editor.command.executeSelectAll()
15
+
16
+ editor.command.executeBackspace()
17
+
18
+ editor.command.executeInsertElementList([
19
+ {
20
+ type,
21
+ value: '',
22
+ checkbox: {
23
+ value: true
24
+ }
25
+ }
26
+ ])
27
+
28
+ const data = editor.command.getValue().data.main[0]
29
+
30
+ expect(data.checkbox?.value).to.eq(true)
31
+ })
32
+ })
33
+ })
@@ -0,0 +1,34 @@
1
+ import Editor from '../../../src/editor'
2
+
3
+ describe('菜单-代码块', () => {
4
+ beforeEach(() => {
5
+ cy.visit('http://localhost:3000/canvas-editor/')
6
+
7
+ cy.get('canvas').first().as('canvas').should('have.length', 1)
8
+ })
9
+
10
+ const text = `console.log('canvas-editor')`
11
+
12
+ it('代码块', () => {
13
+ cy.getEditor().then((editor: Editor) => {
14
+ editor.command.executeSelectAll()
15
+
16
+ editor.command.executeBackspace()
17
+
18
+ cy.get('.menu-item__codeblock').click()
19
+
20
+ cy.get('.dialog-option [name="codeblock"]').type(text)
21
+
22
+ cy.get('.dialog-menu button')
23
+ .eq(1)
24
+ .click()
25
+ .then(() => {
26
+ const data = editor.command.getValue().data.main[2]
27
+
28
+ expect(data.value).to.eq('log')
29
+
30
+ expect(data.color).to.eq('#b9a40a')
31
+ })
32
+ })
33
+ })
34
+ })
@@ -0,0 +1,28 @@
1
+ import Editor from '../../../src/editor'
2
+
3
+ describe('菜单-日期选择器', () => {
4
+ beforeEach(() => {
5
+ cy.visit('http://localhost:3000/canvas-editor/')
6
+
7
+ cy.get('canvas').first().as('canvas').should('have.length', 1)
8
+ })
9
+
10
+ it('LaTeX', () => {
11
+ cy.getEditor().then((editor: Editor) => {
12
+ editor.command.executeSelectAll()
13
+
14
+ editor.command.executeBackspace()
15
+
16
+ cy.get('.menu-item__date').click()
17
+
18
+ cy.get('.menu-item__date li')
19
+ .first()
20
+ .click()
21
+ .then(() => {
22
+ const data = editor.command.getValue().data.main
23
+
24
+ expect(data[0].type).to.eq('date')
25
+ })
26
+ })
27
+ })
28
+ })
@@ -0,0 +1,40 @@
1
+ import Editor from '../../../src/editor'
2
+
3
+ describe('菜单-清除格式', () => {
4
+ beforeEach(() => {
5
+ cy.visit('http://localhost:3000/canvas-editor/')
6
+
7
+ cy.get('canvas').first().as('canvas').should('have.length', 1)
8
+ })
9
+
10
+ const text = 'canvas-editor'
11
+ const textLength = text.length
12
+
13
+ it('清除格式', () => {
14
+ cy.getEditor().then((editor: Editor) => {
15
+ editor.command.executeSelectAll()
16
+
17
+ editor.command.executeBackspace()
18
+
19
+ editor.command.executeInsertElementList([
20
+ {
21
+ value: text,
22
+ bold: true,
23
+ italic: true
24
+ }
25
+ ])
26
+
27
+ editor.command.executeSetRange(0, textLength)
28
+
29
+ cy.get('.menu-item__format')
30
+ .click()
31
+ .then(() => {
32
+ const data = editor.command.getValue().data.main
33
+
34
+ expect(data[0].italic).to.eq(undefined)
35
+
36
+ expect(data[0].bold).to.eq(undefined)
37
+ })
38
+ })
39
+ })
40
+ })
@@ -0,0 +1,39 @@
1
+ import Editor from '../../../src/editor'
2
+
3
+ describe('菜单-超链接', () => {
4
+ beforeEach(() => {
5
+ cy.visit('http://localhost:3000/canvas-editor/')
6
+
7
+ cy.get('canvas').first().as('canvas').should('have.length', 1)
8
+ })
9
+
10
+ const text = 'canvas-editor'
11
+ const url = 'https://hufe.club/canvas-editor'
12
+
13
+ it('超链接', () => {
14
+ cy.getEditor().then((editor: Editor) => {
15
+ editor.command.executeSelectAll()
16
+
17
+ editor.command.executeBackspace()
18
+
19
+ cy.get('.menu-item__hyperlink').click()
20
+
21
+ cy.get('.dialog-option__item [name="name"]').type(text)
22
+
23
+ cy.get('.dialog-option__item [name="url"]').type(url)
24
+
25
+ cy.get('.dialog-menu button')
26
+ .eq(1)
27
+ .click()
28
+ .then(() => {
29
+ const data = editor.command.getValue().data.main
30
+
31
+ expect(data[0].type).to.eq('hyperlink')
32
+
33
+ expect(data[0].url).to.eq(url)
34
+
35
+ expect(data[0]?.valueList?.[0].value).to.eq(text)
36
+ })
37
+ })
38
+ })
39
+ })