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,870 @@
1
+ import { ElementType, ListStyle, RowFlex, VerticalAlign } from '../..'
2
+ import { ZERO } from '../../dataset/constant/Common'
3
+ import { ControlComponent } from '../../dataset/enum/Control'
4
+ import {
5
+ IComputePageRowPositionPayload,
6
+ IComputePageRowPositionResult,
7
+ IComputeRowPositionPayload,
8
+ IFloatPosition,
9
+ IGetFloatPositionByXYPayload,
10
+ ISetSurroundPositionPayload
11
+ } from '../../interface/Position'
12
+ import { IEditorOption } from '../../interface/Editor'
13
+ import { IElement, IElementPosition } from '../../interface/Element'
14
+ import {
15
+ ICurrentPosition,
16
+ IGetPositionByXYPayload,
17
+ IPositionContext
18
+ } from '../../interface/Position'
19
+ import { Draw } from '../draw/Draw'
20
+ import { EditorMode, EditorZone } from '../../dataset/enum/Editor'
21
+ import { deepClone, isRectIntersect } from '../../utils'
22
+ import { ImageDisplay } from '../../dataset/enum/Common'
23
+ import { DeepRequired } from '../../interface/Common'
24
+ import { EventBus } from '../event/eventbus/EventBus'
25
+ import { EventBusMap } from '../../interface/EventBus'
26
+ import { getIsBlockElement } from '../../utils/element'
27
+
28
+ export class Position {
29
+ private cursorPosition: IElementPosition | null
30
+ private positionContext: IPositionContext
31
+ private positionList: IElementPosition[]
32
+ private floatPositionList: IFloatPosition[]
33
+
34
+ private draw: Draw
35
+ private eventBus: EventBus<EventBusMap>
36
+ private options: DeepRequired<IEditorOption>
37
+
38
+ constructor(draw: Draw) {
39
+ this.positionList = []
40
+ this.floatPositionList = []
41
+ this.cursorPosition = null
42
+ this.positionContext = {
43
+ isTable: false,
44
+ isControl: false
45
+ }
46
+
47
+ this.draw = draw
48
+ this.eventBus = draw.getEventBus()
49
+ this.options = draw.getOptions()
50
+ }
51
+
52
+ public getFloatPositionList(): IFloatPosition[] {
53
+ return this.floatPositionList
54
+ }
55
+
56
+ public getTablePositionList(
57
+ sourceElementList: IElement[]
58
+ ): IElementPosition[] {
59
+ const { index, trIndex, tdIndex } = this.positionContext
60
+ return (
61
+ sourceElementList[index!].trList![trIndex!].tdList[tdIndex!]
62
+ .positionList || []
63
+ )
64
+ }
65
+
66
+ public getPositionList(): IElementPosition[] {
67
+ return this.positionContext.isTable
68
+ ? this.getTablePositionList(this.draw.getOriginalElementList())
69
+ : this.getOriginalPositionList()
70
+ }
71
+
72
+ public getMainPositionList(): IElementPosition[] {
73
+ return this.positionContext.isTable
74
+ ? this.getTablePositionList(this.draw.getOriginalMainElementList())
75
+ : this.positionList
76
+ }
77
+
78
+ public getOriginalPositionList(): IElementPosition[] {
79
+ const zoneManager = this.draw.getZone()
80
+ if (zoneManager.isHeaderActive()) {
81
+ const header = this.draw.getHeader()
82
+ return header.getPositionList()
83
+ }
84
+ if (zoneManager.isFooterActive()) {
85
+ const footer = this.draw.getFooter()
86
+ return footer.getPositionList()
87
+ }
88
+ return this.positionList
89
+ }
90
+
91
+ public getOriginalMainPositionList(): IElementPosition[] {
92
+ return this.positionList
93
+ }
94
+
95
+ public getSelectionPositionList(): IElementPosition[] | null {
96
+ const { startIndex, endIndex } = this.draw.getRange().getRange()
97
+ if (startIndex === endIndex) return null
98
+ const positionList = this.getPositionList()
99
+ return positionList.slice(startIndex + 1, endIndex + 1)
100
+ }
101
+
102
+ public setPositionList(payload: IElementPosition[]) {
103
+ this.positionList = payload
104
+ }
105
+
106
+ public setFloatPositionList(payload: IFloatPosition[]) {
107
+ this.floatPositionList = payload
108
+ }
109
+
110
+ public computePageRowPosition(
111
+ payload: IComputePageRowPositionPayload
112
+ ): IComputePageRowPositionResult {
113
+ const {
114
+ positionList,
115
+ rowList,
116
+ pageNo,
117
+ startX,
118
+ startY,
119
+ startRowIndex,
120
+ startIndex,
121
+ innerWidth,
122
+ zone
123
+ } = payload
124
+ const {
125
+ scale,
126
+ table: { tdPadding }
127
+ } = this.options
128
+ let x = startX
129
+ let y = startY
130
+ let index = startIndex
131
+ for (let i = 0; i < rowList.length; i++) {
132
+ const curRow = rowList[i]
133
+ // 行存在环绕的可能性均不设置行布局
134
+ if (!curRow.isSurround) {
135
+ // 计算行偏移量(行居中、居右)
136
+ const curRowWidth = curRow.width + (curRow.offsetX || 0)
137
+ if (curRow.rowFlex === RowFlex.CENTER) {
138
+ x += (innerWidth - curRowWidth) / 2
139
+ } else if (curRow.rowFlex === RowFlex.RIGHT) {
140
+ x += innerWidth - curRowWidth
141
+ }
142
+ }
143
+ // 当前行X/Y轴偏移量
144
+ x += curRow.offsetX || 0
145
+ y += curRow.offsetY || 0
146
+ // 当前td所在位置
147
+ const tablePreX = x
148
+ const tablePreY = y
149
+ for (let j = 0; j < curRow.elementList.length; j++) {
150
+ const element = curRow.elementList[j]
151
+ const metrics = element.metrics
152
+ const offsetY =
153
+ !element.hide &&
154
+ ((element.imgDisplay !== ImageDisplay.INLINE &&
155
+ element.type === ElementType.IMAGE) ||
156
+ element.type === ElementType.LATEX)
157
+ ? curRow.ascent - metrics.height
158
+ : curRow.ascent
159
+ // 偏移量(内部计算使用)
160
+ if (element.left) {
161
+ x += element.left
162
+ }
163
+ // 偏移量(外部传入)
164
+ if (element.translateX) {
165
+ x += element.translateX * scale
166
+ }
167
+ const positionItem: IElementPosition = {
168
+ pageNo,
169
+ index,
170
+ value: element.value,
171
+ rowIndex: startRowIndex + i,
172
+ rowNo: i,
173
+ metrics,
174
+ left: element.left || 0,
175
+ ascent: offsetY,
176
+ lineHeight: curRow.height,
177
+ isFirstLetter: j === 0,
178
+ isLastLetter: j === curRow.elementList.length - 1,
179
+ coordinate: {
180
+ leftTop: [x, y],
181
+ leftBottom: [x, y + curRow.height],
182
+ rightTop: [x + metrics.width, y],
183
+ rightBottom: [x + metrics.width, y + curRow.height]
184
+ }
185
+ }
186
+ // 缓存浮动元素信息
187
+ if (
188
+ element.imgDisplay === ImageDisplay.SURROUND ||
189
+ element.imgDisplay === ImageDisplay.FLOAT_TOP ||
190
+ element.imgDisplay === ImageDisplay.FLOAT_BOTTOM
191
+ ) {
192
+ // 浮动元素使用上一位置信息
193
+ const prePosition = positionList[positionList.length - 1]
194
+ if (prePosition) {
195
+ positionItem.metrics = prePosition.metrics
196
+ positionItem.coordinate = prePosition.coordinate
197
+ }
198
+ // 兼容浮动元素初始坐标为空的情况-默认使用左上坐标
199
+ if (!element.imgFloatPosition) {
200
+ element.imgFloatPosition = {
201
+ x,
202
+ y,
203
+ pageNo
204
+ }
205
+ }
206
+ this.floatPositionList.push({
207
+ pageNo,
208
+ element,
209
+ position: positionItem,
210
+ isTable: payload.isTable,
211
+ index: payload.index,
212
+ tdIndex: payload.tdIndex,
213
+ trIndex: payload.trIndex,
214
+ tdValueIndex: index,
215
+ zone
216
+ })
217
+ }
218
+ positionList.push(positionItem)
219
+ index++
220
+ x += metrics.width
221
+ // 计算表格内元素位置
222
+ if (element.type === ElementType.TABLE && !element.hide) {
223
+ const tdPaddingWidth = tdPadding[1] + tdPadding[3]
224
+ const tdPaddingHeight = tdPadding[0] + tdPadding[2]
225
+ for (let t = 0; t < element.trList!.length; t++) {
226
+ const tr = element.trList![t]
227
+ for (let d = 0; d < tr.tdList!.length; d++) {
228
+ const td = tr.tdList[d]
229
+ td.positionList = []
230
+ const rowList = td.rowList!
231
+ const drawRowResult = this.computePageRowPosition({
232
+ positionList: td.positionList,
233
+ rowList,
234
+ pageNo,
235
+ startRowIndex: 0,
236
+ startIndex: 0,
237
+ startX:
238
+ (td.x! + tdPadding[3]) * scale +
239
+ tablePreX +
240
+ (element.translateX || 0) * scale,
241
+ startY: (td.y! + tdPadding[0]) * scale + tablePreY,
242
+ innerWidth: (td.width! - tdPaddingWidth) * scale,
243
+ isTable: true,
244
+ index: index - 1,
245
+ tdIndex: d,
246
+ trIndex: t,
247
+ zone
248
+ })
249
+ // 垂直对齐方式
250
+ if (
251
+ td.verticalAlign === VerticalAlign.MIDDLE ||
252
+ td.verticalAlign === VerticalAlign.BOTTOM
253
+ ) {
254
+ const rowsHeight = rowList.reduce(
255
+ (pre, cur) => pre + cur.height,
256
+ 0
257
+ )
258
+ const blankHeight =
259
+ (td.height! - tdPaddingHeight) * scale - rowsHeight
260
+ const offsetHeight =
261
+ td.verticalAlign === VerticalAlign.MIDDLE
262
+ ? blankHeight / 2
263
+ : blankHeight
264
+ if (Math.floor(offsetHeight) > 0) {
265
+ td.positionList.forEach(tdPosition => {
266
+ const {
267
+ coordinate: { leftTop, leftBottom, rightBottom, rightTop }
268
+ } = tdPosition
269
+ leftTop[1] += offsetHeight
270
+ leftBottom[1] += offsetHeight
271
+ rightBottom[1] += offsetHeight
272
+ rightTop[1] += offsetHeight
273
+ })
274
+ }
275
+ }
276
+ x = drawRowResult.x
277
+ y = drawRowResult.y
278
+ }
279
+ }
280
+ // 恢复初始x、y
281
+ x = tablePreX
282
+ y = tablePreY
283
+ }
284
+ }
285
+ x = startX
286
+ y += curRow.height
287
+ }
288
+ return { x, y, index }
289
+ }
290
+
291
+ public computePositionList() {
292
+ // 置空原位置信息
293
+ this.positionList = []
294
+ // 按每页行计算
295
+ const innerWidth = this.draw.getInnerWidth()
296
+ const pageRowList = this.draw.getPageRowList()
297
+ const margins = this.draw.getMargins()
298
+ const startX = margins[3]
299
+ // 起始位置受页眉影响
300
+ const header = this.draw.getHeader()
301
+ const extraHeight = header.getExtraHeight()
302
+ const startY = margins[0] + extraHeight
303
+ let startRowIndex = 0
304
+ for (let i = 0; i < pageRowList.length; i++) {
305
+ const rowList = pageRowList[i]
306
+ if (!rowList?.length) continue
307
+ const startIndex = rowList[0].startIndex
308
+ this.computePageRowPosition({
309
+ positionList: this.positionList,
310
+ rowList,
311
+ pageNo: i,
312
+ startRowIndex,
313
+ startIndex,
314
+ startX,
315
+ startY,
316
+ innerWidth
317
+ })
318
+ startRowIndex += rowList.length
319
+ }
320
+ }
321
+
322
+ public computeRowPosition(
323
+ payload: IComputeRowPositionPayload
324
+ ): IElementPosition[] {
325
+ const { row, innerWidth } = payload
326
+ const positionList: IElementPosition[] = []
327
+ this.computePageRowPosition({
328
+ positionList,
329
+ innerWidth,
330
+ rowList: [deepClone(row)],
331
+ pageNo: 0,
332
+ startX: 0,
333
+ startY: 0,
334
+ startIndex: 0,
335
+ startRowIndex: 0
336
+ })
337
+ return positionList
338
+ }
339
+
340
+ public setCursorPosition(position: IElementPosition | null) {
341
+ this.cursorPosition = position
342
+ }
343
+
344
+ public getCursorPosition(): IElementPosition | null {
345
+ return this.cursorPosition
346
+ }
347
+
348
+ public getPositionContext(): IPositionContext {
349
+ return this.positionContext
350
+ }
351
+
352
+ public setPositionContext(payload: IPositionContext) {
353
+ this.eventBus.emit('positionContextChange', {
354
+ value: payload,
355
+ oldValue: this.positionContext
356
+ })
357
+ this.positionContext = payload
358
+ }
359
+
360
+ public getPositionByXY(payload: IGetPositionByXYPayload): ICurrentPosition {
361
+ const { x, y, isTable } = payload
362
+ let { elementList, positionList } = payload
363
+ if (!elementList) {
364
+ elementList = this.draw.getOriginalElementList()
365
+ }
366
+ if (!positionList) {
367
+ positionList = this.getOriginalPositionList()
368
+ }
369
+ const zoneManager = this.draw.getZone()
370
+ const curPageNo = payload.pageNo ?? this.draw.getPageNo()
371
+ const isMainActive = zoneManager.isMainActive()
372
+ const positionNo = isMainActive ? curPageNo : 0
373
+ // 验证浮于文字上方元素
374
+ if (!isTable) {
375
+ const floatTopPosition = this.getFloatPositionByXY({
376
+ ...payload,
377
+ imgDisplays: [ImageDisplay.FLOAT_TOP, ImageDisplay.SURROUND]
378
+ })
379
+ if (floatTopPosition) return floatTopPosition
380
+ }
381
+ // 普通元素
382
+ for (let j = 0; j < positionList.length; j++) {
383
+ const {
384
+ index,
385
+ pageNo,
386
+ left,
387
+ isFirstLetter,
388
+ coordinate: { leftTop, rightTop, leftBottom }
389
+ } = positionList[j]
390
+ if (positionNo !== pageNo) continue
391
+ if (pageNo > positionNo) break
392
+ // 命中元素
393
+ if (
394
+ leftTop[0] - left <= x &&
395
+ rightTop[0] >= x &&
396
+ leftTop[1] <= y &&
397
+ leftBottom[1] >= y
398
+ ) {
399
+ let curPositionIndex = j
400
+ const element = elementList[j]
401
+ // 表格被命中
402
+ if (element.type === ElementType.TABLE) {
403
+ for (let t = 0; t < element.trList!.length; t++) {
404
+ const tr = element.trList![t]
405
+ for (let d = 0; d < tr.tdList.length; d++) {
406
+ const td = tr.tdList[d]
407
+ const tablePosition = this.getPositionByXY({
408
+ x,
409
+ y,
410
+ td,
411
+ pageNo: curPageNo,
412
+ tablePosition: positionList[j],
413
+ isTable: true,
414
+ elementList: td.value,
415
+ positionList: td.positionList
416
+ })
417
+ if (~tablePosition.index) {
418
+ const { index: tdValueIndex, hitLineStartIndex } = tablePosition
419
+ const tdValueElement = td.value[tdValueIndex]
420
+ return {
421
+ index,
422
+ isCheckbox:
423
+ tablePosition.isCheckbox ||
424
+ tdValueElement.type === ElementType.CHECKBOX ||
425
+ tdValueElement.controlComponent ===
426
+ ControlComponent.CHECKBOX,
427
+ isRadio:
428
+ tdValueElement.type === ElementType.RADIO ||
429
+ tdValueElement.controlComponent === ControlComponent.RADIO,
430
+ isControl: !!tdValueElement.controlId,
431
+ isImage: tablePosition.isImage,
432
+ isDirectHit: tablePosition.isDirectHit,
433
+ isTable: true,
434
+ tdIndex: d,
435
+ trIndex: t,
436
+ tdValueIndex,
437
+ tdId: td.id,
438
+ trId: tr.id,
439
+ tableId: element.id,
440
+ hitLineStartIndex
441
+ }
442
+ }
443
+ }
444
+ }
445
+ }
446
+ // 图片区域均为命中
447
+ if (
448
+ element.type === ElementType.IMAGE ||
449
+ element.type === ElementType.LATEX
450
+ ) {
451
+ return {
452
+ index: curPositionIndex,
453
+ isDirectHit: true,
454
+ isImage: true
455
+ }
456
+ }
457
+ if (
458
+ element.type === ElementType.CHECKBOX ||
459
+ element.controlComponent === ControlComponent.CHECKBOX
460
+ ) {
461
+ return {
462
+ index: curPositionIndex,
463
+ isDirectHit: true,
464
+ isCheckbox: true
465
+ }
466
+ }
467
+ // 标签元素检测
468
+ if (element.type === ElementType.LABEL) {
469
+ return {
470
+ index: curPositionIndex,
471
+ isDirectHit: true,
472
+ isLabel: true
473
+ }
474
+ }
475
+ if (
476
+ element.type === ElementType.TAB &&
477
+ element.listStyle === ListStyle.CHECKBOX
478
+ ) {
479
+ // 向前找checkbox元素
480
+ let index = curPositionIndex - 1
481
+ while (index > 0) {
482
+ const element = elementList[index]
483
+ if (
484
+ element.value === ZERO &&
485
+ element.listStyle === ListStyle.CHECKBOX
486
+ ) {
487
+ break
488
+ }
489
+ index--
490
+ }
491
+ return {
492
+ index,
493
+ isDirectHit: true,
494
+ isCheckbox: true
495
+ }
496
+ }
497
+ if (
498
+ element.type === ElementType.RADIO ||
499
+ element.controlComponent === ControlComponent.RADIO
500
+ ) {
501
+ return {
502
+ index: curPositionIndex,
503
+ isDirectHit: true,
504
+ isRadio: true
505
+ }
506
+ }
507
+ let hitLineStartIndex: number | undefined
508
+ // 判断是否在文字中间前后
509
+ if (elementList[index].value !== ZERO) {
510
+ const valueWidth = rightTop[0] - leftTop[0]
511
+ if (x < leftTop[0] + valueWidth / 2) {
512
+ curPositionIndex = j - 1
513
+ if (isFirstLetter) {
514
+ hitLineStartIndex = j
515
+ }
516
+ }
517
+ }
518
+ return {
519
+ isDirectHit: true,
520
+ hitLineStartIndex,
521
+ index: curPositionIndex,
522
+ isControl: !!element.controlId
523
+ }
524
+ }
525
+ }
526
+ // 验证衬于文字下方元素
527
+ if (!isTable) {
528
+ const floatBottomPosition = this.getFloatPositionByXY({
529
+ ...payload,
530
+ imgDisplays: [ImageDisplay.FLOAT_BOTTOM]
531
+ })
532
+ if (floatBottomPosition) return floatBottomPosition
533
+ }
534
+ // 非命中区域
535
+ let isLastArea = false
536
+ let curPositionIndex = -1
537
+ let hitLineStartIndex: number | undefined
538
+ // 判断是否在表格内
539
+ if (isTable) {
540
+ const { scale } = this.options
541
+ const { td, tablePosition } = payload
542
+ if (td && tablePosition) {
543
+ const { leftTop } = tablePosition.coordinate
544
+ const tdX = td.x! * scale + leftTop[0]
545
+ const tdY = td.y! * scale + leftTop[1]
546
+ const tdWidth = td.width! * scale
547
+ const tdHeight = td.height! * scale
548
+ if (!(tdX < x && x < tdX + tdWidth && tdY < y && y < tdY + tdHeight)) {
549
+ return {
550
+ index: curPositionIndex
551
+ }
552
+ }
553
+ }
554
+ }
555
+ // 判断所属行是否存在元素
556
+ const lastLetterList = positionList.filter(
557
+ p => p.isLastLetter && p.pageNo === positionNo
558
+ )
559
+ for (let j = 0; j < lastLetterList.length; j++) {
560
+ const {
561
+ index,
562
+ rowNo,
563
+ coordinate: { leftTop, leftBottom }
564
+ } = lastLetterList[j]
565
+ if (y > leftTop[1] && y <= leftBottom[1]) {
566
+ const headIndex = positionList.findIndex(
567
+ p => p.pageNo === positionNo && p.rowNo === rowNo
568
+ )
569
+ const headElement = elementList[headIndex]
570
+ const headPosition = positionList[headIndex]
571
+ // 是否在头部
572
+ const headStartX =
573
+ headElement.listStyle === ListStyle.CHECKBOX
574
+ ? this.draw.getMargins()[3]
575
+ : headPosition.coordinate.leftTop[0]
576
+ if (x < headStartX) {
577
+ // 头部元素为空元素时无需选中
578
+ if (~headIndex) {
579
+ if (headPosition.value === ZERO) {
580
+ curPositionIndex = headIndex
581
+ } else {
582
+ curPositionIndex = headIndex - 1
583
+ hitLineStartIndex = headIndex
584
+ }
585
+ } else {
586
+ curPositionIndex = index
587
+ }
588
+ } else {
589
+ // 是否是复选框列表
590
+ if (headElement.listStyle === ListStyle.CHECKBOX && x < leftTop[0]) {
591
+ return {
592
+ index: headIndex,
593
+ isDirectHit: true,
594
+ isCheckbox: true
595
+ }
596
+ }
597
+ curPositionIndex = index
598
+ }
599
+ isLastArea = true
600
+ break
601
+ }
602
+ }
603
+ if (!isLastArea) {
604
+ // 页眉页脚正文切换
605
+ if (this.draw.getIsPagingMode()) {
606
+ // 页眉底部距离页面顶部距离
607
+ const header = this.draw.getHeader()
608
+ const headerHeight = header.getHeight()
609
+ const headerBottomY = header.getHeaderTop() + headerHeight
610
+ // 页脚上部距离页面顶部距离
611
+ const footer = this.draw.getFooter()
612
+ const pageHeight = this.draw.getHeight()
613
+ const footerTopY =
614
+ pageHeight - (footer.getFooterBottom() + footer.getHeight())
615
+ // 判断所属位置是否属于页眉页脚区域
616
+ if (isMainActive) {
617
+ // 页眉:当前位置小于页眉底部位置
618
+ if (y < headerBottomY) {
619
+ return {
620
+ index: -1,
621
+ zone: EditorZone.HEADER
622
+ }
623
+ }
624
+ // 页脚:当前位置大于页脚顶部位置
625
+ if (y > footerTopY) {
626
+ return {
627
+ index: -1,
628
+ zone: EditorZone.FOOTER
629
+ }
630
+ }
631
+ } else {
632
+ // main区域:当前位置小于页眉底部位置 && 大于页脚顶部位置
633
+ if (y <= footerTopY && y >= headerBottomY) {
634
+ return {
635
+ index: -1,
636
+ zone: EditorZone.MAIN
637
+ }
638
+ }
639
+ }
640
+ }
641
+ // 正文上-循环首行
642
+ const margins = this.draw.getMargins()
643
+ if (y <= margins[0]) {
644
+ for (let p = 0; p < positionList.length; p++) {
645
+ const position = positionList[p]
646
+ if (position.pageNo !== positionNo || position.rowNo !== 0) continue
647
+ const { leftTop, rightTop } = position.coordinate
648
+ // 小于左页边距 || 命中文字 || 首行最后元素
649
+ if (
650
+ x <= margins[3] ||
651
+ (x >= leftTop[0] && x <= rightTop[0]) ||
652
+ positionList[p + 1]?.rowNo !== 0
653
+ ) {
654
+ return {
655
+ index: position.index
656
+ }
657
+ }
658
+ }
659
+ } else {
660
+ // 正文下-循环尾行
661
+ const lastLetter = lastLetterList[lastLetterList.length - 1]
662
+ if (lastLetter) {
663
+ const lastRowNo = lastLetter.rowNo
664
+ for (let p = 0; p < positionList.length; p++) {
665
+ const position = positionList[p]
666
+ if (
667
+ position.pageNo !== positionNo ||
668
+ position.rowNo !== lastRowNo
669
+ ) {
670
+ continue
671
+ }
672
+ const { leftTop, rightTop } = position.coordinate
673
+ // 小于左页边距 || 命中文字 || 尾行最后元素
674
+ if (
675
+ x <= margins[3] ||
676
+ (x >= leftTop[0] && x <= rightTop[0]) ||
677
+ positionList[p + 1]?.rowNo !== lastRowNo
678
+ ) {
679
+ return {
680
+ index: position.index
681
+ }
682
+ }
683
+ }
684
+ }
685
+ }
686
+ // 当前页最后一行
687
+ return {
688
+ index:
689
+ lastLetterList[lastLetterList.length - 1]?.index ||
690
+ positionList.length - 1
691
+ }
692
+ }
693
+ return {
694
+ hitLineStartIndex,
695
+ index: curPositionIndex,
696
+ isControl: !!elementList[curPositionIndex]?.controlId
697
+ }
698
+ }
699
+
700
+ public getFloatPositionByXY(
701
+ payload: IGetFloatPositionByXYPayload
702
+ ): ICurrentPosition | void {
703
+ const { x, y } = payload
704
+ const currentPageNo = payload.pageNo ?? this.draw.getPageNo()
705
+ const currentZone = this.draw.getZone().getZone()
706
+ const { scale } = this.options
707
+ for (let f = 0; f < this.floatPositionList.length; f++) {
708
+ const {
709
+ position,
710
+ element,
711
+ isTable,
712
+ index,
713
+ trIndex,
714
+ tdIndex,
715
+ tdValueIndex,
716
+ zone: floatElementZone,
717
+ pageNo
718
+ } = this.floatPositionList[f]
719
+ if (
720
+ currentPageNo === pageNo &&
721
+ element.type === ElementType.IMAGE &&
722
+ element.imgDisplay &&
723
+ payload.imgDisplays.includes(element.imgDisplay) &&
724
+ (!floatElementZone || floatElementZone === currentZone)
725
+ ) {
726
+ const imgFloatPosition = element.imgFloatPosition!
727
+ const imgFloatPositionX = imgFloatPosition.x * scale
728
+ const imgFloatPositionY = imgFloatPosition.y * scale
729
+ const elementWidth = element.width! * scale
730
+ const elementHeight = element.height! * scale
731
+ if (
732
+ x >= imgFloatPositionX &&
733
+ x <= imgFloatPositionX + elementWidth &&
734
+ y >= imgFloatPositionY &&
735
+ y <= imgFloatPositionY + elementHeight
736
+ ) {
737
+ if (isTable) {
738
+ return {
739
+ index: index!,
740
+ isDirectHit: true,
741
+ isImage: true,
742
+ isTable,
743
+ trIndex,
744
+ tdIndex,
745
+ tdValueIndex,
746
+ tdId: element.tdId,
747
+ trId: element.trId,
748
+ tableId: element.tableId
749
+ }
750
+ }
751
+ return {
752
+ index: position.index,
753
+ isDirectHit: true,
754
+ isImage: true
755
+ }
756
+ }
757
+ }
758
+ }
759
+ }
760
+
761
+ public adjustPositionContext(
762
+ payload: IGetPositionByXYPayload
763
+ ): ICurrentPosition | null {
764
+ const positionResult = this.getPositionByXY(payload)
765
+ if (!~positionResult.index) return null
766
+ // 移动控件内光标
767
+ if (
768
+ positionResult.isControl &&
769
+ this.draw.getMode() !== EditorMode.READONLY
770
+ ) {
771
+ const { index, isTable, trIndex, tdIndex, tdValueIndex } = positionResult
772
+ const control = this.draw.getControl()
773
+ const { newIndex } = control.moveCursor({
774
+ index,
775
+ isTable,
776
+ trIndex,
777
+ tdIndex,
778
+ tdValueIndex
779
+ })
780
+ if (isTable) {
781
+ positionResult.tdValueIndex = newIndex
782
+ } else {
783
+ positionResult.index = newIndex
784
+ }
785
+ }
786
+ const {
787
+ index,
788
+ isCheckbox,
789
+ isRadio,
790
+ isControl,
791
+ isImage,
792
+ isLabel,
793
+ isDirectHit,
794
+ isTable,
795
+ trIndex,
796
+ tdIndex,
797
+ tdId,
798
+ trId,
799
+ tableId
800
+ } = positionResult
801
+ // 设置位置上下文
802
+ this.setPositionContext({
803
+ isTable: isTable || false,
804
+ isCheckbox: isCheckbox || false,
805
+ isRadio: isRadio || false,
806
+ isControl: isControl || false,
807
+ isImage: isImage || false,
808
+ isLabel: isLabel || false,
809
+ isDirectHit: isDirectHit || false,
810
+ index,
811
+ trIndex,
812
+ tdIndex,
813
+ tdId,
814
+ trId,
815
+ tableId
816
+ })
817
+ return positionResult
818
+ }
819
+
820
+ public setSurroundPosition(payload: ISetSurroundPositionPayload) {
821
+ const { scale } = this.options
822
+ const {
823
+ pageNo,
824
+ row,
825
+ rowElement,
826
+ rowElementRect,
827
+ surroundElementList,
828
+ availableWidth
829
+ } = payload
830
+ let x = rowElementRect.x
831
+ let rowIncreaseWidth = 0
832
+ if (
833
+ surroundElementList.length &&
834
+ !getIsBlockElement(rowElement) &&
835
+ !rowElement.control?.minWidth
836
+ ) {
837
+ for (let s = 0; s < surroundElementList.length; s++) {
838
+ const surroundElement = surroundElementList[s]
839
+ const floatPosition = surroundElement.imgFloatPosition!
840
+ if (floatPosition.pageNo !== pageNo) continue
841
+ const surroundRect = {
842
+ ...floatPosition,
843
+ x: floatPosition.x * scale,
844
+ y: floatPosition.y * scale,
845
+ width: surroundElement.width! * scale,
846
+ height: surroundElement.height! * scale
847
+ }
848
+ if (isRectIntersect(rowElementRect, surroundRect)) {
849
+ row.isSurround = true
850
+ // 需向左移动距离:浮动元素宽度 + 浮动元素左上坐标 - 元素左上坐标
851
+ const translateX =
852
+ surroundRect.width + surroundRect.x - rowElementRect.x
853
+ rowElement.left = translateX
854
+ // 增加行宽
855
+ row.width += translateX
856
+ rowIncreaseWidth += translateX
857
+ // 下个元素起始位置:浮动元素右坐标 - 元素宽度
858
+ x = surroundRect.x + surroundRect.width
859
+ // 检测宽度是否足够,不够则移动到下一行,并还原状态
860
+ if (row.width + rowElement.metrics.width > availableWidth) {
861
+ rowElement.left = 0
862
+ row.width -= rowIncreaseWidth
863
+ break
864
+ }
865
+ }
866
+ }
867
+ }
868
+ return { x, rowIncreaseWidth }
869
+ }
870
+ }