dishui 0.0.106 → 0.0.110

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 (388) hide show
  1. package/dist/.release-verified.json +3 -2
  2. package/dist/components/Accordion/index.js.map +1 -1
  3. package/dist/components/Avatar/index.js.map +1 -1
  4. package/dist/components/Badge/index.js.map +1 -1
  5. package/dist/components/Button/index.js.map +1 -1
  6. package/dist/components/ButtonMenu/index.js.map +1 -1
  7. package/dist/components/Card/Metric2.js.map +1 -1
  8. package/dist/components/Card/Ticket2.js.map +1 -1
  9. package/dist/components/Card/index.js.map +1 -1
  10. package/dist/components/Chart/Chart.js.map +1 -1
  11. package/dist/components/Checkbox/index.js.map +1 -1
  12. package/dist/components/ChoicePicker/index.js.map +1 -1
  13. package/dist/components/Column/index.js.map +1 -1
  14. package/dist/components/ConfirmDialog/index.js.map +1 -1
  15. package/dist/components/DateTimeInput/index.js.map +1 -1
  16. package/dist/components/Demo/index.js.map +1 -1
  17. package/dist/components/Demo/source.js.map +1 -1
  18. package/dist/components/Divider/index.js.map +1 -1
  19. package/dist/components/EmptyState/index.js.map +1 -1
  20. package/dist/components/Field/index.js.map +1 -1
  21. package/dist/components/FileUploader/DropZone.js.map +1 -1
  22. package/dist/components/FileUploader/FileItem.js.map +1 -1
  23. package/dist/components/FileUploader/FileUploader.js.map +1 -1
  24. package/dist/components/FileUploader/UploadQueue.js.map +1 -1
  25. package/dist/components/GroupButton/index.js.map +1 -1
  26. package/dist/components/GroupedTable/index.js.map +1 -1
  27. package/dist/components/Icon/index.js.map +1 -1
  28. package/dist/components/Image/index.js.map +1 -1
  29. package/dist/components/Input/index.js.map +1 -1
  30. package/dist/components/Label/index.js.map +1 -1
  31. package/dist/components/Layout/index.js.map +1 -1
  32. package/dist/components/LayoutSuite/DashboardSuite.js.map +1 -1
  33. package/dist/components/LayoutSuite/index.js.map +1 -1
  34. package/dist/components/List/index.js.map +1 -1
  35. package/dist/components/Markdown/Markdown.js.map +1 -1
  36. package/dist/components/Markdown/codeThemes.js.map +1 -1
  37. package/dist/components/Markdown/markdownComponents.js.map +1 -1
  38. package/dist/components/Markdown/parseCodeBlockMeta.js.map +1 -1
  39. package/dist/components/Markdown/useMarkdownSource.js.map +1 -1
  40. package/dist/components/Markdown/useMarkmapRenderer.js.map +1 -1
  41. package/dist/components/Markdown/useMermaidRenderer.js.map +1 -1
  42. package/dist/components/Modal/focusScope.js.map +1 -1
  43. package/dist/components/Modal/index.js.map +1 -1
  44. package/dist/components/MultipleChoice/index.js.map +1 -1
  45. package/dist/components/NavigationList/index.js.map +1 -1
  46. package/dist/components/Page/Float2.js.map +1 -1
  47. package/dist/components/Page/index.js.map +1 -1
  48. package/dist/components/Page/resize2.js.map +1 -1
  49. package/dist/components/PageHeader/index.js.map +1 -1
  50. package/dist/components/PagePanel/index.js.map +1 -1
  51. package/dist/components/ProtectedRoute/index.js.map +1 -1
  52. package/dist/components/Resizable/ResizeGrip.js.map +1 -1
  53. package/dist/components/Resizable/index.js.map +1 -1
  54. package/dist/components/Resizable/useResize.js.map +1 -1
  55. package/dist/components/Row/index.js.map +1 -1
  56. package/dist/components/Section/index.js.map +1 -1
  57. package/dist/components/Select/index.js.map +1 -1
  58. package/dist/components/SidebarToggleButton/index.js.map +1 -1
  59. package/dist/components/Skeleton/index.js.map +1 -1
  60. package/dist/components/Slider/index.js.map +1 -1
  61. package/dist/components/Switch/index.js.map +1 -1
  62. package/dist/components/Tab/index.js.map +1 -1
  63. package/dist/components/Table/index.js.map +1 -1
  64. package/dist/components/Tabs/index.js.map +1 -1
  65. package/dist/components/Tabs/tabNavigation.js.map +1 -1
  66. package/dist/components/Text/index.js.map +1 -1
  67. package/dist/components/Textarea/index.js.map +1 -1
  68. package/dist/components/Tooltip/index.js.map +1 -1
  69. package/dist/components/Tree/Tree.js.map +1 -1
  70. package/dist/components/ai/AgentChat/index.js.map +1 -1
  71. package/dist/components/ai/AgentRunCard/index.js.map +1 -1
  72. package/dist/components/ai/AgentScreen/index.js.map +1 -1
  73. package/dist/components/ai/ApprovalCard/index.js.map +1 -1
  74. package/dist/components/ai/CodeView/index.js.map +1 -1
  75. package/dist/components/ai/CommandSearch/index.js.map +1 -1
  76. package/dist/components/ai/ContextCards/index.js.map +1 -1
  77. package/dist/components/ai/DiffTable/index.js.map +1 -1
  78. package/dist/components/ai/FilterTable/index.js.map +1 -1
  79. package/dist/components/ai/FineTuneCard/index.js.map +1 -1
  80. package/dist/components/ai/InsightCards/index.js.map +1 -1
  81. package/dist/components/ai/IssueCard/index.js.map +1 -1
  82. package/dist/components/ai/LoadingState/index.js.map +1 -1
  83. package/dist/components/ai/PromptBar/index.js.map +1 -1
  84. package/dist/components/ai/RecommendationCard/index.js.map +1 -1
  85. package/dist/components/ai/RecordsTable/index.js.map +1 -1
  86. package/dist/components/ai/SelectionActions/index.js.map +1 -1
  87. package/dist/components/ai/StateFlow/index.js.map +1 -1
  88. package/dist/components/ai/StreamingText/index.js.map +1 -1
  89. package/dist/components/ai/TaskRows/index.js.map +1 -1
  90. package/dist/components/ai/Thinking/index.js.map +1 -1
  91. package/dist/components/ai/ToolChips/index.js.map +1 -1
  92. package/dist/components/ai/shared.js.map +1 -1
  93. package/dist/components/pro/ArticleContextMenu/index.js.map +1 -1
  94. package/dist/components/pro/ArticleControl/ArticleControl2.js.map +1 -1
  95. package/dist/components/pro/ArticleControl/buildHeadingTree.js.map +1 -1
  96. package/dist/components/pro/ArticleControl/useArticleToc.js.map +1 -1
  97. package/dist/components/pro/Calendar/Calendar.js +165 -160
  98. package/dist/components/pro/Calendar/Calendar.js.map +1 -1
  99. package/dist/components/pro/Calendar/hooks/useCalendarDrag.js.map +1 -1
  100. package/dist/components/pro/Calendar/hooks/useCalendarState.js +31 -31
  101. package/dist/components/pro/Calendar/hooks/useCalendarState.js.map +1 -1
  102. package/dist/components/pro/Calendar/utils.js.map +1 -1
  103. package/dist/components/pro/CodeEditor/editors/CodeEditor.js.map +1 -1
  104. package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
  105. package/dist/components/pro/CodeEditor/editors/markdownExtensions.js.map +1 -1
  106. package/dist/components/pro/CodeEditor/extensions/contextMenu.js.map +1 -1
  107. package/dist/components/pro/CodeEditor/extensions/index.js.map +1 -1
  108. package/dist/components/pro/CodeEditor/langs/index.js.map +1 -1
  109. package/dist/components/pro/CodeEditor/langs/javascript.js.map +1 -1
  110. package/dist/components/pro/CodeEditor/langs/python.js.map +1 -1
  111. package/dist/components/pro/CodeEditor/langs/snippets.js.map +1 -1
  112. package/dist/components/pro/CodeEditor/panels/FootnotePanel.js.map +1 -1
  113. package/dist/components/pro/CodeEditor/panels/HistoryPanel.js +65 -59
  114. package/dist/components/pro/CodeEditor/panels/HistoryPanel.js.map +1 -1
  115. package/dist/components/pro/CodeEditor/panels/OutlinePanel.js.map +1 -1
  116. package/dist/components/pro/CodeEditor/panels/TableOfContentsPanel.js.map +1 -1
  117. package/dist/components/pro/CodeEditor/panels/VariablePanel.js.map +1 -1
  118. package/dist/components/pro/CodeEditor/themes.js.map +1 -1
  119. package/dist/components/pro/CodeEditor/utils.js.map +1 -1
  120. package/dist/components/pro/DataTable/DataTable.js.map +1 -1
  121. package/dist/components/pro/DataTable/Filters.js.map +1 -1
  122. package/dist/components/pro/DataTable/PivotPanel.js.map +1 -1
  123. package/dist/components/pro/DataTable/PivotView.js.map +1 -1
  124. package/dist/components/pro/DataTable/components/BulkActions.js.map +1 -1
  125. package/dist/components/pro/DataTable/components/ColumnSelector.js.map +1 -1
  126. package/dist/components/pro/DataTable/components/FilterBar.js.map +1 -1
  127. package/dist/components/pro/DataTable/components/TableBody.js.map +1 -1
  128. package/dist/components/pro/DataTable/components/TableHeader.js.map +1 -1
  129. package/dist/components/pro/DataTable/components/TablePagination.js.map +1 -1
  130. package/dist/components/pro/DataTable/components/TableToolbar.js.map +1 -1
  131. package/dist/components/pro/DataTable/extension.js.map +1 -1
  132. package/dist/components/pro/DataTable/pivotEngine.js.map +1 -1
  133. package/dist/components/pro/DataTable/pivotExtension.js.map +1 -1
  134. package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
  135. package/dist/components/pro/DataTable/tanstack-table.js.map +1 -1
  136. package/dist/components/pro/DataTable/treeDataUtils.js.map +1 -1
  137. package/dist/components/pro/DataTable/useColumnDragReorder.js.map +1 -1
  138. package/dist/components/pro/DataTable/useDataTableModel.js +119 -104
  139. package/dist/components/pro/DataTable/useDataTableModel.js.map +1 -1
  140. package/dist/components/pro/DataTable/utils.js.map +1 -1
  141. package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
  142. package/dist/components/pro/FileExplorer/CreateDialog.js.map +1 -1
  143. package/dist/components/pro/FileExplorer/FileExplorer.js.map +1 -1
  144. package/dist/components/pro/FileExplorer/FileIcon.js.map +1 -1
  145. package/dist/components/pro/FileExplorer/GridView.js.map +1 -1
  146. package/dist/components/pro/FileExplorer/ListView.js.map +1 -1
  147. package/dist/components/pro/FileExplorer/Toolbar.js.map +1 -1
  148. package/dist/components/pro/Flow/Flow.js.map +1 -1
  149. package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
  150. package/dist/components/pro/Flow/archify/build.js.map +1 -1
  151. package/dist/components/pro/Flow/archify/convert.js.map +1 -1
  152. package/dist/components/pro/Flow/archify/palette.js.map +1 -1
  153. package/dist/components/pro/Flow/archify/presets.js.map +1 -1
  154. package/dist/components/pro/Flow/archify/spec.js.map +1 -1
  155. package/dist/components/pro/Flow/canvas/AlignmentGuides.js.map +1 -1
  156. package/dist/components/pro/Flow/canvas/GridRenderer.js.map +1 -1
  157. package/dist/components/pro/Flow/canvas/MiniMapRenderer.js.map +1 -1
  158. package/dist/components/pro/Flow/canvas/PixiApp.js.map +1 -1
  159. package/dist/components/pro/Flow/canvas/SelectionOverlay.js.map +1 -1
  160. package/dist/components/pro/Flow/canvas/ViewportContainer.js.map +1 -1
  161. package/dist/components/pro/Flow/constants.js.map +1 -1
  162. package/dist/components/pro/Flow/context/FlowAIContext.js.map +1 -1
  163. package/dist/components/pro/Flow/context/FlowContext.js.map +1 -1
  164. package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
  165. package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
  166. package/dist/components/pro/Flow/edges/edgeMarkers.js.map +1 -1
  167. package/dist/components/pro/Flow/edges/edgePaths.js.map +1 -1
  168. package/dist/components/pro/Flow/hooks/useAlignmentGuides.js.map +1 -1
  169. package/dist/components/pro/Flow/hooks/useClipboard.js.map +1 -1
  170. package/dist/components/pro/Flow/hooks/useCompactMode.js.map +1 -1
  171. package/dist/components/pro/Flow/hooks/useDeleteSelection.js.map +1 -1
  172. package/dist/components/pro/Flow/hooks/useDraggablePanel.js.map +1 -1
  173. package/dist/components/pro/Flow/hooks/useEdgeMutations.js.map +1 -1
  174. package/dist/components/pro/Flow/hooks/useFlowImportExport.js.map +1 -1
  175. package/dist/components/pro/Flow/hooks/useKeyboardShortcuts.js.map +1 -1
  176. package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
  177. package/dist/components/pro/Flow/hooks/useLineMutations.js.map +1 -1
  178. package/dist/components/pro/Flow/hooks/useMindMap.js.map +1 -1
  179. package/dist/components/pro/Flow/hooks/useNodeMutations.js.map +1 -1
  180. package/dist/components/pro/Flow/hooks/usePdfExport.js.map +1 -1
  181. package/dist/components/pro/Flow/hooks/usePixiApp.js.map +1 -1
  182. package/dist/components/pro/Flow/hooks/useResizablePanel.js.map +1 -1
  183. package/dist/components/pro/Flow/hooks/useSelection.js.map +1 -1
  184. package/dist/components/pro/Flow/hooks/useUndoRedo.js.map +1 -1
  185. package/dist/components/pro/Flow/hooks/useViewport.js.map +1 -1
  186. package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
  187. package/dist/components/pro/Flow/lines/GeometricLineTool.js.map +1 -1
  188. package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
  189. package/dist/components/pro/Flow/lines/lineSmoothing.js.map +1 -1
  190. package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
  191. package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
  192. package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
  193. package/dist/components/pro/Flow/nodes/Model3DView.js.map +1 -1
  194. package/dist/components/pro/Flow/nodes/NodeHandles.js.map +1 -1
  195. package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
  196. package/dist/components/pro/Flow/nodes/NodeText.js.map +1 -1
  197. package/dist/components/pro/Flow/nodes/aiClient.js.map +1 -1
  198. package/dist/components/pro/Flow/nodes/animAnchors.js.map +1 -1
  199. package/dist/components/pro/Flow/nodes/chartGeometryBudget.js.map +1 -1
  200. package/dist/components/pro/Flow/nodes/dataUtils.js.map +1 -1
  201. package/dist/components/pro/Flow/nodes/demandRender.js.map +1 -1
  202. package/dist/components/pro/Flow/nodes/nodeUtils.js.map +1 -1
  203. package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
  204. package/dist/components/pro/Flow/nodes/svgIconTexture.js.map +1 -1
  205. package/dist/components/pro/Flow/nodes/svgIcons.js.map +1 -1
  206. package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -1
  207. package/dist/components/pro/Flow/panels/Breadcrumb.js.map +1 -1
  208. package/dist/components/pro/Flow/panels/ContextMenu.js.map +1 -1
  209. package/dist/components/pro/Flow/panels/DataInspectorSection.js.map +1 -1
  210. package/dist/components/pro/Flow/panels/ExpandableTextarea.js.map +1 -1
  211. package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
  212. package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
  213. package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
  214. package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
  215. package/dist/components/pro/Flow/panels/PresentationMode.js.map +1 -1
  216. package/dist/components/pro/Flow/panels/ProjectTitle.js.map +1 -1
  217. package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
  218. package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
  219. package/dist/components/pro/Flow/types.js.map +1 -1
  220. package/dist/components/pro/Flow/utils/dashedLine.js.map +1 -1
  221. package/dist/components/pro/Flow/utils/gradient.js.map +1 -1
  222. package/dist/components/pro/Flow/utils/pdfExport.js.map +1 -1
  223. package/dist/components/pro/Flow/utils/themeColor.js.map +1 -1
  224. package/dist/components/pro/Gantt/Gantt.js.map +1 -1
  225. package/dist/components/pro/Gantt/hooks/useGanttDrag.js.map +1 -1
  226. package/dist/components/pro/Gantt/hooks/useGanttState.js +79 -71
  227. package/dist/components/pro/Gantt/hooks/useGanttState.js.map +1 -1
  228. package/dist/components/pro/Gantt/utils.js.map +1 -1
  229. package/dist/components/pro/Kanban/Kanban.js.map +1 -1
  230. package/dist/components/pro/Kanban/Swimlanes.js.map +1 -1
  231. package/dist/components/pro/Kanban/useKanbanDrag.js.map +1 -1
  232. package/dist/components/pro/Kanban/utils.js.map +1 -1
  233. package/dist/components/pro/RichTextEditor/AIRewrite.d.ts +1 -0
  234. package/dist/components/pro/RichTextEditor/AIRewrite.js +109 -88
  235. package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
  236. package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
  237. package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
  238. package/dist/components/pro/RichTextEditor/CommentDialog.js.map +1 -1
  239. package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
  240. package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
  241. package/dist/components/pro/RichTextEditor/ContextMenu.js.map +1 -1
  242. package/dist/components/pro/RichTextEditor/RichTextEditor.js +133 -132
  243. package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
  244. package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
  245. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
  246. package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
  247. package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
  248. package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
  249. package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
  250. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
  251. package/dist/components/pro/RichTextEditor/Toolbar/ToolbarButton.js.map +1 -1
  252. package/dist/components/pro/RichTextEditor/Toolbar/useAnchoredDropdown.js.map +1 -1
  253. package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
  254. package/dist/components/pro/RichTextEditor/extensions/CommentMark.js.map +1 -1
  255. package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
  256. package/dist/components/pro/RichTextEditor/extensions/FontSize.js.map +1 -1
  257. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
  258. package/dist/components/pro/RichTextEditor/extensions/ResizableImage.js.map +1 -1
  259. package/dist/components/pro/RichTextEditor/extensions/legacyMermaid.js.map +1 -1
  260. package/dist/components/pro/RichTextEditor/types.d.ts +2 -0
  261. package/dist/components/pro/RichTextEditor/types.js.map +1 -1
  262. package/dist/components/pro/Sprite/Molly/animations.d.ts +6 -0
  263. package/dist/components/pro/Sprite/Molly/animations.js +52 -0
  264. package/dist/components/pro/Sprite/Molly/animations.js.map +1 -0
  265. package/dist/components/pro/Sprite/Molly/events.d.ts +2 -0
  266. package/dist/components/pro/Sprite/Molly/events.js +46 -0
  267. package/dist/components/pro/Sprite/Molly/events.js.map +1 -0
  268. package/dist/components/pro/Sprite/Molly/index.d.ts +1 -0
  269. package/dist/components/pro/Sprite/Molly/index.js +12 -0
  270. package/dist/components/pro/Sprite/Molly/index.js.map +1 -0
  271. package/dist/components/pro/Sprite/Molly/legFlexion.d.ts +3 -0
  272. package/dist/components/pro/Sprite/Molly/legFlexion.js +48 -0
  273. package/dist/components/pro/Sprite/Molly/legFlexion.js.map +1 -0
  274. package/dist/components/pro/Sprite/Molly/locomotion.d.ts +4 -0
  275. package/dist/components/pro/Sprite/Molly/locomotion.js +51 -0
  276. package/dist/components/pro/Sprite/Molly/locomotion.js.map +1 -0
  277. package/dist/components/pro/Sprite/Molly/model.d.ts +23 -0
  278. package/dist/components/pro/Sprite/Molly/model.js +614 -0
  279. package/dist/components/pro/Sprite/Molly/model.js.map +1 -0
  280. package/dist/components/pro/Sprite/Molly/rig.d.ts +25 -0
  281. package/dist/components/pro/Sprite/Molly/rig.js +102 -0
  282. package/dist/components/pro/Sprite/Molly/rig.js.map +1 -0
  283. package/dist/components/pro/Sprite/Ruby/animations.d.ts +6 -0
  284. package/dist/components/pro/Sprite/Ruby/animations.js +58 -0
  285. package/dist/components/pro/Sprite/Ruby/animations.js.map +1 -0
  286. package/dist/components/pro/Sprite/Ruby/events.d.ts +2 -0
  287. package/dist/components/pro/Sprite/Ruby/events.js +46 -0
  288. package/dist/components/pro/Sprite/Ruby/events.js.map +1 -0
  289. package/dist/components/pro/Sprite/Ruby/index.d.ts +1 -0
  290. package/dist/components/pro/Sprite/Ruby/index.js +12 -0
  291. package/dist/components/pro/Sprite/Ruby/index.js.map +1 -0
  292. package/dist/components/pro/Sprite/Ruby/locomotion.d.ts +4 -0
  293. package/dist/components/pro/Sprite/Ruby/locomotion.js +41 -0
  294. package/dist/components/pro/Sprite/Ruby/locomotion.js.map +1 -0
  295. package/dist/components/pro/Sprite/Ruby/model.d.ts +23 -0
  296. package/dist/components/pro/Sprite/Ruby/model.js +605 -0
  297. package/dist/components/pro/Sprite/Ruby/model.js.map +1 -0
  298. package/dist/components/pro/Sprite/Ruby/rig.d.ts +26 -0
  299. package/dist/components/pro/Sprite/Ruby/rig.js +112 -0
  300. package/dist/components/pro/Sprite/Ruby/rig.js.map +1 -0
  301. package/dist/components/pro/Sprite/Sprite.d.ts +23 -0
  302. package/dist/components/pro/Sprite/Sprite2.js +224 -0
  303. package/dist/components/pro/Sprite/Sprite2.js.map +1 -0
  304. package/dist/components/pro/Sprite/actions.d.ts +3 -0
  305. package/dist/components/pro/Sprite/actions.js +16 -0
  306. package/dist/components/pro/Sprite/actions.js.map +1 -0
  307. package/dist/components/pro/Sprite/createSpriteScene.d.ts +4 -0
  308. package/dist/components/pro/Sprite/createSpriteScene.js +14 -0
  309. package/dist/components/pro/Sprite/createSpriteScene.js.map +1 -0
  310. package/dist/components/pro/Sprite/index.d.ts +4 -0
  311. package/dist/components/pro/Sprite/shared/animation.d.ts +33 -0
  312. package/dist/components/pro/Sprite/shared/animation.js +39 -0
  313. package/dist/components/pro/Sprite/shared/animation.js.map +1 -0
  314. package/dist/components/pro/Sprite/shared/createSpriteStage.d.ts +14 -0
  315. package/dist/components/pro/Sprite/shared/createSpriteStage.js +127 -0
  316. package/dist/components/pro/Sprite/shared/createSpriteStage.js.map +1 -0
  317. package/dist/components/pro/Sprite/shared/events.d.ts +5 -0
  318. package/dist/components/pro/Sprite/shared/events.js +21 -0
  319. package/dist/components/pro/Sprite/shared/events.js.map +1 -0
  320. package/dist/components/pro/Sprite/shared/face.d.ts +15 -0
  321. package/dist/components/pro/Sprite/shared/face.js +33 -0
  322. package/dist/components/pro/Sprite/shared/face.js.map +1 -0
  323. package/dist/components/pro/Sprite/shared/faceSurface.d.ts +6 -0
  324. package/dist/components/pro/Sprite/shared/faceSurface.js +66 -0
  325. package/dist/components/pro/Sprite/shared/faceSurface.js.map +1 -0
  326. package/dist/components/pro/Sprite/shared/gait.d.ts +5 -0
  327. package/dist/components/pro/Sprite/shared/gait.js +19 -0
  328. package/dist/components/pro/Sprite/shared/gait.js.map +1 -0
  329. package/dist/components/pro/Sprite/shared/geometry.d.ts +8 -0
  330. package/dist/components/pro/Sprite/shared/geometry.js +59 -0
  331. package/dist/components/pro/Sprite/shared/geometry.js.map +1 -0
  332. package/dist/components/pro/Sprite/shared/magicEffect.d.ts +27 -0
  333. package/dist/components/pro/Sprite/shared/magicEffect.js +61 -0
  334. package/dist/components/pro/Sprite/shared/magicEffect.js.map +1 -0
  335. package/dist/components/pro/Sprite/shared/playback.d.ts +8 -0
  336. package/dist/components/pro/Sprite/shared/playback.js +74 -0
  337. package/dist/components/pro/Sprite/shared/playback.js.map +1 -0
  338. package/dist/components/pro/Sprite/shared/rig.d.ts +6 -0
  339. package/dist/components/pro/Sprite/shared/rig.js +48 -0
  340. package/dist/components/pro/Sprite/shared/rig.js.map +1 -0
  341. package/dist/components/pro/Sprite/shared/scene.d.ts +9 -0
  342. package/dist/components/pro/Sprite/shared/scene.js +21 -0
  343. package/dist/components/pro/Sprite/shared/scene.js.map +1 -0
  344. package/dist/components/pro/Sprite/shared/sculptor.d.ts +14 -0
  345. package/dist/components/pro/Sprite/shared/sculptor.js +78 -0
  346. package/dist/components/pro/Sprite/shared/sculptor.js.map +1 -0
  347. package/dist/components/pro/Sprite/shared/speechBubble.d.ts +15 -0
  348. package/dist/components/pro/Sprite/shared/speechBubble.js +129 -0
  349. package/dist/components/pro/Sprite/shared/speechBubble.js.map +1 -0
  350. package/dist/components/pro/Sprite/types.d.ts +40 -0
  351. package/dist/contexts/AppContext.js.map +1 -1
  352. package/dist/contexts/authentication.js.map +1 -1
  353. package/dist/data-table.js +3 -3
  354. package/dist/data-table.js.map +1 -1
  355. package/dist/dishui.css +1 -1
  356. package/dist/hooks/useClickOutside.js.map +1 -1
  357. package/dist/hooks/useContainerElement.js.map +1 -1
  358. package/dist/hooks/useControllableState.js.map +1 -1
  359. package/dist/hooks/useCopyToClipboard.js.map +1 -1
  360. package/dist/hooks/useDebounce.js.map +1 -1
  361. package/dist/hooks/useDraggable.js.map +1 -1
  362. package/dist/hooks/useTableColumns.js.map +1 -1
  363. package/dist/hooks/useTableData.js.map +1 -1
  364. package/dist/index-nostyled.d.ts +2 -0
  365. package/dist/index.d.ts +2 -0
  366. package/dist/index.js +116 -115
  367. package/dist/layouts/MainLayout.js.map +1 -1
  368. package/dist/layouts/Navbar.js.map +1 -1
  369. package/dist/layouts/Sidebar.js.map +1 -1
  370. package/dist/layouts/headbar/Headbar.js.map +1 -1
  371. package/dist/layouts/headbar/HeadbarLangSwitcher.js.map +1 -1
  372. package/dist/layouts/headbar/HeadbarSearch.js.map +1 -1
  373. package/dist/layouts/headbar/HeadbarThemeSwitcher.js.map +1 -1
  374. package/dist/layouts/headbar/HeadbarTitle.js.map +1 -1
  375. package/dist/sprite.js +2 -0
  376. package/dist/styles/themeStyles.js.map +1 -1
  377. package/dist/utils/cn.js.map +1 -1
  378. package/dist/utils/flexLayout.js.map +1 -1
  379. package/dist/utils/i18n.js.map +1 -1
  380. package/dist/utils/menu.js.map +1 -1
  381. package/dist/utils/rehype-code-meta.js.map +1 -1
  382. package/dist/utils/remark-code-meta.js.map +1 -1
  383. package/dist/utils/routerBuilder.js.map +1 -1
  384. package/dist/utils/safeStorage.js.map +1 -1
  385. package/dist/utils/selection.js +29 -20
  386. package/dist/utils/selection.js.map +1 -1
  387. package/dist/utils/themes.js.map +1 -1
  388. package/package.json +15 -11
@@ -1 +1 @@
1
- {"version":3,"file":"CodeEditor.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/editors/CodeEditor.tsx"],"sourcesContent":["import React, { useEffect, useLayoutEffect, useRef, useState, useCallback, forwardRef, useImperativeHandle } from 'react';\nimport { EditorView, keymap, lineNumbers, highlightActiveLine, highlightActiveLineGutter, drawSelection } from '@codemirror/view';\nimport { EditorState, Extension, Compartment } from '@codemirror/state';\nimport { defaultKeymap, history, historyKeymap, indentWithTab } from '@codemirror/commands';\nimport { syntaxHighlighting, defaultHighlightStyle, foldGutter, indentOnInput, bracketMatching } from '@codemirror/language';\nimport { completionKeymap, closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';\nimport { lintKeymap } from '@codemirror/lint';\nimport { searchKeymap } from '@codemirror/search';\nimport { javascript } from '@codemirror/lang-javascript';\nimport { python } from '@codemirror/lang-python';\nimport { html } from '@codemirror/lang-html';\nimport { css } from '@codemirror/lang-css';\nimport { json } from '@codemirror/lang-json';\nimport { markdown } from '@codemirror/lang-markdown';\nimport { jumpToDefinition, smartAutocompletion, bracketMatchingStyle, lineHighlightStyle, jumpTargetHighlight } from '../extensions';\nimport { createThemeExtension, createHighlightExtension } from '../themes';\nimport { collectVariables, generateOutline } from '../utils';\nimport { defaultContextMenu } from '../extensions/contextMenu';\n\n// 导出类型\nexport type {\n CodeEditorProps,\n CodeEditorHandle,\n LanguageType,\n EditorTheme,\n ContextMenuItem,\n VariableInfo,\n OutlineItem,\n AutocompletionConfig,\n JumpToDefinitionConfig,\n CodeSnippet,\n HistoryEntry,\n} from '../types';\n\nimport type { CodeEditorProps, CodeEditorHandle, AutocompletionConfig, JumpToDefinitionConfig, HistoryEntry } from '../types';\n\n// ============= 语言扩展映射 =============\n\nconst getLanguageExtension = (language: string): Extension => {\n const langMap: Record<string, () => Extension> = {\n javascript: () => javascript({ jsx: false }),\n jsx: () => javascript({ jsx: true }),\n typescript: () => javascript({ jsx: false, typescript: true }),\n tsx: () => javascript({ jsx: true, typescript: true }),\n python,\n html,\n css,\n json,\n markdown,\n };\n\n return langMap[language]?.() || javascript();\n};\n\n// ============= CodeEditor 组件 =============\n\nconst CodeEditor = forwardRef<CodeEditorHandle, CodeEditorProps>(({\n value = '',\n onChange,\n language = 'javascript',\n theme = 'light',\n readOnly = false,\n lineNumbers: showLineNumbers = true,\n highlightActiveLine: shouldHighlightActiveLine = true,\n autocompletion = true,\n jumpToDefinition: jumpToDefinitionConfig = true,\n contextMenu,\n onVariablesCollected,\n onOutlineGenerated,\n enableHistory = false,\n historyLimit = 50,\n historySaveInterval = 3, // 默认 3 * 10s = 30s\n onHistoryChange,\n className = '',\n height = '400px',\n minHeight,\n maxHeight,\n placeholder,\n extensions: customExtensions = [],\n}, ref) => {\n const editorRef = useRef<HTMLDivElement>(null);\n const viewRef = useRef<EditorView | null>(null);\n const [contextMenuState, setContextMenuState] = useState<{\n visible: boolean;\n x: number;\n y: number;\n }>({ visible: false, x: 0, y: 0 });\n\n // 历史记录状态\n const [codeHistory, setCodeHistory] = useState<HistoryEntry[]>([]);\n const [currentHistoryIndex, setCurrentHistoryIndex] = useState<number>(-1);\n const lastSaveTime = useRef<number>(0);\n const isRestoringHistory = useRef<boolean>(false);\n const isExternalUpdate = useRef<boolean>(false); // 标记是否是外部更新\n const pendingContent = useRef<string>('');\n const hasChanges = useRef<boolean>(false);\n const lastSavedContent = useRef<string>(''); // 记录上次保存的内容\n\n // 配置隔间,用于动态更新\n const languageCompartment = useRef(new Compartment());\n const themeCompartment = useRef(new Compartment());\n const highlightCompartment = useRef(new Compartment());\n const readOnlyCompartment = useRef(new Compartment());\n\n const languageRef = useRef(language);\n const documentText = useRef(value);\n const analysisTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const analysisRevision = useRef(0);\n const callbacksRef = useRef({ onChange, onVariablesCollected, onOutlineGenerated });\n const hasVariableListener = Boolean(onVariablesCollected);\n const hasOutlineListener = Boolean(onOutlineGenerated);\n\n const cancelAnalysis = useCallback(() => {\n analysisRevision.current += 1;\n if (analysisTimer.current !== null) {\n clearTimeout(analysisTimer.current);\n analysisTimer.current = null;\n }\n }, []);\n\n const scheduleAnalysis = useCallback((code: string, delay = 150) => {\n cancelAnalysis();\n const view = viewRef.current;\n if (!view || (!callbacksRef.current.onVariablesCollected && !callbacksRef.current.onOutlineGenerated)) return;\n\n const revision = analysisRevision.current;\n const doc = view.state.doc;\n const analysisLanguage = languageRef.current;\n const isCurrent = () => revision === analysisRevision.current\n && viewRef.current === view && view.state.doc === doc\n && languageRef.current === analysisLanguage;\n\n analysisTimer.current = setTimeout(() => {\n analysisTimer.current = null;\n if (!isCurrent()) return;\n const variables = callbacksRef.current.onVariablesCollected\n ? collectVariables(code, analysisLanguage) : undefined;\n const outline = callbacksRef.current.onOutlineGenerated\n ? generateOutline(code, analysisLanguage) : undefined;\n\n // A callback may synchronously change the document/language or unmount us.\n if (variables && isCurrent()) callbacksRef.current.onVariablesCollected?.(variables);\n if (outline && isCurrent()) callbacksRef.current.onOutlineGenerated?.(outline);\n }, delay);\n }, [cancelAnalysis]);\n\n // 跳转到指定行\n const jumpToLine = useCallback((line: number) => {\n if (viewRef.current) {\n try {\n const lineInfo = viewRef.current.state.doc.line(line);\n viewRef.current.dispatch({\n selection: { anchor: lineInfo.from, head: lineInfo.to },\n scrollIntoView: true,\n });\n viewRef.current.focus();\n } catch (error) {\n console.error('Failed to jump to line:', error);\n }\n }\n }, []);\n\n // 添加历史记录\n const addToHistory = useCallback((content: string, description?: string) => {\n // 如果是外部更新或正在恢复历史,不添加记录\n if (!enableHistory || isRestoringHistory.current || isExternalUpdate.current) {\n return;\n }\n\n const now = Date.now();\n const intervalMs = historySaveInterval * 10000; // 转换为毫秒\n const timeSinceLastSave = now - lastSaveTime.current;\n const timeCheckPassed = timeSinceLastSave >= intervalMs;\n\n // 按配置的间隔记录\n if (!timeCheckPassed) {\n // 时间未到,标记有变更,但不立即保存\n hasChanges.current = true;\n pendingContent.current = content;\n return;\n }\n\n // 时间检查已通过,现在检查内容是否真的发生变化\n if (content === lastSavedContent.current && !description) {\n // 内容没有变化,不保存\n hasChanges.current = false;\n return;\n }\n\n // 时间检查通过 + 内容有变化 → 保存!\n lastSaveTime.current = now;\n hasChanges.current = false;\n lastSavedContent.current = content; // 记录本次保存的内容\n\n setCodeHistory((prevHistory) => {\n // 如果当前不在最新位置,删除后面的历史\n const newHistory = currentHistoryIndex >= 0\n ? prevHistory.slice(0, currentHistoryIndex + 1)\n : prevHistory;\n\n const newEntry: HistoryEntry = {\n id: `${now}-${Math.random()}`,\n timestamp: new Date(now),\n content,\n description,\n };\n\n const updatedHistory = [...newHistory, newEntry];\n\n // 限制历史记录数量\n if (updatedHistory.length > historyLimit) {\n updatedHistory.shift();\n }\n\n const newIndex = updatedHistory.length - 1;\n setCurrentHistoryIndex(newIndex);\n\n // 延迟调用 onHistoryChange 避免在渲染期间更新父组件\n setTimeout(() => {\n if (onHistoryChange) {\n onHistoryChange(updatedHistory, newIndex);\n }\n }, 0);\n\n return updatedHistory;\n });\n }, [enableHistory, historyLimit, historySaveInterval, currentHistoryIndex, onHistoryChange]);\n\n const historyWriterRef = useRef(addToHistory);\n useLayoutEffect(() => {\n languageRef.current = language;\n callbacksRef.current = { onChange, onVariablesCollected, onOutlineGenerated };\n historyWriterRef.current = addToHistory;\n });\n\n // 恢复历史记录\n const restoreHistory = useCallback((index: number) => {\n if (index < 0 || index >= codeHistory.length) return;\n\n isRestoringHistory.current = true;\n const entry = codeHistory[index];\n\n if (viewRef.current) {\n viewRef.current.dispatch({\n changes: {\n from: 0,\n to: viewRef.current.state.doc.length,\n insert: entry.content,\n },\n });\n }\n\n // 清除当前版本之后的所有版本\n const newHistory = codeHistory.slice(0, index + 1);\n setCodeHistory(newHistory);\n\n // 回滚的版本成为最新版本\n const newIndex = newHistory.length - 1;\n setCurrentHistoryIndex(newIndex);\n\n // 延迟调用 onHistoryChange 避免在渲染期间更新父组件\n setTimeout(() => {\n if (onHistoryChange) {\n onHistoryChange(newHistory, newIndex);\n }\n }, 0);\n\n // 触发 onChange\n if (onChange) {\n onChange(entry.content);\n }\n\n // 延迟重置标志,确保不会立即添加到历史\n setTimeout(() => {\n isRestoringHistory.current = false;\n }, 100);\n }, [codeHistory, onChange, onHistoryChange]);\n\n // 暴露历史记录相关方法\n useImperativeHandle(ref, () => ({\n jumpToLine,\n getView: () => viewRef.current,\n getValue: () => viewRef.current?.state.doc.toString() || '',\n setValue: (newValue: string) => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n changes: {\n from: 0,\n to: viewRef.current.state.doc.length,\n insert: newValue,\n },\n });\n }\n },\n focus: () => viewRef.current?.focus(),\n getHistory: () => codeHistory,\n restoreHistory,\n clearHistory: () => {\n setCodeHistory([]);\n setCurrentHistoryIndex(-1);\n // 重置所有历史记录相关的内部状态\n lastSaveTime.current = 0;\n hasChanges.current = false;\n pendingContent.current = '';\n lastSavedContent.current = '';\n // 延迟调用 onHistoryChange 避免在渲染期间更新父组件\n setTimeout(() => {\n if (onHistoryChange) {\n onHistoryChange([], -1);\n }\n }, 0);\n },\n } as any), [jumpToLine, codeHistory, restoreHistory, onHistoryChange]);\n\n // 定时保存待处理的历史记录\n useEffect(() => {\n if (!enableHistory) return;\n\n const intervalMs = historySaveInterval * 10000; // 转换为毫秒\n\n const interval = setInterval(() => {\n if (hasChanges.current && pendingContent.current) {\n addToHistory(pendingContent.current);\n }\n }, intervalMs);\n\n return () => clearInterval(interval);\n }, [enableHistory, historySaveInterval, addToHistory]);\n\n // 初始化编辑器\n useEffect(() => {\n if (!editorRef.current) return;\n\n const updateListener = EditorView.updateListener.of((update) => {\n if (!update.docChanged) return;\n const newContent = update.state.doc.toString();\n documentText.current = newContent;\n // Schedule before notifying consumers so reentrant updates always win.\n scheduleAnalysis(newContent);\n try {\n if (!isExternalUpdate.current) historyWriterRef.current(newContent);\n } finally {\n isExternalUpdate.current = false;\n }\n callbacksRef.current.onChange?.(newContent);\n });\n\n const baseExtensions: Extension[] = [\n history(),\n drawSelection(),\n bracketMatching(),\n closeBrackets(),\n indentOnInput(),\n syntaxHighlighting(defaultHighlightStyle, { fallback: true }),\n languageCompartment.current.of(getLanguageExtension(language)),\n themeCompartment.current.of(createThemeExtension(theme)),\n highlightCompartment.current.of(createHighlightExtension(theme)),\n readOnlyCompartment.current.of(EditorState.readOnly.of(readOnly)),\n updateListener,\n keymap.of([\n ...closeBracketsKeymap,\n ...defaultKeymap,\n ...searchKeymap,\n ...historyKeymap,\n ...completionKeymap,\n ...lintKeymap,\n indentWithTab,\n ]),\n bracketMatchingStyle,\n lineHighlightStyle,\n jumpTargetHighlight,\n ];\n\n // 可选扩展\n if (showLineNumbers) {\n baseExtensions.push(lineNumbers(), foldGutter(), highlightActiveLineGutter());\n }\n\n if (shouldHighlightActiveLine) {\n baseExtensions.push(highlightActiveLine());\n }\n\n // 自动补全\n if (autocompletion) {\n const config: AutocompletionConfig = typeof autocompletion === 'object' ? autocompletion : {};\n baseExtensions.push(smartAutocompletion(language, config));\n }\n\n // 跳转到定义\n if (jumpToDefinitionConfig) {\n const config: JumpToDefinitionConfig = typeof jumpToDefinitionConfig === 'object'\n ? jumpToDefinitionConfig\n : {};\n baseExtensions.push(jumpToDefinition(jumpToLine, config));\n }\n\n // 占位符\n if (placeholder) {\n baseExtensions.push(\n EditorView.contentAttributes.of({ 'data-placeholder': placeholder })\n );\n }\n\n // 自定义扩展\n if (customExtensions.length > 0) {\n baseExtensions.push(...customExtensions);\n }\n\n const startState = EditorState.create({\n doc: value,\n extensions: baseExtensions,\n });\n\n const view = new EditorView({\n state: startState,\n parent: editorRef.current,\n });\n\n viewRef.current = view;\n documentText.current = view.state.doc.toString();\n\n // 添加初始内容到历史记录\n if (enableHistory && value) {\n addToHistory(value, 'Initial content');\n }\n\n return () => {\n cancelAnalysis();\n viewRef.current = null;\n view.destroy();\n };\n }, []); // 只在挂载时初始化\n\n // 更新值\n useEffect(() => {\n if (viewRef.current && value !== documentText.current) {\n isExternalUpdate.current = true; // 标记为外部更新\n viewRef.current.dispatch({\n changes: {\n from: 0,\n to: viewRef.current.state.doc.length,\n insert: value,\n },\n });\n // 注意:标志会在 updateListener 中被立即重置,不需要 setTimeout\n }\n }, [value]);\n\n // 更新语言\n useEffect(() => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n effects: languageCompartment.current.reconfigure(getLanguageExtension(language)),\n });\n }\n }, [language]);\n\n // Callback identity changes only update refs: inline callbacks must not restart\n // pending input analysis or create a callback -> render -> analysis loop.\n useEffect(() => {\n scheduleAnalysis(documentText.current, 0);\n return cancelAnalysis;\n }, [language, hasVariableListener, hasOutlineListener, scheduleAnalysis, cancelAnalysis]);\n\n // 更新主题\n useEffect(() => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n effects: [\n themeCompartment.current.reconfigure(createThemeExtension(theme)),\n highlightCompartment.current.reconfigure(createHighlightExtension(theme)),\n ],\n });\n }\n }, [theme]);\n\n // 更新只读状态\n useEffect(() => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n effects: readOnlyCompartment.current.reconfigure(EditorState.readOnly.of(readOnly)),\n });\n }\n }, [readOnly]);\n\n // 处理右键菜单\n const handleContextMenu = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n setContextMenuState({\n visible: true,\n x: e.clientX,\n y: e.clientY,\n });\n }, []);\n\n const closeContextMenu = useCallback(() => {\n setContextMenuState({ visible: false, x: 0, y: 0 });\n }, []);\n\n const handleMenuItemClick = useCallback(\n (item: any) => {\n if (viewRef.current && !item.disabled) {\n item.action(viewRef.current);\n }\n closeContextMenu();\n },\n [closeContextMenu]\n );\n\n // 点击其他地方关闭菜单\n useEffect(() => {\n if (contextMenuState.visible) {\n const handleClick = () => closeContextMenu();\n document.addEventListener('click', handleClick);\n return () => document.removeEventListener('click', handleClick);\n }\n }, [contextMenuState.visible, closeContextMenu]);\n\n const editorStyles: React.CSSProperties = {\n height,\n minHeight,\n maxHeight,\n overflow: 'auto',\n };\n\n const menuItems = contextMenu || defaultContextMenu;\n\n return (\n <div className={`code-editor-wrapper ${className}`}>\n <div\n ref={editorRef}\n onContextMenu={handleContextMenu}\n style={editorStyles}\n className=\"code-editor\"\n />\n\n {/* 上下文菜单 */}\n {contextMenuState.visible && (\n <div\n className=\"context-menu\"\n style={{\n position: 'fixed',\n top: contextMenuState.y,\n left: contextMenuState.x,\n zIndex: 1000,\n }}\n >\n <ul className=\"menu bg-base-200 rounded-box shadow-lg\">\n {menuItems.map((item, index) => {\n if (item.separator) {\n return <li key={index} className=\"menu-separator\" />;\n }\n return (\n <li key={index}>\n <a\n onClick={() => handleMenuItemClick(item)}\n className={item.disabled ? 'disabled' : ''}\n >\n {item.label}\n </a>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n\n <style>{`\n .code-editor-wrapper {\n position: relative;\n border: 1px solid var(--fallback-bc, oklch(var(--bc) / 0.2));\n border-radius: 0.5rem;\n overflow: hidden;\n }\n\n .code-editor .cm-editor {\n height: 100%;\n }\n\n .code-editor .cm-scroller {\n overflow: auto;\n font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;\n font-size: 14px;\n line-height: 1.5;\n }\n\n .code-editor .cm-content[data-placeholder]::before {\n content: attr(data-placeholder);\n color: var(--fallback-bc, oklch(var(--bc) / 0.4));\n position: absolute;\n pointer-events: none;\n }\n\n .context-menu {\n min-width: 150px;\n }\n\n .context-menu .menu-separator {\n height: 1px;\n background: var(--fallback-bc, oklch(var(--bc) / 0.2));\n margin: 0.25rem 0;\n }\n\n .context-menu .disabled {\n opacity: 0.5;\n pointer-events: none;\n }\n `}</style>\n </div>\n );\n});\n\nCodeEditor.displayName = 'CodeEditor';\n\nexport default CodeEditor;\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAsCA,IAAM,MAAwB,OAarB;CAXL,kBAAkB,EAAW,EAAE,KAAK,GAAM,CAAC;CAC3C,WAAW,EAAW,EAAE,KAAK,GAAK,CAAC;CACnC,kBAAkB,EAAW;EAAE,KAAK;EAAO,YAAY;CAAK,CAAC;CAC7D,WAAW,EAAW;EAAE,KAAK;EAAM,YAAY;CAAK,CAAC;CACrD;CACA;CACA;CACA;CACA;AAGK,EAAA,CAAQ,EAAS,GAAG,KAAK,EAAW,GAKvC,IAAa,GAA+C,EAChE,WAAQ,IACR,aACA,cAAW,cACX,WAAQ,SACR,cAAW,IACX,aAAa,KAAkB,IAC/B,qBAAqB,KAA4B,IACjD,oBAAiB,IACjB,kBAAkB,IAAyB,IAC3C,iBACA,yBACA,uBACA,mBAAgB,IAChB,kBAAe,IACf,yBAAsB,GACtB,oBACA,gBAAY,IACZ,aAAS,SACT,eACA,eACA,iBACA,YAAY,KAAmB,CAAC,KAC/B,OAAQ;CACT,IAAM,IAAY,EAAuB,IAAI,GACvC,IAAU,EAA0B,IAAI,GACxC,CAAC,GAAkB,KAAuB,EAI7C;EAAE,SAAS;EAAO,GAAG;EAAG,GAAG;CAAE,CAAC,GAG3B,CAAC,GAAa,KAAkB,EAAyB,CAAC,CAAC,GAC3D,CAAC,GAAqB,KAA0B,EAAiB,EAAE,GACnE,IAAe,EAAe,CAAC,GAC/B,IAAqB,EAAgB,EAAK,GAC1C,IAAmB,EAAgB,EAAK,GACxC,IAAiB,EAAe,EAAE,GAClC,IAAa,EAAgB,EAAK,GAClC,IAAmB,EAAe,EAAE,GAGpC,KAAsB,EAAO,IAAI,EAAY,CAAC,GAC9C,KAAmB,EAAO,IAAI,EAAY,CAAC,GAC3C,KAAuB,EAAO,IAAI,EAAY,CAAC,GAC/C,KAAsB,EAAO,IAAI,EAAY,CAAC,GAE9C,IAAc,EAAO,CAAQ,GAC7B,IAAe,EAAO,CAAK,GAC3B,IAAgB,EAA6C,IAAI,GACjE,IAAmB,EAAO,CAAC,GAC3B,IAAe,EAAO;EAAE;EAAU;EAAsB;CAAmB,CAAC,GAC5E,KAAsB,EAAQ,GAC9B,KAAqB,EAAQ,GAE7B,IAAiB,QAAkB;EAEvC,AADA,EAAiB,WAAW,GACxB,EAAc,YAAY,SAC5B,aAAa,EAAc,OAAO,GAClC,EAAc,UAAU;CAE5B,GAAG,CAAC,CAAC,GAEC,IAAmB,GAAa,GAAc,IAAQ,QAAQ;EAClE,EAAe;EACf,IAAM,IAAO,EAAQ;EACrB,IAAI,CAAC,KAAS,CAAC,EAAa,QAAQ,wBAAwB,CAAC,EAAa,QAAQ,oBAAqB;EAEvG,IAAM,IAAW,EAAiB,SAC5B,IAAM,EAAK,MAAM,KACjB,IAAmB,EAAY,SAC/B,UAAkB,MAAa,EAAiB,WACjD,EAAQ,YAAY,KAAQ,EAAK,MAAM,QAAQ,KAC/C,EAAY,YAAY;EAE7B,EAAc,UAAU,iBAAiB;GAEvC,IADA,EAAc,UAAU,MACpB,CAAC,EAAU,GAAG;GAClB,IAAM,IAAY,EAAa,QAAQ,uBACnC,EAAiB,GAAM,CAAgB,IAAI,KAAA,GACzC,IAAU,EAAa,QAAQ,qBACjC,EAAgB,GAAM,CAAgB,IAAI,KAAA;GAI9C,AADI,KAAa,EAAU,KAAG,EAAa,QAAQ,uBAAuB,CAAS,GAC/E,KAAW,EAAU,KAAG,EAAa,QAAQ,qBAAqB,CAAO;EAC/E,GAAG,CAAK;CACV,GAAG,CAAC,CAAc,CAAC,GAGb,IAAa,GAAa,MAAiB;EAC/C,IAAI,EAAQ,SACV,IAAI;GACF,IAAM,IAAW,EAAQ,QAAQ,MAAM,IAAI,KAAK,CAAI;GAKpD,AAJA,EAAQ,QAAQ,SAAS;IACvB,WAAW;KAAE,QAAQ,EAAS;KAAM,MAAM,EAAS;IAAG;IACtD,gBAAgB;GAClB,CAAC,GACD,EAAQ,QAAQ,MAAM;EACxB,SAAS,GAAO;GACd,QAAQ,MAAM,2BAA2B,CAAK;EAChD;CAEJ,GAAG,CAAC,CAAC,GAGC,IAAe,GAAa,GAAiB,MAAyB;EAE1E,IAAI,CAAC,KAAiB,EAAmB,WAAW,EAAiB,SACnE;EAGF,IAAM,IAAM,KAAK,IAAI,GACf,IAAa,IAAsB;EAKzC,IAAI,EAJsB,IAAM,EAAa,WACA,IAGvB;GAGpB,AADA,EAAW,UAAU,IACrB,EAAe,UAAU;GACzB;EACF;EAGA,IAAI,MAAY,EAAiB,WAAW,CAAC,GAAa;GAExD,EAAW,UAAU;GACrB;EACF;EAOA,AAJA,EAAa,UAAU,GACvB,EAAW,UAAU,IACrB,EAAiB,UAAU,GAE3B,GAAgB,MAAgB;GAE9B,IAAM,IAAa,KAAuB,IACtC,EAAY,MAAM,GAAG,IAAsB,CAAC,IAC5C,GAEE,IAAyB;IAC7B,IAAI,GAAG,EAAI,GAAG,KAAK,OAAO;IAC1B,WAAW,IAAI,KAAK,CAAG;IACvB;IACA;GACF,GAEM,IAAiB,CAAC,GAAG,GAAY,CAAQ;GAG/C,AAAI,EAAe,SAAS,KAC1B,EAAe,MAAM;GAGvB,IAAM,IAAW,EAAe,SAAS;GAUzC,OATA,EAAuB,CAAQ,GAG/B,iBAAiB;IACf,AAAI,KACF,EAAgB,GAAgB,CAAQ;GAE5C,GAAG,CAAC,GAEG;EACT,CAAC;CACH,GAAG;EAAC;EAAe;EAAc;EAAqB;EAAqB;CAAe,CAAC,GAErF,KAAmB,EAAO,CAAY;CAC5C,SAAsB;EAGpB,AAFA,EAAY,UAAU,GACtB,EAAa,UAAU;GAAE;GAAU;GAAsB;EAAmB,GAC5E,GAAiB,UAAU;CAC7B,CAAC;CAGD,IAAM,KAAiB,GAAa,MAAkB;EACpD,IAAI,IAAQ,KAAK,KAAS,EAAY,QAAQ;EAE9C,EAAmB,UAAU;EAC7B,IAAM,IAAQ,EAAY;EAE1B,AAAI,EAAQ,WACV,EAAQ,QAAQ,SAAS,EACvB,SAAS;GACP,MAAM;GACN,IAAI,EAAQ,QAAQ,MAAM,IAAI;GAC9B,QAAQ,EAAM;EAChB,EACF,CAAC;EAIH,IAAM,IAAa,EAAY,MAAM,GAAG,IAAQ,CAAC;EACjD,EAAe,CAAU;EAGzB,IAAM,IAAW,EAAW,SAAS;EAgBrC,AAfA,EAAuB,CAAQ,GAG/B,iBAAiB;GACf,AAAI,KACF,EAAgB,GAAY,CAAQ;EAExC,GAAG,CAAC,GAGA,KACF,EAAS,EAAM,OAAO,GAIxB,iBAAiB;GACf,EAAmB,UAAU;EAC/B,GAAG,GAAG;CACR,GAAG;EAAC;EAAa;EAAU;CAAe,CAAC;CAyM3C,AAtMA,GAAoB,WAAY;EAC9B;EACA,eAAe,EAAQ;EACvB,gBAAgB,EAAQ,SAAS,MAAM,IAAI,SAAS,KAAK;EACzD,WAAW,MAAqB;GAC9B,AAAI,EAAQ,WACV,EAAQ,QAAQ,SAAS,EACvB,SAAS;IACP,MAAM;IACN,IAAI,EAAQ,QAAQ,MAAM,IAAI;IAC9B,QAAQ;GACV,EACF,CAAC;EAEL;EACA,aAAa,EAAQ,SAAS,MAAM;EACpC,kBAAkB;EAClB;EACA,oBAAoB;GASlB,AARA,EAAe,CAAC,CAAC,GACjB,EAAuB,EAAE,GAEzB,EAAa,UAAU,GACvB,EAAW,UAAU,IACrB,EAAe,UAAU,IACzB,EAAiB,UAAU,IAE3B,iBAAiB;IACf,AAAI,KACF,EAAgB,CAAC,GAAG,EAAE;GAE1B,GAAG,CAAC;EACN;CACF,IAAW;EAAC;EAAY;EAAa;EAAgB;CAAe,CAAC,GAGrE,QAAgB;EACd,IAAI,CAAC,GAAe;EAEpB,IAAM,IAAa,IAAsB,KAEnC,IAAW,kBAAkB;GACjC,AAAI,EAAW,WAAW,EAAe,WACvC,EAAa,EAAe,OAAO;EAEvC,GAAG,CAAU;EAEb,aAAa,cAAc,CAAQ;CACrC,GAAG;EAAC;EAAe;EAAqB;CAAY,CAAC,GAGrD,QAAgB;EACd,IAAI,CAAC,EAAU,SAAS;EAExB,IAAM,IAAiB,EAAW,eAAe,IAAI,MAAW;GAC9D,IAAI,CAAC,EAAO,YAAY;GACxB,IAAM,IAAa,EAAO,MAAM,IAAI,SAAS;GAG7C,AAFA,EAAa,UAAU,GAEvB,EAAiB,CAAU;GAC3B,IAAI;IACF,AAAK,EAAiB,WAAS,GAAiB,QAAQ,CAAU;GACpE,UAAU;IACR,EAAiB,UAAU;GAC7B;GACA,EAAa,QAAQ,WAAW,CAAU;EAC5C,CAAC,GAEK,IAA8B;GAClC,GAAQ;GACR,GAAc;GACd,GAAgB;GAChB,GAAc;GACd,GAAc;GACd,GAAmB,IAAuB,EAAE,UAAU,GAAK,CAAC;GAC5D,GAAoB,QAAQ,GAAG,GAAqB,CAAQ,CAAC;GAC7D,GAAiB,QAAQ,GAAG,EAAqB,CAAK,CAAC;GACvD,GAAqB,QAAQ,GAAG,EAAyB,CAAK,CAAC;GAC/D,GAAoB,QAAQ,GAAG,EAAY,SAAS,GAAG,CAAQ,CAAC;GAChE;GACA,GAAO,GAAG;IACR,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH;GACF,CAAC;GACD;GACA;GACA;EACF;EAYA,IATI,MACF,EAAe,KAAK,GAAY,GAAG,GAAW,GAAG,GAA0B,CAAC,GAG1E,MACF,EAAe,KAAK,GAAoB,CAAC,GAIvC,GAAgB;GAClB,IAAM,IAA+B,OAAO,KAAmB,WAAW,IAAiB,CAAC;GAC5F,EAAe,KAAK,EAAoB,GAAU,CAAM,CAAC;EAC3D;EAGA,IAAI,GAAwB;GAC1B,IAAM,IAAiC,OAAO,KAA2B,WACrE,IACA,CAAC;GACL,EAAe,KAAK,EAAiB,GAAY,CAAM,CAAC;EAC1D;EAUA,AAPI,MACF,EAAe,KACb,EAAW,kBAAkB,GAAG,EAAE,oBAAoB,GAAY,CAAC,CACrE,GAIE,GAAiB,SAAS,KAC5B,EAAe,KAAK,GAAG,EAAgB;EAGzC,IAAM,KAAa,EAAY,OAAO;GACpC,KAAK;GACL,YAAY;EACd,CAAC,GAEK,IAAO,IAAI,EAAW;GAC1B,OAAO;GACP,QAAQ,EAAU;EACpB,CAAC;EAUD,OARA,EAAQ,UAAU,GAClB,EAAa,UAAU,EAAK,MAAM,IAAI,SAAS,GAG3C,KAAiB,KACnB,EAAa,GAAO,iBAAiB,SAG1B;GAGX,AAFA,EAAe,GACf,EAAQ,UAAU,MAClB,EAAK,QAAQ;EACf;CACF,GAAG,CAAC,CAAC,GAGL,QAAgB;EACd,AAAI,EAAQ,WAAW,MAAU,EAAa,YAC5C,EAAiB,UAAU,IAC3B,EAAQ,QAAQ,SAAS,EACvB,SAAS;GACP,MAAM;GACN,IAAI,EAAQ,QAAQ,MAAM,IAAI;GAC9B,QAAQ;EACV,EACF,CAAC;CAGL,GAAG,CAAC,CAAK,CAAC,GAGV,QAAgB;EACd,AAAI,EAAQ,WACV,EAAQ,QAAQ,SAAS,EACvB,SAAS,GAAoB,QAAQ,YAAY,GAAqB,CAAQ,CAAC,EACjF,CAAC;CAEL,GAAG,CAAC,CAAQ,CAAC,GAIb,SACE,EAAiB,EAAa,SAAS,CAAC,GACjC,IACN;EAAC;EAAU;EAAqB;EAAoB;EAAkB;CAAc,CAAC,GAGxF,QAAgB;EACd,AAAI,EAAQ,WACV,EAAQ,QAAQ,SAAS,EACvB,SAAS,CACP,GAAiB,QAAQ,YAAY,EAAqB,CAAK,CAAC,GAChE,GAAqB,QAAQ,YAAY,EAAyB,CAAK,CAAC,CAC1E,EACF,CAAC;CAEL,GAAG,CAAC,CAAK,CAAC,GAGV,QAAgB;EACd,AAAI,EAAQ,WACV,EAAQ,QAAQ,SAAS,EACvB,SAAS,GAAoB,QAAQ,YAAY,EAAY,SAAS,GAAG,CAAQ,CAAC,EACpF,CAAC;CAEL,GAAG,CAAC,CAAQ,CAAC;CAGb,IAAM,KAAoB,GAAa,MAAwB;EAE7D,AADA,EAAE,eAAe,GACjB,EAAoB;GAClB,SAAS;GACT,GAAG,EAAE;GACL,GAAG,EAAE;EACP,CAAC;CACH,GAAG,CAAC,CAAC,GAEC,IAAmB,QAAkB;EACzC,EAAoB;GAAE,SAAS;GAAO,GAAG;GAAG,GAAG;EAAE,CAAC;CACpD,GAAG,CAAC,CAAC,GAEC,KAAsB,GACzB,MAAc;EAIb,AAHI,EAAQ,WAAW,CAAC,EAAK,YAC3B,EAAK,OAAO,EAAQ,OAAO,GAE7B,EAAiB;CACnB,GACA,CAAC,CAAgB,CACnB;CAGA,QAAgB;EACd,IAAI,EAAiB,SAAS;GAC5B,IAAM,UAAoB,EAAiB;GAE3C,OADA,SAAS,iBAAiB,SAAS,CAAW,SACjC,SAAS,oBAAoB,SAAS,CAAW;EAChE;CACF,GAAG,CAAC,EAAiB,SAAS,CAAgB,CAAC;CAE/C,IAAM,KAAoC;EACxC;EACA;EACA;EACA,UAAU;CACZ,GAEM,KAAY,MAAe;CAEjC,OACE,mBAAC,OAAD;EAAK,WAAW,uBAAuB;EAAvC,UAAA;GACE,kBAAC,OAAD;IACE,KAAK;IACL,eAAe;IACf,OAAO;IACP,WAAU;GACX,CAAA;GAGA,EAAiB,WAChB,kBAAC,OAAD;IACE,WAAU;IACV,OAAO;KACL,UAAU;KACV,KAAK,EAAiB;KACtB,MAAM,EAAiB;KACvB,QAAQ;IACV;IAEA,UAAA,kBAAC,MAAD;KAAI,WAAU;KACX,UAAA,GAAU,KAAK,GAAM,MAChB,EAAK,YACA,kBAAC,MAAD,EAAgB,WAAU,iBAAkB,GAAnC,CAAmC,IAGnD,kBAAC,MAAD,EAAA,UACE,kBAAC,KAAD;MACE,eAAe,GAAoB,CAAI;MACvC,WAAW,EAAK,WAAW,aAAa;MAEvC,UAAA,EAAK;KACL,CAAA,EACD,GAPK,CAOL,CAEP;IACC,CAAA;GACD,CAAA;GAGP,kBAAC,SAAD,EAAA,UAAQ,mkCAwCC,CAAA;EACN;;AAET,CAAC;AAED,EAAW,cAAc"}
1
+ {"version":3,"file":"CodeEditor.js","names":["getLanguageExtension","javascript","language","CodeEditor","forwardRef","showLineNumbers","shouldHighlightActiveLine","jumpToDefinitionConfig","customExtensions","editorRef","useRef","viewRef","contextMenuState","setContextMenuState","useState","codeHistory","setCodeHistory","currentHistoryIndex","setCurrentHistoryIndex","lastSaveTime","isRestoringHistory","isExternalUpdate","pendingContent","hasChanges","lastSavedContent","languageCompartment","Compartment","themeCompartment","highlightCompartment","readOnlyCompartment","languageRef","documentText","value","analysisTimer","analysisRevision","callbacksRef","hasVariableListener","onVariablesCollected","hasOutlineListener","onOutlineGenerated","cancelAnalysis","useCallback","scheduleAnalysis","view","revision","doc","analysisLanguage","isCurrent","variables","collectVariables","code","outline","generateOutline","delay","jumpToLine","lineInfo","line","error","addToHistory","enableHistory","now","intervalMs","historySaveInterval","content","description","newHistory","prevHistory","newEntry","updatedHistory","historyLimit","newIndex","onHistoryChange","historyWriterRef","restoreHistory","index","entry","onChange","useImperativeHandle","ref","newValue","useEffect","interval","updateListener","EditorView","update","newContent","baseExtensions","history","drawSelection","bracketMatching","closeBrackets","indentOnInput","syntaxHighlighting","defaultHighlightStyle","createThemeExtension","theme","createHighlightExtension","EditorState","readOnly","keymap","closeBracketsKeymap","defaultKeymap","searchKeymap","historyKeymap","completionKeymap","lintKeymap","indentWithTab","bracketMatchingStyle","lineHighlightStyle","jumpTargetHighlight","lineNumbers","foldGutter","highlightActiveLineGutter","highlightActiveLine","autocompletion","config","smartAutocompletion","jumpToDefinition","placeholder","startState","handleContextMenu","closeContextMenu","handleMenuItemClick","item","handleClick","editorStyles","menuItems","contextMenu","defaultContextMenu","className"],"sources":["../../../../../src/components/pro/CodeEditor/editors/CodeEditor.tsx"],"sourcesContent":["import React, { useEffect, useLayoutEffect, useRef, useState, useCallback, forwardRef, useImperativeHandle } from 'react';\nimport { EditorView, keymap, lineNumbers, highlightActiveLine, highlightActiveLineGutter, drawSelection } from '@codemirror/view';\nimport { EditorState, Extension, Compartment } from '@codemirror/state';\nimport { defaultKeymap, history, historyKeymap, indentWithTab } from '@codemirror/commands';\nimport { syntaxHighlighting, defaultHighlightStyle, foldGutter, indentOnInput, bracketMatching } from '@codemirror/language';\nimport { completionKeymap, closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';\nimport { lintKeymap } from '@codemirror/lint';\nimport { searchKeymap } from '@codemirror/search';\nimport { javascript } from '@codemirror/lang-javascript';\nimport { python } from '@codemirror/lang-python';\nimport { html } from '@codemirror/lang-html';\nimport { css } from '@codemirror/lang-css';\nimport { json } from '@codemirror/lang-json';\nimport { markdown } from '@codemirror/lang-markdown';\nimport { jumpToDefinition, smartAutocompletion, bracketMatchingStyle, lineHighlightStyle, jumpTargetHighlight } from '../extensions';\nimport { createThemeExtension, createHighlightExtension } from '../themes';\nimport { collectVariables, generateOutline } from '../utils';\nimport { defaultContextMenu } from '../extensions/contextMenu';\n\n// 导出类型\nexport type {\n CodeEditorProps,\n CodeEditorHandle,\n LanguageType,\n EditorTheme,\n ContextMenuItem,\n VariableInfo,\n OutlineItem,\n AutocompletionConfig,\n JumpToDefinitionConfig,\n CodeSnippet,\n HistoryEntry,\n} from '../types';\n\nimport type { CodeEditorProps, CodeEditorHandle, AutocompletionConfig, JumpToDefinitionConfig, HistoryEntry } from '../types';\n\n// ============= 语言扩展映射 =============\n\nconst getLanguageExtension = (language: string): Extension => {\n const langMap: Record<string, () => Extension> = {\n javascript: () => javascript({ jsx: false }),\n jsx: () => javascript({ jsx: true }),\n typescript: () => javascript({ jsx: false, typescript: true }),\n tsx: () => javascript({ jsx: true, typescript: true }),\n python,\n html,\n css,\n json,\n markdown,\n };\n\n return langMap[language]?.() || javascript();\n};\n\n// ============= CodeEditor 组件 =============\n\nconst CodeEditor = forwardRef<CodeEditorHandle, CodeEditorProps>(({\n value = '',\n onChange,\n language = 'javascript',\n theme = 'light',\n readOnly = false,\n lineNumbers: showLineNumbers = true,\n highlightActiveLine: shouldHighlightActiveLine = true,\n autocompletion = true,\n jumpToDefinition: jumpToDefinitionConfig = true,\n contextMenu,\n onVariablesCollected,\n onOutlineGenerated,\n enableHistory = false,\n historyLimit = 50,\n historySaveInterval = 3, // 默认 3 * 10s = 30s\n onHistoryChange,\n className = '',\n height = '400px',\n minHeight,\n maxHeight,\n placeholder,\n extensions: customExtensions = [],\n}, ref) => {\n const editorRef = useRef<HTMLDivElement>(null);\n const viewRef = useRef<EditorView | null>(null);\n const [contextMenuState, setContextMenuState] = useState<{\n visible: boolean;\n x: number;\n y: number;\n }>({ visible: false, x: 0, y: 0 });\n\n // 历史记录状态\n const [codeHistory, setCodeHistory] = useState<HistoryEntry[]>([]);\n const [currentHistoryIndex, setCurrentHistoryIndex] = useState<number>(-1);\n const lastSaveTime = useRef<number>(0);\n const isRestoringHistory = useRef<boolean>(false);\n const isExternalUpdate = useRef<boolean>(false); // 标记是否是外部更新\n const pendingContent = useRef<string>('');\n const hasChanges = useRef<boolean>(false);\n const lastSavedContent = useRef<string>(''); // 记录上次保存的内容\n\n // 配置隔间,用于动态更新\n const languageCompartment = useRef(new Compartment());\n const themeCompartment = useRef(new Compartment());\n const highlightCompartment = useRef(new Compartment());\n const readOnlyCompartment = useRef(new Compartment());\n\n const languageRef = useRef(language);\n const documentText = useRef(value);\n const analysisTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const analysisRevision = useRef(0);\n const callbacksRef = useRef({ onChange, onVariablesCollected, onOutlineGenerated });\n const hasVariableListener = Boolean(onVariablesCollected);\n const hasOutlineListener = Boolean(onOutlineGenerated);\n\n const cancelAnalysis = useCallback(() => {\n analysisRevision.current += 1;\n if (analysisTimer.current !== null) {\n clearTimeout(analysisTimer.current);\n analysisTimer.current = null;\n }\n }, []);\n\n const scheduleAnalysis = useCallback((code: string, delay = 150) => {\n cancelAnalysis();\n const view = viewRef.current;\n if (!view || (!callbacksRef.current.onVariablesCollected && !callbacksRef.current.onOutlineGenerated)) return;\n\n const revision = analysisRevision.current;\n const doc = view.state.doc;\n const analysisLanguage = languageRef.current;\n const isCurrent = () => revision === analysisRevision.current\n && viewRef.current === view && view.state.doc === doc\n && languageRef.current === analysisLanguage;\n\n analysisTimer.current = setTimeout(() => {\n analysisTimer.current = null;\n if (!isCurrent()) return;\n const variables = callbacksRef.current.onVariablesCollected\n ? collectVariables(code, analysisLanguage) : undefined;\n const outline = callbacksRef.current.onOutlineGenerated\n ? generateOutline(code, analysisLanguage) : undefined;\n\n // A callback may synchronously change the document/language or unmount us.\n if (variables && isCurrent()) callbacksRef.current.onVariablesCollected?.(variables);\n if (outline && isCurrent()) callbacksRef.current.onOutlineGenerated?.(outline);\n }, delay);\n }, [cancelAnalysis]);\n\n // 跳转到指定行\n const jumpToLine = useCallback((line: number) => {\n if (viewRef.current) {\n try {\n const lineInfo = viewRef.current.state.doc.line(line);\n viewRef.current.dispatch({\n selection: { anchor: lineInfo.from, head: lineInfo.to },\n scrollIntoView: true,\n });\n viewRef.current.focus();\n } catch (error) {\n console.error('Failed to jump to line:', error);\n }\n }\n }, []);\n\n // 添加历史记录\n const addToHistory = useCallback((content: string, description?: string) => {\n // 如果是外部更新或正在恢复历史,不添加记录\n if (!enableHistory || isRestoringHistory.current || isExternalUpdate.current) {\n return;\n }\n\n const now = Date.now();\n const intervalMs = historySaveInterval * 10000; // 转换为毫秒\n const timeSinceLastSave = now - lastSaveTime.current;\n const timeCheckPassed = timeSinceLastSave >= intervalMs;\n\n // 按配置的间隔记录\n if (!timeCheckPassed) {\n // 时间未到,标记有变更,但不立即保存\n hasChanges.current = true;\n pendingContent.current = content;\n return;\n }\n\n // 时间检查已通过,现在检查内容是否真的发生变化\n if (content === lastSavedContent.current && !description) {\n // 内容没有变化,不保存\n hasChanges.current = false;\n return;\n }\n\n // 时间检查通过 + 内容有变化 → 保存!\n lastSaveTime.current = now;\n hasChanges.current = false;\n lastSavedContent.current = content; // 记录本次保存的内容\n\n setCodeHistory((prevHistory) => {\n // 如果当前不在最新位置,删除后面的历史\n const newHistory = currentHistoryIndex >= 0\n ? prevHistory.slice(0, currentHistoryIndex + 1)\n : prevHistory;\n\n const newEntry: HistoryEntry = {\n id: `${now}-${Math.random()}`,\n timestamp: new Date(now),\n content,\n description,\n };\n\n const updatedHistory = [...newHistory, newEntry];\n\n // 限制历史记录数量\n if (updatedHistory.length > historyLimit) {\n updatedHistory.shift();\n }\n\n const newIndex = updatedHistory.length - 1;\n setCurrentHistoryIndex(newIndex);\n\n // 延迟调用 onHistoryChange 避免在渲染期间更新父组件\n setTimeout(() => {\n if (onHistoryChange) {\n onHistoryChange(updatedHistory, newIndex);\n }\n }, 0);\n\n return updatedHistory;\n });\n }, [enableHistory, historyLimit, historySaveInterval, currentHistoryIndex, onHistoryChange]);\n\n const historyWriterRef = useRef(addToHistory);\n useLayoutEffect(() => {\n languageRef.current = language;\n callbacksRef.current = { onChange, onVariablesCollected, onOutlineGenerated };\n historyWriterRef.current = addToHistory;\n });\n\n // 恢复历史记录\n const restoreHistory = useCallback((index: number) => {\n if (index < 0 || index >= codeHistory.length) return;\n\n isRestoringHistory.current = true;\n const entry = codeHistory[index];\n\n if (viewRef.current) {\n viewRef.current.dispatch({\n changes: {\n from: 0,\n to: viewRef.current.state.doc.length,\n insert: entry.content,\n },\n });\n }\n\n // 清除当前版本之后的所有版本\n const newHistory = codeHistory.slice(0, index + 1);\n setCodeHistory(newHistory);\n\n // 回滚的版本成为最新版本\n const newIndex = newHistory.length - 1;\n setCurrentHistoryIndex(newIndex);\n\n // 延迟调用 onHistoryChange 避免在渲染期间更新父组件\n setTimeout(() => {\n if (onHistoryChange) {\n onHistoryChange(newHistory, newIndex);\n }\n }, 0);\n\n // 触发 onChange\n if (onChange) {\n onChange(entry.content);\n }\n\n // 延迟重置标志,确保不会立即添加到历史\n setTimeout(() => {\n isRestoringHistory.current = false;\n }, 100);\n }, [codeHistory, onChange, onHistoryChange]);\n\n // 暴露历史记录相关方法\n useImperativeHandle(ref, () => ({\n jumpToLine,\n getView: () => viewRef.current,\n getValue: () => viewRef.current?.state.doc.toString() || '',\n setValue: (newValue: string) => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n changes: {\n from: 0,\n to: viewRef.current.state.doc.length,\n insert: newValue,\n },\n });\n }\n },\n focus: () => viewRef.current?.focus(),\n getHistory: () => codeHistory,\n restoreHistory,\n clearHistory: () => {\n setCodeHistory([]);\n setCurrentHistoryIndex(-1);\n // 重置所有历史记录相关的内部状态\n lastSaveTime.current = 0;\n hasChanges.current = false;\n pendingContent.current = '';\n lastSavedContent.current = '';\n // 延迟调用 onHistoryChange 避免在渲染期间更新父组件\n setTimeout(() => {\n if (onHistoryChange) {\n onHistoryChange([], -1);\n }\n }, 0);\n },\n } as any), [jumpToLine, codeHistory, restoreHistory, onHistoryChange]);\n\n // 定时保存待处理的历史记录\n useEffect(() => {\n if (!enableHistory) return;\n\n const intervalMs = historySaveInterval * 10000; // 转换为毫秒\n\n const interval = setInterval(() => {\n if (hasChanges.current && pendingContent.current) {\n addToHistory(pendingContent.current);\n }\n }, intervalMs);\n\n return () => clearInterval(interval);\n }, [enableHistory, historySaveInterval, addToHistory]);\n\n // 初始化编辑器\n useEffect(() => {\n if (!editorRef.current) return;\n\n const updateListener = EditorView.updateListener.of((update) => {\n if (!update.docChanged) return;\n const newContent = update.state.doc.toString();\n documentText.current = newContent;\n // Schedule before notifying consumers so reentrant updates always win.\n scheduleAnalysis(newContent);\n try {\n if (!isExternalUpdate.current) historyWriterRef.current(newContent);\n } finally {\n isExternalUpdate.current = false;\n }\n callbacksRef.current.onChange?.(newContent);\n });\n\n const baseExtensions: Extension[] = [\n history(),\n drawSelection(),\n bracketMatching(),\n closeBrackets(),\n indentOnInput(),\n syntaxHighlighting(defaultHighlightStyle, { fallback: true }),\n languageCompartment.current.of(getLanguageExtension(language)),\n themeCompartment.current.of(createThemeExtension(theme)),\n highlightCompartment.current.of(createHighlightExtension(theme)),\n readOnlyCompartment.current.of(EditorState.readOnly.of(readOnly)),\n updateListener,\n keymap.of([\n ...closeBracketsKeymap,\n ...defaultKeymap,\n ...searchKeymap,\n ...historyKeymap,\n ...completionKeymap,\n ...lintKeymap,\n indentWithTab,\n ]),\n bracketMatchingStyle,\n lineHighlightStyle,\n jumpTargetHighlight,\n ];\n\n // 可选扩展\n if (showLineNumbers) {\n baseExtensions.push(lineNumbers(), foldGutter(), highlightActiveLineGutter());\n }\n\n if (shouldHighlightActiveLine) {\n baseExtensions.push(highlightActiveLine());\n }\n\n // 自动补全\n if (autocompletion) {\n const config: AutocompletionConfig = typeof autocompletion === 'object' ? autocompletion : {};\n baseExtensions.push(smartAutocompletion(language, config));\n }\n\n // 跳转到定义\n if (jumpToDefinitionConfig) {\n const config: JumpToDefinitionConfig = typeof jumpToDefinitionConfig === 'object'\n ? jumpToDefinitionConfig\n : {};\n baseExtensions.push(jumpToDefinition(jumpToLine, config));\n }\n\n // 占位符\n if (placeholder) {\n baseExtensions.push(\n EditorView.contentAttributes.of({ 'data-placeholder': placeholder })\n );\n }\n\n // 自定义扩展\n if (customExtensions.length > 0) {\n baseExtensions.push(...customExtensions);\n }\n\n const startState = EditorState.create({\n doc: value,\n extensions: baseExtensions,\n });\n\n const view = new EditorView({\n state: startState,\n parent: editorRef.current,\n });\n\n viewRef.current = view;\n documentText.current = view.state.doc.toString();\n\n // 添加初始内容到历史记录\n if (enableHistory && value) {\n addToHistory(value, 'Initial content');\n }\n\n return () => {\n cancelAnalysis();\n viewRef.current = null;\n view.destroy();\n };\n }, []); // 只在挂载时初始化\n\n // 更新值\n useEffect(() => {\n if (viewRef.current && value !== documentText.current) {\n isExternalUpdate.current = true; // 标记为外部更新\n viewRef.current.dispatch({\n changes: {\n from: 0,\n to: viewRef.current.state.doc.length,\n insert: value,\n },\n });\n // 注意:标志会在 updateListener 中被立即重置,不需要 setTimeout\n }\n }, [value]);\n\n // 更新语言\n useEffect(() => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n effects: languageCompartment.current.reconfigure(getLanguageExtension(language)),\n });\n }\n }, [language]);\n\n // Callback identity changes only update refs: inline callbacks must not restart\n // pending input analysis or create a callback -> render -> analysis loop.\n useEffect(() => {\n scheduleAnalysis(documentText.current, 0);\n return cancelAnalysis;\n }, [language, hasVariableListener, hasOutlineListener, scheduleAnalysis, cancelAnalysis]);\n\n // 更新主题\n useEffect(() => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n effects: [\n themeCompartment.current.reconfigure(createThemeExtension(theme)),\n highlightCompartment.current.reconfigure(createHighlightExtension(theme)),\n ],\n });\n }\n }, [theme]);\n\n // 更新只读状态\n useEffect(() => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n effects: readOnlyCompartment.current.reconfigure(EditorState.readOnly.of(readOnly)),\n });\n }\n }, [readOnly]);\n\n // 处理右键菜单\n const handleContextMenu = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n setContextMenuState({\n visible: true,\n x: e.clientX,\n y: e.clientY,\n });\n }, []);\n\n const closeContextMenu = useCallback(() => {\n setContextMenuState({ visible: false, x: 0, y: 0 });\n }, []);\n\n const handleMenuItemClick = useCallback(\n (item: any) => {\n if (viewRef.current && !item.disabled) {\n item.action(viewRef.current);\n }\n closeContextMenu();\n },\n [closeContextMenu]\n );\n\n // 点击其他地方关闭菜单\n useEffect(() => {\n if (contextMenuState.visible) {\n const handleClick = () => closeContextMenu();\n document.addEventListener('click', handleClick);\n return () => document.removeEventListener('click', handleClick);\n }\n }, [contextMenuState.visible, closeContextMenu]);\n\n const editorStyles: React.CSSProperties = {\n height,\n minHeight,\n maxHeight,\n overflow: 'auto',\n };\n\n const menuItems = contextMenu || defaultContextMenu;\n\n return (\n <div className={`code-editor-wrapper ${className}`}>\n <div\n ref={editorRef}\n onContextMenu={handleContextMenu}\n style={editorStyles}\n className=\"code-editor\"\n />\n\n {/* 上下文菜单 */}\n {contextMenuState.visible && (\n <div\n className=\"context-menu\"\n style={{\n position: 'fixed',\n top: contextMenuState.y,\n left: contextMenuState.x,\n zIndex: 1000,\n }}\n >\n <ul className=\"menu bg-base-200 rounded-box shadow-lg\">\n {menuItems.map((item, index) => {\n if (item.separator) {\n return <li key={index} className=\"menu-separator\" />;\n }\n return (\n <li key={index}>\n <a\n onClick={() => handleMenuItemClick(item)}\n className={item.disabled ? 'disabled' : ''}\n >\n {item.label}\n </a>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n\n <style>{`\n .code-editor-wrapper {\n position: relative;\n border: 1px solid var(--fallback-bc, oklch(var(--bc) / 0.2));\n border-radius: 0.5rem;\n overflow: hidden;\n }\n\n .code-editor .cm-editor {\n height: 100%;\n }\n\n .code-editor .cm-scroller {\n overflow: auto;\n font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;\n font-size: 14px;\n line-height: 1.5;\n }\n\n .code-editor .cm-content[data-placeholder]::before {\n content: attr(data-placeholder);\n color: var(--fallback-bc, oklch(var(--bc) / 0.4));\n position: absolute;\n pointer-events: none;\n }\n\n .context-menu {\n min-width: 150px;\n }\n\n .context-menu .menu-separator {\n height: 1px;\n background: var(--fallback-bc, oklch(var(--bc) / 0.2));\n margin: 0.25rem 0;\n }\n\n .context-menu .disabled {\n opacity: 0.5;\n pointer-events: none;\n }\n `}</style>\n </div>\n );\n});\n\nCodeEditor.displayName = 'CodeEditor';\n\nexport default CodeEditor;\n\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"MarkdownEditor.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/editors/MarkdownEditor.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback, useRef } from 'react';\nimport CodeEditor, { type CodeEditorProps, type CodeEditorHandle, type ContextMenuItem } from './CodeEditor';\nimport TableOfContentsPanel from '../panels/TableOfContentsPanel';\nimport FootnotePanel from '../panels/FootnotePanel';\nimport {\n markdownExtensions,\n extractMarkdownSections,\n extractFootnotes,\n MarkdownSection,\n FootnoteInfo,\n} from './markdownExtensions';\nimport { EditorView } from '@codemirror/view';\n\nexport interface MarkdownEditorProps extends Omit<CodeEditorProps, 'language' | 'extensions' | 'autocompletion' | 'contextMenu'> {\n showTableOfContents?: boolean;\n showFootnotes?: boolean;\n onSectionsChange?: (sections: MarkdownSection[]) => void;\n onFootnotesChange?: (footnotes: FootnoteInfo[]) => void;\n tableOfContentsPosition?: 'left' | 'right';\n customExtensions?: CodeEditorProps['extensions'];\n customContextMenu?: ContextMenuItem[];\n}\n\n// 表格格式化函数\nconst formatMarkdownTable = (tableText: string): string => {\n const lines = tableText.split('\\n').filter(line => line.trim());\n if (lines.length < 2) return tableText;\n\n // 解析表格\n const rows = lines.map(line => {\n return line.split('|')\n .map(cell => cell.trim())\n .filter((_, i, arr) => i > 0 && i < arr.length - 1); // 移除首尾空元素\n });\n\n // 计算每列的最大宽度\n const colWidths: number[] = [];\n rows.forEach(row => {\n row.forEach((cell, i) => {\n colWidths[i] = Math.max(colWidths[i] || 0, cell.length);\n });\n });\n\n // 格式化每一行\n const formattedRows = rows.map((row, rowIndex) => {\n const cells = row.map((cell, colIndex) => {\n // 对于分隔行,保持对齐标记\n if (rowIndex === 1 && cell.match(/^:?-+:?$/)) {\n const hasLeft = cell.startsWith(':');\n const hasRight = cell.endsWith(':');\n const width = colWidths[colIndex];\n\n if (hasLeft && hasRight) {\n return ':' + '-'.repeat(width - 2) + ':';\n } else if (hasLeft) {\n return ':' + '-'.repeat(width - 1);\n } else if (hasRight) {\n return '-'.repeat(width - 1) + ':';\n } else {\n return '-'.repeat(width);\n }\n }\n\n return cell.padEnd(colWidths[colIndex], ' ');\n });\n\n return '| ' + cells.join(' | ') + ' |';\n });\n\n return formattedRows.join('\\n');\n};\n\n// 检测是否在表格中\nconst isInTable = (view: EditorView, pos: number): { start: number; end: number; text: string } | null => {\n const line = view.state.doc.lineAt(pos);\n const lineText = line.text;\n\n if (!lineText.includes('|')) return null;\n\n // 向上查找表格开始\n let startLine = line.number;\n let currentLine = line.number - 1;\n while (currentLine >= 1) {\n const l = view.state.doc.line(currentLine);\n if (!l.text.includes('|')) break;\n startLine = currentLine;\n currentLine--;\n }\n\n // 向下查找表格结束\n let endLine = line.number;\n currentLine = line.number + 1;\n const totalLines = view.state.doc.lines;\n while (currentLine <= totalLines) {\n const l = view.state.doc.line(currentLine);\n if (!l.text.includes('|')) break;\n endLine = currentLine;\n currentLine++;\n }\n\n const startLineObj = view.state.doc.line(startLine);\n const endLineObj = view.state.doc.line(endLine);\n\n return {\n start: startLineObj.from,\n end: endLineObj.to,\n text: view.state.doc.sliceString(startLineObj.from, endLineObj.to),\n };\n};\n\nconst MarkdownEditor: React.FC<MarkdownEditorProps> = ({\n value = '',\n onChange,\n showTableOfContents = true,\n showFootnotes = true,\n onSectionsChange,\n onFootnotesChange,\n tableOfContentsPosition = 'right',\n customExtensions = [],\n customContextMenu = [],\n ...codeEditorProps\n}) => {\n const [sections, setSections] = useState<MarkdownSection[]>([]);\n const [footnotes, setFootnotes] = useState<FootnoteInfo[]>([]);\n const [currentLine, setCurrentLine] = useState(1);\n const editorRef = useRef<CodeEditorHandle>(null);\n const lastPropValue = useRef<string | null>(null);\n const lastAnalyzedValue = useRef<string | null>(null);\n\n const updateMetadata = useCallback((content: string) => {\n if (lastAnalyzedValue.current === content) return;\n lastAnalyzedValue.current = content;\n const newSections = extractMarkdownSections(content);\n const newFootnotes = extractFootnotes(content);\n setSections(newSections);\n setFootnotes(newFootnotes);\n onSectionsChange?.(newSections);\n onFootnotesChange?.(newFootnotes);\n }, [onSectionsChange, onFootnotesChange]);\n\n // The editor can change without a parent echoing value; a new callback alone\n // must not re-analyze the stale value prop and overwrite the live sidebar.\n useEffect(() => {\n if (lastPropValue.current !== value) {\n lastPropValue.current = value;\n updateMetadata(value);\n }\n }, [value, updateMetadata]);\n\n const handleChange = useCallback((content: string) => {\n updateMetadata(content);\n onChange?.(content);\n }, [updateMetadata, onChange]);\n\n const jumpToLine = useCallback((line: number) => {\n editorRef.current?.jumpToLine(line);\n }, []);\n\n // Markdown 专属上下文菜单\n const markdownContextMenu: ContextMenuItem[] = [\n {\n label: '格式化表格',\n action: (view) => {\n const selection = view.state.selection.main;\n const tableInfo = isInTable(view, selection.from);\n\n if (tableInfo) {\n const formatted = formatMarkdownTable(tableInfo.text);\n view.dispatch({\n changes: {\n from: tableInfo.start,\n to: tableInfo.end,\n insert: formatted,\n },\n });\n } else {\n alert('请将光标放在表格中');\n }\n },\n },\n { label: '', action: () => { }, separator: true },\n {\n label: '剪切',\n action: (view) => {\n const selection = view.state.selection.main;\n const text = view.state.sliceDoc(selection.from, selection.to);\n navigator.clipboard.writeText(text);\n view.dispatch({\n changes: { from: selection.from, to: selection.to, insert: '' },\n });\n },\n },\n {\n label: '复制',\n action: (view) => {\n const selection = view.state.selection.main;\n const text = view.state.sliceDoc(selection.from, selection.to);\n navigator.clipboard.writeText(text);\n },\n },\n {\n label: '粘贴',\n action: async (view) => {\n const text = await navigator.clipboard.readText();\n const selection = view.state.selection.main;\n view.dispatch({\n changes: { from: selection.from, to: selection.to, insert: text },\n });\n },\n },\n { label: '', action: () => { }, separator: true },\n {\n label: '全选',\n action: (view) => {\n view.dispatch({\n selection: { anchor: 0, head: view.state.doc.length },\n });\n },\n },\n ...customContextMenu,\n ];\n\n // 合并扩展\n const allExtensions = [...markdownExtensions(), ...customExtensions];\n\n // 侧边栏内容\n const renderSidebar = () => {\n // 根据主题决定侧边栏的样式类\n const darkThemes = ['dark', 'retro', 'cyberpunk', 'matrix'];\n const sidebarThemeClass =\n darkThemes.includes(codeEditorProps.theme || 'light')\n ? 'markdown-sidebar-dark'\n : 'markdown-sidebar-light';\n\n return (\n <div className={`markdown-sidebar space-y-4 ${sidebarThemeClass}`} style={{ width: '320px' }}>\n {showTableOfContents && (\n <TableOfContentsPanel\n sections={sections}\n onSectionClick={jumpToLine}\n currentLine={currentLine}\n theme={codeEditorProps.theme}\n />\n )}\n {showFootnotes && footnotes.length > 0 && (\n <FootnotePanel\n footnotes={footnotes}\n onFootnoteClick={jumpToLine}\n onJumpToDefinition={(id, line) => {\n console.log(`Jumping to definition of footnote ${id} at line ${line}`);\n jumpToLine(line);\n }}\n onJumpToReference={(id, line) => {\n console.log(`Jumping to reference of footnote ${id} at line ${line}`);\n jumpToLine(line);\n }}\n theme={codeEditorProps.theme}\n />\n )}\n </div>\n );\n };\n\n return (\n <div className=\"markdown-editor-wrapper flex gap-4\">\n {/* 左侧边栏 */}\n {tableOfContentsPosition === 'left' && (showTableOfContents || showFootnotes) && renderSidebar()}\n\n {/* 编辑器 */}\n <div className=\"markdown-editor-main flex-1\">\n <CodeEditor\n {...codeEditorProps}\n ref={editorRef}\n value={value}\n onChange={handleChange}\n language=\"markdown\"\n autocompletion={false}\n extensions={allExtensions}\n contextMenu={markdownContextMenu}\n />\n </div>\n\n {/* 右侧边栏 */}\n {tableOfContentsPosition === 'right' && (showTableOfContents || showFootnotes) && renderSidebar()}\n\n {/* 侧边栏主题样式 */}\n <style>{`\n .markdown-sidebar-light {\n color: #000000;\n }\n .markdown-sidebar-dark {\n color: #d4d4d4;\n }\n .markdown-sidebar-dark .card,\n .markdown-sidebar-dark .toc-panel,\n .markdown-sidebar-dark .footnote-panel,\n .markdown-sidebar-dark .outline-panel,\n .markdown-sidebar-dark .variable-panel {\n background-color: #1e1e1e !important;\n border-color: #3e3e42 !important;\n color: #d4d4d4 !important;\n }\n .markdown-sidebar-dark .border-base-300 {\n border-color: #3e3e42 !important;\n }\n .markdown-sidebar-dark input,\n .markdown-sidebar-dark .input {\n background-color: #2d2d2d !important;\n border-color: #3e3e42 !important;\n color: #d4d4d4 !important;\n }\n .markdown-sidebar-dark button,\n .markdown-sidebar-dark .btn {\n color: #d4d4d4 !important;\n }\n .markdown-sidebar-dark .hover\\\\:bg-base-200:hover,\n .markdown-sidebar-dark .toc-item:hover,\n .markdown-sidebar-dark .outline-item:hover,\n .markdown-sidebar-dark .variable-item:hover,\n .markdown-sidebar-dark .footnote-item:hover {\n background-color: #2d2d2d !important;\n }\n .markdown-sidebar-dark .bg-primary\\\\/20 {\n background-color: rgba(96, 165, 250, 0.2) !important;\n }\n .markdown-sidebar-dark .bg-base-200 {\n background-color: #2d2d2d !important;\n }\n .markdown-sidebar-dark .bg-warning\\\\/10 {\n background-color: rgba(251, 191, 36, 0.1) !important;\n }\n .markdown-sidebar-dark .border-warning\\\\/30 {\n border-color: rgba(251, 191, 36, 0.3) !important;\n }\n .markdown-sidebar-dark .text-warning {\n color: #fbbf24 !important;\n }\n `}</style>\n </div>\n );\n};\n\nexport default MarkdownEditor;\n"],"mappings":"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"}
1
+ {"version":3,"file":"MarkdownEditor.js","names":["CodeEditor","TableOfContentsPanel","FootnotePanel","formatMarkdownTable","lines","tableText","line","rows","cell","i","arr","colWidths","row","rowIndex","hasLeft","hasRight","width","colIndex","isInTable","view","pos","startLine","currentLine","endLine","totalLines","startLineObj","endLineObj","MarkdownEditor","codeEditorProps","sections","setSections","useState","footnotes","setFootnotes","setCurrentLine","editorRef","useRef","lastPropValue","lastAnalyzedValue","updateMetadata","useCallback","content","newSections","extractMarkdownSections","newFootnotes","extractFootnotes","onSectionsChange","onFootnotesChange","value","handleChange","onChange","jumpToLine","markdownContextMenu","selection","tableInfo","formatted","text","customContextMenu","allExtensions","markdownExtensions","customExtensions","renderSidebar","sidebarThemeClass","showTableOfContents","showFootnotes","id","tableOfContentsPosition"],"sources":["../../../../../src/components/pro/CodeEditor/editors/MarkdownEditor.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback, useRef } from 'react';\nimport CodeEditor, { type CodeEditorProps, type CodeEditorHandle, type ContextMenuItem } from './CodeEditor';\nimport TableOfContentsPanel from '../panels/TableOfContentsPanel';\nimport FootnotePanel from '../panels/FootnotePanel';\nimport {\n markdownExtensions,\n extractMarkdownSections,\n extractFootnotes,\n MarkdownSection,\n FootnoteInfo,\n} from './markdownExtensions';\nimport { EditorView } from '@codemirror/view';\n\nexport interface MarkdownEditorProps extends Omit<CodeEditorProps, 'language' | 'extensions' | 'autocompletion' | 'contextMenu'> {\n showTableOfContents?: boolean;\n showFootnotes?: boolean;\n onSectionsChange?: (sections: MarkdownSection[]) => void;\n onFootnotesChange?: (footnotes: FootnoteInfo[]) => void;\n tableOfContentsPosition?: 'left' | 'right';\n customExtensions?: CodeEditorProps['extensions'];\n customContextMenu?: ContextMenuItem[];\n}\n\n// 表格格式化函数\nconst formatMarkdownTable = (tableText: string): string => {\n const lines = tableText.split('\\n').filter(line => line.trim());\n if (lines.length < 2) return tableText;\n\n // 解析表格\n const rows = lines.map(line => {\n return line.split('|')\n .map(cell => cell.trim())\n .filter((_, i, arr) => i > 0 && i < arr.length - 1); // 移除首尾空元素\n });\n\n // 计算每列的最大宽度\n const colWidths: number[] = [];\n rows.forEach(row => {\n row.forEach((cell, i) => {\n colWidths[i] = Math.max(colWidths[i] || 0, cell.length);\n });\n });\n\n // 格式化每一行\n const formattedRows = rows.map((row, rowIndex) => {\n const cells = row.map((cell, colIndex) => {\n // 对于分隔行,保持对齐标记\n if (rowIndex === 1 && cell.match(/^:?-+:?$/)) {\n const hasLeft = cell.startsWith(':');\n const hasRight = cell.endsWith(':');\n const width = colWidths[colIndex];\n\n if (hasLeft && hasRight) {\n return ':' + '-'.repeat(width - 2) + ':';\n } else if (hasLeft) {\n return ':' + '-'.repeat(width - 1);\n } else if (hasRight) {\n return '-'.repeat(width - 1) + ':';\n } else {\n return '-'.repeat(width);\n }\n }\n\n return cell.padEnd(colWidths[colIndex], ' ');\n });\n\n return '| ' + cells.join(' | ') + ' |';\n });\n\n return formattedRows.join('\\n');\n};\n\n// 检测是否在表格中\nconst isInTable = (view: EditorView, pos: number): { start: number; end: number; text: string } | null => {\n const line = view.state.doc.lineAt(pos);\n const lineText = line.text;\n\n if (!lineText.includes('|')) return null;\n\n // 向上查找表格开始\n let startLine = line.number;\n let currentLine = line.number - 1;\n while (currentLine >= 1) {\n const l = view.state.doc.line(currentLine);\n if (!l.text.includes('|')) break;\n startLine = currentLine;\n currentLine--;\n }\n\n // 向下查找表格结束\n let endLine = line.number;\n currentLine = line.number + 1;\n const totalLines = view.state.doc.lines;\n while (currentLine <= totalLines) {\n const l = view.state.doc.line(currentLine);\n if (!l.text.includes('|')) break;\n endLine = currentLine;\n currentLine++;\n }\n\n const startLineObj = view.state.doc.line(startLine);\n const endLineObj = view.state.doc.line(endLine);\n\n return {\n start: startLineObj.from,\n end: endLineObj.to,\n text: view.state.doc.sliceString(startLineObj.from, endLineObj.to),\n };\n};\n\nconst MarkdownEditor: React.FC<MarkdownEditorProps> = ({\n value = '',\n onChange,\n showTableOfContents = true,\n showFootnotes = true,\n onSectionsChange,\n onFootnotesChange,\n tableOfContentsPosition = 'right',\n customExtensions = [],\n customContextMenu = [],\n ...codeEditorProps\n}) => {\n const [sections, setSections] = useState<MarkdownSection[]>([]);\n const [footnotes, setFootnotes] = useState<FootnoteInfo[]>([]);\n const [currentLine, setCurrentLine] = useState(1);\n const editorRef = useRef<CodeEditorHandle>(null);\n const lastPropValue = useRef<string | null>(null);\n const lastAnalyzedValue = useRef<string | null>(null);\n\n const updateMetadata = useCallback((content: string) => {\n if (lastAnalyzedValue.current === content) return;\n lastAnalyzedValue.current = content;\n const newSections = extractMarkdownSections(content);\n const newFootnotes = extractFootnotes(content);\n setSections(newSections);\n setFootnotes(newFootnotes);\n onSectionsChange?.(newSections);\n onFootnotesChange?.(newFootnotes);\n }, [onSectionsChange, onFootnotesChange]);\n\n // The editor can change without a parent echoing value; a new callback alone\n // must not re-analyze the stale value prop and overwrite the live sidebar.\n useEffect(() => {\n if (lastPropValue.current !== value) {\n lastPropValue.current = value;\n updateMetadata(value);\n }\n }, [value, updateMetadata]);\n\n const handleChange = useCallback((content: string) => {\n updateMetadata(content);\n onChange?.(content);\n }, [updateMetadata, onChange]);\n\n const jumpToLine = useCallback((line: number) => {\n editorRef.current?.jumpToLine(line);\n }, []);\n\n // Markdown 专属上下文菜单\n const markdownContextMenu: ContextMenuItem[] = [\n {\n label: '格式化表格',\n action: (view) => {\n const selection = view.state.selection.main;\n const tableInfo = isInTable(view, selection.from);\n\n if (tableInfo) {\n const formatted = formatMarkdownTable(tableInfo.text);\n view.dispatch({\n changes: {\n from: tableInfo.start,\n to: tableInfo.end,\n insert: formatted,\n },\n });\n } else {\n alert('请将光标放在表格中');\n }\n },\n },\n { label: '', action: () => { }, separator: true },\n {\n label: '剪切',\n action: (view) => {\n const selection = view.state.selection.main;\n const text = view.state.sliceDoc(selection.from, selection.to);\n navigator.clipboard.writeText(text);\n view.dispatch({\n changes: { from: selection.from, to: selection.to, insert: '' },\n });\n },\n },\n {\n label: '复制',\n action: (view) => {\n const selection = view.state.selection.main;\n const text = view.state.sliceDoc(selection.from, selection.to);\n navigator.clipboard.writeText(text);\n },\n },\n {\n label: '粘贴',\n action: async (view) => {\n const text = await navigator.clipboard.readText();\n const selection = view.state.selection.main;\n view.dispatch({\n changes: { from: selection.from, to: selection.to, insert: text },\n });\n },\n },\n { label: '', action: () => { }, separator: true },\n {\n label: '全选',\n action: (view) => {\n view.dispatch({\n selection: { anchor: 0, head: view.state.doc.length },\n });\n },\n },\n ...customContextMenu,\n ];\n\n // 合并扩展\n const allExtensions = [...markdownExtensions(), ...customExtensions];\n\n // 侧边栏内容\n const renderSidebar = () => {\n // 根据主题决定侧边栏的样式类\n const darkThemes = ['dark', 'retro', 'cyberpunk', 'matrix'];\n const sidebarThemeClass =\n darkThemes.includes(codeEditorProps.theme || 'light')\n ? 'markdown-sidebar-dark'\n : 'markdown-sidebar-light';\n\n return (\n <div className={`markdown-sidebar space-y-4 ${sidebarThemeClass}`} style={{ width: '320px' }}>\n {showTableOfContents && (\n <TableOfContentsPanel\n sections={sections}\n onSectionClick={jumpToLine}\n currentLine={currentLine}\n theme={codeEditorProps.theme}\n />\n )}\n {showFootnotes && footnotes.length > 0 && (\n <FootnotePanel\n footnotes={footnotes}\n onFootnoteClick={jumpToLine}\n onJumpToDefinition={(id, line) => {\n console.log(`Jumping to definition of footnote ${id} at line ${line}`);\n jumpToLine(line);\n }}\n onJumpToReference={(id, line) => {\n console.log(`Jumping to reference of footnote ${id} at line ${line}`);\n jumpToLine(line);\n }}\n theme={codeEditorProps.theme}\n />\n )}\n </div>\n );\n };\n\n return (\n <div className=\"markdown-editor-wrapper flex gap-4\">\n {/* 左侧边栏 */}\n {tableOfContentsPosition === 'left' && (showTableOfContents || showFootnotes) && renderSidebar()}\n\n {/* 编辑器 */}\n <div className=\"markdown-editor-main flex-1\">\n <CodeEditor\n {...codeEditorProps}\n ref={editorRef}\n value={value}\n onChange={handleChange}\n language=\"markdown\"\n autocompletion={false}\n extensions={allExtensions}\n contextMenu={markdownContextMenu}\n />\n </div>\n\n {/* 右侧边栏 */}\n {tableOfContentsPosition === 'right' && (showTableOfContents || showFootnotes) && renderSidebar()}\n\n {/* 侧边栏主题样式 */}\n <style>{`\n .markdown-sidebar-light {\n color: #000000;\n }\n .markdown-sidebar-dark {\n color: #d4d4d4;\n }\n .markdown-sidebar-dark .card,\n .markdown-sidebar-dark .toc-panel,\n .markdown-sidebar-dark .footnote-panel,\n .markdown-sidebar-dark .outline-panel,\n .markdown-sidebar-dark .variable-panel {\n background-color: #1e1e1e !important;\n border-color: #3e3e42 !important;\n color: #d4d4d4 !important;\n }\n .markdown-sidebar-dark .border-base-300 {\n border-color: #3e3e42 !important;\n }\n .markdown-sidebar-dark input,\n .markdown-sidebar-dark .input {\n background-color: #2d2d2d !important;\n border-color: #3e3e42 !important;\n color: #d4d4d4 !important;\n }\n .markdown-sidebar-dark button,\n .markdown-sidebar-dark .btn {\n color: #d4d4d4 !important;\n }\n .markdown-sidebar-dark .hover\\\\:bg-base-200:hover,\n .markdown-sidebar-dark .toc-item:hover,\n .markdown-sidebar-dark .outline-item:hover,\n .markdown-sidebar-dark .variable-item:hover,\n .markdown-sidebar-dark .footnote-item:hover {\n background-color: #2d2d2d !important;\n }\n .markdown-sidebar-dark .bg-primary\\\\/20 {\n background-color: rgba(96, 165, 250, 0.2) !important;\n }\n .markdown-sidebar-dark .bg-base-200 {\n background-color: #2d2d2d !important;\n }\n .markdown-sidebar-dark .bg-warning\\\\/10 {\n background-color: rgba(251, 191, 36, 0.1) !important;\n }\n .markdown-sidebar-dark .border-warning\\\\/30 {\n border-color: rgba(251, 191, 36, 0.3) !important;\n }\n .markdown-sidebar-dark .text-warning {\n color: #fbbf24 !important;\n }\n `}</style>\n </div>\n );\n};\n\nexport default MarkdownEditor;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"markdownExtensions.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/editors/markdownExtensions.ts"],"sourcesContent":["import { Extension } from '@codemirror/state';\nimport { EditorView, Decoration, DecorationSet, ViewPlugin, ViewUpdate } from '@codemirror/view';\nimport { syntaxTree } from '@codemirror/language';\nimport { CompletionContext, CompletionResult, autocompletion } from '@codemirror/autocomplete';\nimport { LanguageSupport } from '@codemirror/language';\nimport { javascript } from '@codemirror/lang-javascript';\nimport { python } from '@codemirror/lang-python';\nimport { html } from '@codemirror/lang-html';\nimport { css } from '@codemirror/lang-css';\nimport { json } from '@codemirror/lang-json';\n\n// Markdown 章节信息\nexport interface MarkdownSection {\n level: number;\n title: string;\n line: number;\n id: string;\n}\n\n// 脚注信息\nexport interface FootnoteInfo {\n id: string;\n line: number; // 第一次引用的行号\n definitionLine?: number; // 定义的行号\n referenceLines?: number[]; // 所有引用的行号列表\n}\n\n// 获取代码块语言支持\nconst getCodeBlockLanguage = (lang: string): LanguageSupport | null => {\n switch (lang.toLowerCase()) {\n case 'javascript':\n case 'js':\n case 'jsx':\n return javascript({ jsx: true });\n case 'typescript':\n case 'ts':\n case 'tsx':\n return javascript({ jsx: true, typescript: true });\n case 'python':\n case 'py':\n return python();\n case 'html':\n return html();\n case 'css':\n return css();\n case 'json':\n return json();\n default:\n return null;\n }\n};\n\n// Mermaid/KaTeX 块高亮 + 代码块语法高亮\nconst codeBlockHighlight = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n\n constructor(view: EditorView) {\n this.decorations = this.buildDecorations(view);\n }\n\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged) {\n this.decorations = this.buildDecorations(update.view);\n }\n }\n\n buildDecorations(view: EditorView): DecorationSet {\n const decorations = [];\n const text = view.state.doc.toString();\n const lines = text.split('\\n');\n\n let inCodeBlock = false;\n let blockType: 'mermaid' | 'katex' | 'math' | 'code' | null = null;\n let blockLang: string = '';\n let blockStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const lineStart = view.state.doc.line(i + 1).from;\n\n // 检测代码块开始\n const codeBlockStart = line.match(/^```(\\w+)/);\n if (codeBlockStart && !inCodeBlock) {\n inCodeBlock = true;\n const lang = codeBlockStart[1];\n\n if (lang === 'mermaid') {\n blockType = 'mermaid';\n } else if (lang === 'math' || lang === 'katex') {\n blockType = 'katex';\n } else {\n blockType = 'code';\n blockLang = lang;\n }\n\n blockStart = lineStart;\n\n // 高亮代码块标记\n const mark = Decoration.mark({\n class: `cm-markdown-codeblock-marker${blockType === 'mermaid' ? ' cm-markdown-mermaid-marker' : blockType === 'katex' ? ' cm-markdown-katex-marker' : ' cm-markdown-code-marker'}`,\n });\n decorations.push(mark.range(lineStart, lineStart + line.length));\n }\n // 检测代码块结束\n else if (inCodeBlock && line.match(/^```\\s*$/)) {\n inCodeBlock = false;\n\n // 高亮代码块标记\n const mark = Decoration.mark({\n class: 'cm-markdown-codeblock-marker',\n });\n decorations.push(mark.range(lineStart, lineStart + line.length));\n\n blockType = null;\n blockLang = '';\n }\n // 代码块内容高亮\n else if (inCodeBlock && blockType) {\n const className = blockType === 'mermaid'\n ? 'cm-markdown-codeblock-content cm-markdown-mermaid-content'\n : blockType === 'katex'\n ? 'cm-markdown-codeblock-content cm-markdown-katex-content'\n : `cm-markdown-codeblock-content cm-markdown-code-content cm-code-${blockLang}`;\n\n const mark = Decoration.mark({\n class: className,\n });\n decorations.push(mark.range(lineStart, lineStart + line.length));\n }\n\n // 行内 KaTeX 高亮 $...$\n if (!inCodeBlock) {\n const inlineKatexRegex = /\\$([^$]+)\\$/g;\n let match;\n while ((match = inlineKatexRegex.exec(line)) !== null) {\n const from = lineStart + match.index;\n const to = from + match[0].length;\n const mark = Decoration.mark({\n class: 'cm-markdown-inline-katex',\n });\n decorations.push(mark.range(from, to));\n }\n\n // 块级 KaTeX 高亮 $$...$$\n const blockKatexRegex = /\\$\\$([^$]+)\\$\\$/g;\n while ((match = blockKatexRegex.exec(line)) !== null) {\n const from = lineStart + match.index;\n const to = from + match[0].length;\n const mark = Decoration.mark({\n class: 'cm-markdown-block-katex',\n });\n decorations.push(mark.range(from, to));\n }\n }\n }\n\n // 按位置排序装饰,避免 CodeMirror 错误\n decorations.sort((a, b) => a.from - b.from);\n\n return Decoration.set(decorations);\n }\n },\n {\n decorations: (v) => v.decorations,\n }\n);\n\n// Markdown 表格高亮\nconst tableHighlight = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n\n constructor(view: EditorView) {\n this.decorations = this.buildDecorations(view);\n }\n\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged) {\n this.decorations = this.buildDecorations(update.view);\n }\n }\n\n buildDecorations(view: EditorView): DecorationSet {\n const decorations = [];\n const text = view.state.doc.toString();\n const lines = text.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const lineStart = view.state.doc.line(i + 1).from;\n\n // 检测表格行 (包含 |)\n if (line.includes('|') && line.trim().startsWith('|')) {\n // 不要添加整行的装饰,只高亮管道符\n // 这样可以避免与管道符装饰重叠\n\n // 高亮表格分隔符 |\n const pipeRegex = /\\|/g;\n let match;\n while ((match = pipeRegex.exec(line)) !== null) {\n const from = lineStart + match.index;\n const to = from + 1;\n const pipeMark = Decoration.mark({\n class: 'cm-markdown-table-pipe',\n });\n decorations.push(pipeMark.range(from, to));\n }\n }\n\n // 检测表格分隔行 |---|---|\n if (line.match(/^\\|?\\s*:?-+:?\\s*\\|/)) {\n const mark = Decoration.mark({\n class: 'cm-markdown-table-separator',\n });\n decorations.push(mark.range(lineStart, lineStart + line.length));\n }\n }\n\n // 按位置排序装饰,避免 CodeMirror 错误\n decorations.sort((a, b) => a.from - b.from);\n\n return Decoration.set(decorations);\n }\n },\n {\n decorations: (v) => v.decorations,\n }\n);\n\n// 脚注点击跳转处理\nconst footnoteClickHandler = EditorView.domEventHandlers({\n mousedown: (event, view) => {\n const target = event.target as HTMLElement;\n const pos = view.posAtCoords({ x: event.clientX, y: event.clientY });\n\n if (pos === null) return false;\n\n const line = view.state.doc.lineAt(pos);\n const lineText = line.text;\n const clickOffset = pos - line.from;\n\n // 检查是否点击了脚注引用 [^id]\n const refRegex = /\\[\\^(\\w+)\\]/g;\n let match;\n while ((match = refRegex.exec(lineText)) !== null) {\n const matchStart = match.index;\n const matchEnd = matchStart + match[0].length;\n\n if (clickOffset >= matchStart && clickOffset <= matchEnd) {\n const footnoteId = match[1];\n\n // 查找脚注定义\n const text = view.state.doc.toString();\n const lines = text.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const defMatch = lines[i].match(/^\\[\\^(\\w+)\\]:\\s*(.+)$/);\n if (defMatch && defMatch[1] === footnoteId) {\n // 找到定义,跳转到该行\n const targetLine = view.state.doc.line(i + 1);\n view.dispatch({\n selection: { anchor: targetLine.from },\n effects: EditorView.scrollIntoView(targetLine.from, { y: 'center' })\n });\n\n event.preventDefault();\n return true;\n }\n }\n }\n }\n\n // 检查是否点击了脚注定义 [^id]:\n const defMatch = lineText.match(/^\\[\\^(\\w+)\\]:/);\n if (defMatch) {\n const matchEnd = defMatch[0].length;\n\n if (clickOffset <= matchEnd) {\n const footnoteId = defMatch[1];\n\n // 查找第一个引用\n const text = view.state.doc.toString();\n const lines = text.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const refRegex = new RegExp(`\\\\[\\\\^${footnoteId}\\\\](?!:)`, 'g');\n if (refRegex.test(lines[i])) {\n // 找到引用,跳转到该行\n const targetLine = view.state.doc.line(i + 1);\n view.dispatch({\n selection: { anchor: targetLine.from },\n effects: EditorView.scrollIntoView(targetLine.from, { y: 'center' })\n });\n\n event.preventDefault();\n return true;\n }\n }\n }\n }\n\n return false;\n }\n});\n\n// 脚注样式装饰 - 让脚注看起来可点击\nconst footnoteDecoration = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n\n constructor(view: EditorView) {\n this.decorations = this.buildDecorations(view);\n }\n\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged) {\n this.decorations = this.buildDecorations(update.view);\n }\n }\n\n buildDecorations(view: EditorView): DecorationSet {\n const decorations = [];\n const text = view.state.doc.toString();\n const lines = text.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const lineStart = view.state.doc.line(i + 1).from;\n\n // 脚注引用 [^id]\n const refRegex = /\\[\\^(\\w+)\\]/g;\n let match;\n while ((match = refRegex.exec(line)) !== null) {\n const from = lineStart + match.index;\n const to = from + match[0].length;\n const mark = Decoration.mark({\n class: 'cm-markdown-footnote-ref',\n attributes: { style: 'cursor: pointer; text-decoration: underline; text-decoration-style: dotted;' }\n });\n decorations.push(mark.range(from, to));\n }\n\n // 脚注定义 [^id]:\n const defMatch = line.match(/^\\[\\^(\\w+)\\]:/);\n if (defMatch) {\n const from = lineStart;\n const to = from + defMatch[0].length;\n const mark = Decoration.mark({\n class: 'cm-markdown-footnote-def',\n attributes: { style: 'cursor: pointer; font-weight: bold;' }\n });\n decorations.push(mark.range(from, to));\n }\n }\n\n // 按位置排序装饰,避免 CodeMirror 错误\n decorations.sort((a, b) => a.from - b.from);\n\n return Decoration.set(decorations);\n }\n },\n {\n decorations: (v) => v.decorations,\n }\n);\n\n// 提取 Markdown 章节\nexport const extractMarkdownSections = (code: string): MarkdownSection[] => {\n const sections: MarkdownSection[] = [];\n const lines = code.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const match = line.match(/^(#{1,6})\\s+(.+)$/);\n\n if (match) {\n const level = match[1].length;\n const title = match[2].trim();\n const id = title\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-');\n\n sections.push({\n level,\n title,\n line: i + 1,\n id,\n });\n }\n }\n\n return sections;\n};\n\n// 提取脚注\nexport const extractFootnotes = (code: string): FootnoteInfo[] => {\n const footnotes: FootnoteInfo[] = [];\n const lines = code.split('\\n');\n const footnoteMap = new Map<string, FootnoteInfo>();\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // 脚注引用 [^1]\n const refRegex = /\\[\\^(\\w+)\\]/g;\n let match;\n while ((match = refRegex.exec(line)) !== null) {\n const id = match[1];\n const existing = footnoteMap.get(id);\n if (existing) {\n // 已存在,添加到引用列表\n if (!existing.referenceLines) {\n existing.referenceLines = [existing.line];\n }\n existing.referenceLines.push(i + 1);\n } else {\n // 首次出现\n footnoteMap.set(id, {\n id,\n line: i + 1,\n referenceLines: [i + 1],\n });\n }\n }\n\n // 脚注定义 [^1]: ...\n const defMatch = line.match(/^\\[\\^(\\w+)\\]:\\s*(.+)$/);\n if (defMatch) {\n const id = defMatch[1];\n const existing = footnoteMap.get(id);\n if (existing) {\n existing.definitionLine = i + 1;\n } else {\n footnoteMap.set(id, {\n id,\n line: i + 1,\n definitionLine: i + 1,\n referenceLines: [],\n });\n }\n }\n }\n\n return Array.from(footnoteMap.values());\n};\n\n// Markdown 智能补全 - 改进版,支持更多触发方式\nexport const markdownAutocompletion = () => {\n return autocompletion({\n override: [\n (context: CompletionContext): CompletionResult | null => {\n const word = context.matchBefore(/\\S*/);\n if (!word || (word.from === word.to && !context.explicit)) {\n return null;\n }\n\n const options = [];\n const wordText = word.text.toLowerCase();\n\n // 获取当前行的文本,用于更好的上下文判断\n const line = context.state.doc.lineAt(context.pos);\n const lineText = line.text;\n const cursorPosInLine = context.pos - line.from;\n\n // 检查是否在行首输入特殊字符\n const isLineStart = lineText.trim() === wordText || cursorPosInLine <= 2;\n\n // Markdown 基础语法\n const basicSnippets = [\n { label: '#', detail: 'Heading 1', apply: '# ${title}', type: 'snippet', boost: 10 },\n { label: '##', detail: 'Heading 2', apply: '## ${title}', type: 'snippet', boost: 10 },\n { label: '###', detail: 'Heading 3', apply: '### ${title}', type: 'snippet', boost: 10 },\n { label: '####', detail: 'Heading 4', apply: '#### ${title}', type: 'snippet', boost: 10 },\n { label: '#####', detail: 'Heading 5', apply: '##### ${title}', type: 'snippet', boost: 10 },\n { label: '######', detail: 'Heading 6', apply: '###### ${title}', type: 'snippet', boost: 10 },\n { label: '-', detail: 'Unordered list', apply: '- ${item}', type: 'snippet', boost: 10 },\n { label: '*', detail: 'Unordered list', apply: '* ${item}', type: 'snippet', boost: 10 },\n { label: '1.', detail: 'Ordered list', apply: '1. ${item}', type: 'snippet', boost: 10 },\n { label: 'h1', detail: '# Heading 1', apply: '# ${title}', type: 'snippet' },\n { label: 'h2', detail: '## Heading 2', apply: '## ${title}', type: 'snippet' },\n { label: 'h3', detail: '### Heading 3', apply: '### ${title}', type: 'snippet' },\n { label: 'bold', detail: '**bold**', apply: '**${text}**', type: 'snippet' },\n { label: 'italic', detail: '*italic*', apply: '*${text}*', type: 'snippet' },\n { label: 'code', detail: '`code`', apply: '`${code}`', type: 'snippet' },\n { label: 'link', detail: '[text](url)', apply: '[${text}](${url})', type: 'snippet' },\n { label: 'image', detail: '![alt](url)', apply: '![${alt}](${url})', type: 'snippet' },\n { label: 'quote', detail: '> quote', apply: '> ${text}', type: 'snippet' },\n { label: 'ul', detail: '- item', apply: '- ${item}', type: 'snippet' },\n { label: 'ol', detail: '1. item', apply: '1. ${item}', type: 'snippet' },\n { label: 'task', detail: '- [ ] task', apply: '- [ ] ${task}', type: 'snippet' },\n { label: 'hr', detail: '---', apply: '---', type: 'snippet' },\n ];\n\n // Mermaid 图表 - 支持通过图表类型触发\n const mermaidSnippets = [\n {\n label: 'mermaid',\n detail: 'Mermaid diagram',\n apply: '```mermaid\\ngraph TD\\n A[${Start}] --> B[${End}]\\n```',\n type: 'snippet',\n },\n {\n label: 'flowchart',\n detail: 'Mermaid flowchart',\n apply: '```mermaid\\nflowchart LR\\n A[${Start}] --> B{${Decision}}\\n B -->|Yes| C[${Option 1}]\\n B -->|No| D[${Option 2}]\\n```',\n type: 'snippet',\n boost: 5,\n },\n {\n label: 'sequence',\n detail: 'Mermaid sequence diagram',\n apply: '```mermaid\\nsequenceDiagram\\n participant A as ${Alice}\\n participant B as ${Bob}\\n A->>B: ${Hello Bob}\\n B->>A: ${Hello Alice}\\n```',\n type: 'snippet',\n boost: 5,\n },\n {\n label: 'gantt',\n detail: 'Mermaid Gantt chart',\n apply: '```mermaid\\ngantt\\n title ${Project Timeline}\\n dateFormat YYYY-MM-DD\\n section ${Phase 1}\\n ${Task 1} :a1, 2024-01-01, 30d\\n ${Task 2} :after a1, 20d\\n```',\n type: 'snippet',\n boost: 5,\n },\n {\n label: 'pie',\n detail: 'Mermaid pie chart',\n apply: '```mermaid\\npie title ${Distribution}\\n \"${Category A}\" : ${45}\\n \"${Category B}\" : ${30}\\n \"${Category C}\" : ${25}\\n```',\n type: 'snippet',\n boost: 5,\n },\n {\n label: 'mermaid-flowchart',\n detail: 'Mermaid flowchart (alias)',\n apply: '```mermaid\\nflowchart LR\\n A[${Start}] --> B{${Decision}}\\n B -->|Yes| C[${Option 1}]\\n B -->|No| D[${Option 2}]\\n```',\n type: 'snippet',\n },\n {\n label: 'mermaid-sequence',\n detail: 'Mermaid sequence diagram (alias)',\n apply: '```mermaid\\nsequenceDiagram\\n participant A as ${Alice}\\n participant B as ${Bob}\\n A->>B: ${Hello Bob}\\n B->>A: ${Hello Alice}\\n```',\n type: 'snippet',\n },\n ];\n\n // KaTeX 数学公式\n const katexSnippets = [\n {\n label: 'math',\n detail: 'Math block',\n apply: '```math\\n${formula}\\n```',\n type: 'snippet',\n },\n {\n label: 'inline-math',\n detail: 'Inline math $...$',\n apply: '$${formula}$',\n type: 'snippet',\n },\n {\n label: 'block-math',\n detail: 'Block math $$...$$',\n apply: '$$\\n${formula}\\n$$',\n type: 'snippet',\n },\n {\n label: 'fraction',\n detail: 'Fraction',\n apply: '\\\\frac{${numerator}}{${denominator}}',\n type: 'snippet',\n },\n {\n label: 'sqrt',\n detail: 'Square root',\n apply: '\\\\sqrt{${x}}',\n type: 'snippet',\n },\n {\n label: 'sum',\n detail: 'Summation',\n apply: '\\\\sum_{${i=1}}^{${n}} ${x_i}',\n type: 'snippet',\n },\n {\n label: 'integral',\n detail: 'Integral',\n apply: '\\\\int_{${a}}^{${b}} ${f(x)} dx',\n type: 'snippet',\n },\n {\n label: 'matrix',\n detail: 'Matrix',\n apply: '\\\\begin{bmatrix}\\n${a} & ${b} \\\\\\\\\\n${c} & ${d}\\n\\\\end{bmatrix}',\n type: 'snippet',\n },\n ];\n\n // Markdown 表格\n const tableSnippets = [\n {\n label: 'table',\n detail: 'Markdown table',\n apply: '| ${Column 1} | ${Column 2} | ${Column 3} |\\n|------------|------------|------------|\\n| ${Cell 1} | ${Cell 2} | ${Cell 3} |\\n| ${Cell 4} | ${Cell 5} | ${Cell 6} |',\n type: 'snippet',\n },\n {\n label: 'table-2col',\n detail: '2-column table',\n apply: '| ${Column 1} | ${Column 2} |\\n|------------|------------|\\n| ${Cell 1} | ${Cell 2} |\\n| ${Cell 3} | ${Cell 4} |',\n type: 'snippet',\n },\n {\n label: 'table-align',\n detail: 'Table with alignment',\n apply: '| ${Left} | ${Center} | ${Right} |\\n|:--------|:---------:|---------:|\\n| ${L1} | ${C1} | ${R1} |\\n| ${L2} | ${C2} | ${R2} |',\n type: 'snippet',\n },\n ];\n\n // 脚注\n const footnoteSnippets = [\n {\n label: 'footnote',\n detail: 'Footnote reference',\n apply: '[^${1}]',\n type: 'snippet',\n },\n {\n label: 'footnote-def',\n detail: 'Footnote definition',\n apply: '[^${1}]: ${definition}',\n type: 'snippet',\n },\n ];\n\n // 合并所有补全选项\n const allSnippets = [\n ...basicSnippets,\n ...mermaidSnippets,\n ...katexSnippets,\n ...tableSnippets,\n ...footnoteSnippets,\n ];\n\n // 过滤匹配的选项\n for (const snippet of allSnippets) {\n if (snippet.label.startsWith(wordText) || wordText === '' || context.explicit) {\n options.push(snippet);\n }\n }\n\n // 如果没有匹配项,返回 null 让其他补全源处理\n if (options.length === 0) {\n return null;\n }\n\n return {\n from: word.from,\n options,\n };\n },\n ],\n });\n};\n\n// Markdown 样式 - 改进选中背景和其他样式\nexport const markdownTheme = EditorView.baseTheme({\n // 活动行背景 - Light 模式(降低不透明度,让选中更明显)\n '&light .cm-activeLine': {\n backgroundColor: 'rgba(0, 0, 0, 0.03)',\n },\n\n // 活动行背景 - Dark 模式(降低不透明度,让选中更明显)\n '&dark .cm-activeLine': {\n backgroundColor: 'rgba(255, 255, 255, 0.05)',\n },\n\n // 选中文本背景由 CodeEditor 主主题统一控制,避免重复定义\n\n // Mermaid 块 - Light 模式\n '&light .cm-markdown-mermaid-marker': {\n color: '#10b981',\n fontWeight: 'bold',\n },\n '&light .cm-markdown-mermaid-content': {\n backgroundColor: 'rgba(16, 185, 129, 0.1)',\n color: '#059669',\n },\n\n // Mermaid 块 - Dark 模式 - 使用更亮的颜色\n '&dark .cm-markdown-mermaid-marker': {\n color: '#6ee7b7',\n fontWeight: 'bold',\n },\n '&dark .cm-markdown-mermaid-content': {\n backgroundColor: 'rgba(52, 211, 153, 0.15)',\n color: '#a7f3d0',\n },\n\n // KaTeX 块 - Light 模式\n '&light .cm-markdown-katex-marker': {\n color: '#3b82f6',\n fontWeight: 'bold',\n },\n '&light .cm-markdown-katex-content': {\n backgroundColor: 'rgba(59, 130, 246, 0.1)',\n color: '#2563eb',\n },\n '&light .cm-markdown-inline-katex': {\n backgroundColor: 'rgba(59, 130, 246, 0.15)',\n color: '#1d4ed8',\n borderRadius: '2px',\n padding: '1px 3px',\n },\n '&light .cm-markdown-block-katex': {\n backgroundColor: 'rgba(59, 130, 246, 0.15)',\n color: '#1d4ed8',\n borderRadius: '2px',\n padding: '2px 4px',\n display: 'inline-block',\n },\n\n // KaTeX 块 - Dark 模式 - 使用更亮的颜色\n '&dark .cm-markdown-katex-marker': {\n color: '#93c5fd',\n fontWeight: 'bold',\n },\n '&dark .cm-markdown-katex-content': {\n backgroundColor: 'rgba(96, 165, 250, 0.15)',\n color: '#bfdbfe',\n },\n '&dark .cm-markdown-inline-katex': {\n backgroundColor: 'rgba(96, 165, 250, 0.2)',\n color: '#e0f2fe',\n borderRadius: '2px',\n padding: '1px 3px',\n },\n '&dark .cm-markdown-block-katex': {\n backgroundColor: 'rgba(96, 165, 250, 0.2)',\n color: '#e0f2fe',\n borderRadius: '2px',\n padding: '2px 4px',\n display: 'inline-block',\n },\n\n // 代码块 - Light 模式\n '&light .cm-markdown-code-marker': {\n color: '#6b7280',\n fontWeight: 'bold',\n },\n '&light .cm-markdown-code-content': {\n backgroundColor: 'rgba(100, 116, 139, 0.08)',\n color: '#334155',\n fontFamily: 'monospace',\n },\n\n // 代码块 - Dark 模式 - 使用更亮的颜色\n '&dark .cm-markdown-code-marker': {\n color: '#d1d5db',\n fontWeight: 'bold',\n },\n '&dark .cm-markdown-code-content': {\n backgroundColor: 'rgba(148, 163, 184, 0.1)',\n color: '#e5e7eb',\n fontFamily: 'monospace',\n },\n\n // 表格 - Light 模式\n '&light .cm-markdown-table-row': {\n backgroundColor: 'rgba(100, 116, 139, 0.05)',\n },\n '&light .cm-markdown-table-pipe': {\n color: '#64748b',\n fontWeight: 'bold',\n },\n '&light .cm-markdown-table-separator': {\n color: '#94a3b8',\n fontWeight: 'bold',\n backgroundColor: 'rgba(100, 116, 139, 0.1)',\n },\n\n // 表格 - Dark 模式 - 使用更亮的颜色\n '&dark .cm-markdown-table-row': {\n backgroundColor: 'rgba(148, 163, 184, 0.08)',\n },\n '&dark .cm-markdown-table-pipe': {\n color: '#d1d5db',\n fontWeight: 'bold',\n },\n '&dark .cm-markdown-table-separator': {\n color: '#e5e7eb',\n fontWeight: 'bold',\n backgroundColor: 'rgba(148, 163, 184, 0.15)',\n },\n\n // 代码块标记\n '.cm-markdown-codeblock-marker': {\n fontWeight: 'bold',\n },\n\n // 目录面板样式 - 修复展开按钮遮挡\n '.toc-panel': {\n position: 'relative',\n zIndex: 1,\n },\n\n // 脚注样式\n '&light .cm-markdown-footnote-ref': {\n color: '#3b82f6',\n cursor: 'pointer',\n textDecoration: 'none',\n fontWeight: 'bold',\n },\n '&dark .cm-markdown-footnote-ref': {\n color: '#93c5fd',\n cursor: 'pointer',\n textDecoration: 'none',\n fontWeight: 'bold',\n },\n '&light .cm-markdown-footnote-def': {\n color: '#059669',\n cursor: 'pointer',\n fontWeight: 'bold',\n },\n '&dark .cm-markdown-footnote-def': {\n color: '#6ee7b7',\n cursor: 'pointer',\n fontWeight: 'bold',\n },\n});\n\n// 导出所有 Markdown 扩展\nexport const markdownExtensions = (): Extension[] => {\n return [\n codeBlockHighlight,\n tableHighlight,\n footnoteDecoration,\n footnoteClickHandler,\n markdownAutocompletion(),\n markdownTheme\n ];\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"markdownExtensions.js","names":["codeBlockHighlight","ViewPlugin","view","update","decorations","lines","inCodeBlock","blockType","blockLang","i","line","lineStart","codeBlockStart","lang","mark","Decoration","className","inlineKatexRegex","match","from","to","blockKatexRegex","a","b","v","tableHighlight","pipeRegex","pipeMark","footnoteClickHandler","EditorView","pos","event","lineText","clickOffset","refRegex","matchStart","matchEnd","footnoteId","defMatch","targetLine","footnoteDecoration","extractMarkdownSections","sections","code","level","title","id","extractFootnotes","footnoteMap","existing","markdownAutocompletion","autocompletion","word","context","options","wordText","basicSnippets","mermaidSnippets","katexSnippets","tableSnippets","footnoteSnippets","allSnippets","snippet","markdownTheme","markdownExtensions"],"sources":["../../../../../src/components/pro/CodeEditor/editors/markdownExtensions.ts"],"sourcesContent":["import { Extension } from '@codemirror/state';\nimport { EditorView, Decoration, DecorationSet, ViewPlugin, ViewUpdate } from '@codemirror/view';\nimport { syntaxTree } from '@codemirror/language';\nimport { CompletionContext, CompletionResult, autocompletion } from '@codemirror/autocomplete';\nimport { LanguageSupport } from '@codemirror/language';\nimport { javascript } from '@codemirror/lang-javascript';\nimport { python } from '@codemirror/lang-python';\nimport { html } from '@codemirror/lang-html';\nimport { css } from '@codemirror/lang-css';\nimport { json } from '@codemirror/lang-json';\n\n// Markdown 章节信息\nexport interface MarkdownSection {\n level: number;\n title: string;\n line: number;\n id: string;\n}\n\n// 脚注信息\nexport interface FootnoteInfo {\n id: string;\n line: number; // 第一次引用的行号\n definitionLine?: number; // 定义的行号\n referenceLines?: number[]; // 所有引用的行号列表\n}\n\n// 获取代码块语言支持\nconst getCodeBlockLanguage = (lang: string): LanguageSupport | null => {\n switch (lang.toLowerCase()) {\n case 'javascript':\n case 'js':\n case 'jsx':\n return javascript({ jsx: true });\n case 'typescript':\n case 'ts':\n case 'tsx':\n return javascript({ jsx: true, typescript: true });\n case 'python':\n case 'py':\n return python();\n case 'html':\n return html();\n case 'css':\n return css();\n case 'json':\n return json();\n default:\n return null;\n }\n};\n\n// Mermaid/KaTeX 块高亮 + 代码块语法高亮\nconst codeBlockHighlight = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n\n constructor(view: EditorView) {\n this.decorations = this.buildDecorations(view);\n }\n\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged) {\n this.decorations = this.buildDecorations(update.view);\n }\n }\n\n buildDecorations(view: EditorView): DecorationSet {\n const decorations = [];\n const text = view.state.doc.toString();\n const lines = text.split('\\n');\n\n let inCodeBlock = false;\n let blockType: 'mermaid' | 'katex' | 'math' | 'code' | null = null;\n let blockLang: string = '';\n let blockStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const lineStart = view.state.doc.line(i + 1).from;\n\n // 检测代码块开始\n const codeBlockStart = line.match(/^```(\\w+)/);\n if (codeBlockStart && !inCodeBlock) {\n inCodeBlock = true;\n const lang = codeBlockStart[1];\n\n if (lang === 'mermaid') {\n blockType = 'mermaid';\n } else if (lang === 'math' || lang === 'katex') {\n blockType = 'katex';\n } else {\n blockType = 'code';\n blockLang = lang;\n }\n\n blockStart = lineStart;\n\n // 高亮代码块标记\n const mark = Decoration.mark({\n class: `cm-markdown-codeblock-marker${blockType === 'mermaid' ? ' cm-markdown-mermaid-marker' : blockType === 'katex' ? ' cm-markdown-katex-marker' : ' cm-markdown-code-marker'}`,\n });\n decorations.push(mark.range(lineStart, lineStart + line.length));\n }\n // 检测代码块结束\n else if (inCodeBlock && line.match(/^```\\s*$/)) {\n inCodeBlock = false;\n\n // 高亮代码块标记\n const mark = Decoration.mark({\n class: 'cm-markdown-codeblock-marker',\n });\n decorations.push(mark.range(lineStart, lineStart + line.length));\n\n blockType = null;\n blockLang = '';\n }\n // 代码块内容高亮\n else if (inCodeBlock && blockType) {\n const className = blockType === 'mermaid'\n ? 'cm-markdown-codeblock-content cm-markdown-mermaid-content'\n : blockType === 'katex'\n ? 'cm-markdown-codeblock-content cm-markdown-katex-content'\n : `cm-markdown-codeblock-content cm-markdown-code-content cm-code-${blockLang}`;\n\n const mark = Decoration.mark({\n class: className,\n });\n decorations.push(mark.range(lineStart, lineStart + line.length));\n }\n\n // 行内 KaTeX 高亮 $...$\n if (!inCodeBlock) {\n const inlineKatexRegex = /\\$([^$]+)\\$/g;\n let match;\n while ((match = inlineKatexRegex.exec(line)) !== null) {\n const from = lineStart + match.index;\n const to = from + match[0].length;\n const mark = Decoration.mark({\n class: 'cm-markdown-inline-katex',\n });\n decorations.push(mark.range(from, to));\n }\n\n // 块级 KaTeX 高亮 $$...$$\n const blockKatexRegex = /\\$\\$([^$]+)\\$\\$/g;\n while ((match = blockKatexRegex.exec(line)) !== null) {\n const from = lineStart + match.index;\n const to = from + match[0].length;\n const mark = Decoration.mark({\n class: 'cm-markdown-block-katex',\n });\n decorations.push(mark.range(from, to));\n }\n }\n }\n\n // 按位置排序装饰,避免 CodeMirror 错误\n decorations.sort((a, b) => a.from - b.from);\n\n return Decoration.set(decorations);\n }\n },\n {\n decorations: (v) => v.decorations,\n }\n);\n\n// Markdown 表格高亮\nconst tableHighlight = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n\n constructor(view: EditorView) {\n this.decorations = this.buildDecorations(view);\n }\n\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged) {\n this.decorations = this.buildDecorations(update.view);\n }\n }\n\n buildDecorations(view: EditorView): DecorationSet {\n const decorations = [];\n const text = view.state.doc.toString();\n const lines = text.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const lineStart = view.state.doc.line(i + 1).from;\n\n // 检测表格行 (包含 |)\n if (line.includes('|') && line.trim().startsWith('|')) {\n // 不要添加整行的装饰,只高亮管道符\n // 这样可以避免与管道符装饰重叠\n\n // 高亮表格分隔符 |\n const pipeRegex = /\\|/g;\n let match;\n while ((match = pipeRegex.exec(line)) !== null) {\n const from = lineStart + match.index;\n const to = from + 1;\n const pipeMark = Decoration.mark({\n class: 'cm-markdown-table-pipe',\n });\n decorations.push(pipeMark.range(from, to));\n }\n }\n\n // 检测表格分隔行 |---|---|\n if (line.match(/^\\|?\\s*:?-+:?\\s*\\|/)) {\n const mark = Decoration.mark({\n class: 'cm-markdown-table-separator',\n });\n decorations.push(mark.range(lineStart, lineStart + line.length));\n }\n }\n\n // 按位置排序装饰,避免 CodeMirror 错误\n decorations.sort((a, b) => a.from - b.from);\n\n return Decoration.set(decorations);\n }\n },\n {\n decorations: (v) => v.decorations,\n }\n);\n\n// 脚注点击跳转处理\nconst footnoteClickHandler = EditorView.domEventHandlers({\n mousedown: (event, view) => {\n const target = event.target as HTMLElement;\n const pos = view.posAtCoords({ x: event.clientX, y: event.clientY });\n\n if (pos === null) return false;\n\n const line = view.state.doc.lineAt(pos);\n const lineText = line.text;\n const clickOffset = pos - line.from;\n\n // 检查是否点击了脚注引用 [^id]\n const refRegex = /\\[\\^(\\w+)\\]/g;\n let match;\n while ((match = refRegex.exec(lineText)) !== null) {\n const matchStart = match.index;\n const matchEnd = matchStart + match[0].length;\n\n if (clickOffset >= matchStart && clickOffset <= matchEnd) {\n const footnoteId = match[1];\n\n // 查找脚注定义\n const text = view.state.doc.toString();\n const lines = text.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const defMatch = lines[i].match(/^\\[\\^(\\w+)\\]:\\s*(.+)$/);\n if (defMatch && defMatch[1] === footnoteId) {\n // 找到定义,跳转到该行\n const targetLine = view.state.doc.line(i + 1);\n view.dispatch({\n selection: { anchor: targetLine.from },\n effects: EditorView.scrollIntoView(targetLine.from, { y: 'center' })\n });\n\n event.preventDefault();\n return true;\n }\n }\n }\n }\n\n // 检查是否点击了脚注定义 [^id]:\n const defMatch = lineText.match(/^\\[\\^(\\w+)\\]:/);\n if (defMatch) {\n const matchEnd = defMatch[0].length;\n\n if (clickOffset <= matchEnd) {\n const footnoteId = defMatch[1];\n\n // 查找第一个引用\n const text = view.state.doc.toString();\n const lines = text.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const refRegex = new RegExp(`\\\\[\\\\^${footnoteId}\\\\](?!:)`, 'g');\n if (refRegex.test(lines[i])) {\n // 找到引用,跳转到该行\n const targetLine = view.state.doc.line(i + 1);\n view.dispatch({\n selection: { anchor: targetLine.from },\n effects: EditorView.scrollIntoView(targetLine.from, { y: 'center' })\n });\n\n event.preventDefault();\n return true;\n }\n }\n }\n }\n\n return false;\n }\n});\n\n// 脚注样式装饰 - 让脚注看起来可点击\nconst footnoteDecoration = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n\n constructor(view: EditorView) {\n this.decorations = this.buildDecorations(view);\n }\n\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged) {\n this.decorations = this.buildDecorations(update.view);\n }\n }\n\n buildDecorations(view: EditorView): DecorationSet {\n const decorations = [];\n const text = view.state.doc.toString();\n const lines = text.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const lineStart = view.state.doc.line(i + 1).from;\n\n // 脚注引用 [^id]\n const refRegex = /\\[\\^(\\w+)\\]/g;\n let match;\n while ((match = refRegex.exec(line)) !== null) {\n const from = lineStart + match.index;\n const to = from + match[0].length;\n const mark = Decoration.mark({\n class: 'cm-markdown-footnote-ref',\n attributes: { style: 'cursor: pointer; text-decoration: underline; text-decoration-style: dotted;' }\n });\n decorations.push(mark.range(from, to));\n }\n\n // 脚注定义 [^id]:\n const defMatch = line.match(/^\\[\\^(\\w+)\\]:/);\n if (defMatch) {\n const from = lineStart;\n const to = from + defMatch[0].length;\n const mark = Decoration.mark({\n class: 'cm-markdown-footnote-def',\n attributes: { style: 'cursor: pointer; font-weight: bold;' }\n });\n decorations.push(mark.range(from, to));\n }\n }\n\n // 按位置排序装饰,避免 CodeMirror 错误\n decorations.sort((a, b) => a.from - b.from);\n\n return Decoration.set(decorations);\n }\n },\n {\n decorations: (v) => v.decorations,\n }\n);\n\n// 提取 Markdown 章节\nexport const extractMarkdownSections = (code: string): MarkdownSection[] => {\n const sections: MarkdownSection[] = [];\n const lines = code.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const match = line.match(/^(#{1,6})\\s+(.+)$/);\n\n if (match) {\n const level = match[1].length;\n const title = match[2].trim();\n const id = title\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-');\n\n sections.push({\n level,\n title,\n line: i + 1,\n id,\n });\n }\n }\n\n return sections;\n};\n\n// 提取脚注\nexport const extractFootnotes = (code: string): FootnoteInfo[] => {\n const footnotes: FootnoteInfo[] = [];\n const lines = code.split('\\n');\n const footnoteMap = new Map<string, FootnoteInfo>();\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // 脚注引用 [^1]\n const refRegex = /\\[\\^(\\w+)\\]/g;\n let match;\n while ((match = refRegex.exec(line)) !== null) {\n const id = match[1];\n const existing = footnoteMap.get(id);\n if (existing) {\n // 已存在,添加到引用列表\n if (!existing.referenceLines) {\n existing.referenceLines = [existing.line];\n }\n existing.referenceLines.push(i + 1);\n } else {\n // 首次出现\n footnoteMap.set(id, {\n id,\n line: i + 1,\n referenceLines: [i + 1],\n });\n }\n }\n\n // 脚注定义 [^1]: ...\n const defMatch = line.match(/^\\[\\^(\\w+)\\]:\\s*(.+)$/);\n if (defMatch) {\n const id = defMatch[1];\n const existing = footnoteMap.get(id);\n if (existing) {\n existing.definitionLine = i + 1;\n } else {\n footnoteMap.set(id, {\n id,\n line: i + 1,\n definitionLine: i + 1,\n referenceLines: [],\n });\n }\n }\n }\n\n return Array.from(footnoteMap.values());\n};\n\n// Markdown 智能补全 - 改进版,支持更多触发方式\nexport const markdownAutocompletion = () => {\n return autocompletion({\n override: [\n (context: CompletionContext): CompletionResult | null => {\n const word = context.matchBefore(/\\S*/);\n if (!word || (word.from === word.to && !context.explicit)) {\n return null;\n }\n\n const options = [];\n const wordText = word.text.toLowerCase();\n\n // 获取当前行的文本,用于更好的上下文判断\n const line = context.state.doc.lineAt(context.pos);\n const lineText = line.text;\n const cursorPosInLine = context.pos - line.from;\n\n // 检查是否在行首输入特殊字符\n const isLineStart = lineText.trim() === wordText || cursorPosInLine <= 2;\n\n // Markdown 基础语法\n const basicSnippets = [\n { label: '#', detail: 'Heading 1', apply: '# ${title}', type: 'snippet', boost: 10 },\n { label: '##', detail: 'Heading 2', apply: '## ${title}', type: 'snippet', boost: 10 },\n { label: '###', detail: 'Heading 3', apply: '### ${title}', type: 'snippet', boost: 10 },\n { label: '####', detail: 'Heading 4', apply: '#### ${title}', type: 'snippet', boost: 10 },\n { label: '#####', detail: 'Heading 5', apply: '##### ${title}', type: 'snippet', boost: 10 },\n { label: '######', detail: 'Heading 6', apply: '###### ${title}', type: 'snippet', boost: 10 },\n { label: '-', detail: 'Unordered list', apply: '- ${item}', type: 'snippet', boost: 10 },\n { label: '*', detail: 'Unordered list', apply: '* ${item}', type: 'snippet', boost: 10 },\n { label: '1.', detail: 'Ordered list', apply: '1. ${item}', type: 'snippet', boost: 10 },\n { label: 'h1', detail: '# Heading 1', apply: '# ${title}', type: 'snippet' },\n { label: 'h2', detail: '## Heading 2', apply: '## ${title}', type: 'snippet' },\n { label: 'h3', detail: '### Heading 3', apply: '### ${title}', type: 'snippet' },\n { label: 'bold', detail: '**bold**', apply: '**${text}**', type: 'snippet' },\n { label: 'italic', detail: '*italic*', apply: '*${text}*', type: 'snippet' },\n { label: 'code', detail: '`code`', apply: '`${code}`', type: 'snippet' },\n { label: 'link', detail: '[text](url)', apply: '[${text}](${url})', type: 'snippet' },\n { label: 'image', detail: '![alt](url)', apply: '![${alt}](${url})', type: 'snippet' },\n { label: 'quote', detail: '> quote', apply: '> ${text}', type: 'snippet' },\n { label: 'ul', detail: '- item', apply: '- ${item}', type: 'snippet' },\n { label: 'ol', detail: '1. item', apply: '1. ${item}', type: 'snippet' },\n { label: 'task', detail: '- [ ] task', apply: '- [ ] ${task}', type: 'snippet' },\n { label: 'hr', detail: '---', apply: '---', type: 'snippet' },\n ];\n\n // Mermaid 图表 - 支持通过图表类型触发\n const mermaidSnippets = [\n {\n label: 'mermaid',\n detail: 'Mermaid diagram',\n apply: '```mermaid\\ngraph TD\\n A[${Start}] --> B[${End}]\\n```',\n type: 'snippet',\n },\n {\n label: 'flowchart',\n detail: 'Mermaid flowchart',\n apply: '```mermaid\\nflowchart LR\\n A[${Start}] --> B{${Decision}}\\n B -->|Yes| C[${Option 1}]\\n B -->|No| D[${Option 2}]\\n```',\n type: 'snippet',\n boost: 5,\n },\n {\n label: 'sequence',\n detail: 'Mermaid sequence diagram',\n apply: '```mermaid\\nsequenceDiagram\\n participant A as ${Alice}\\n participant B as ${Bob}\\n A->>B: ${Hello Bob}\\n B->>A: ${Hello Alice}\\n```',\n type: 'snippet',\n boost: 5,\n },\n {\n label: 'gantt',\n detail: 'Mermaid Gantt chart',\n apply: '```mermaid\\ngantt\\n title ${Project Timeline}\\n dateFormat YYYY-MM-DD\\n section ${Phase 1}\\n ${Task 1} :a1, 2024-01-01, 30d\\n ${Task 2} :after a1, 20d\\n```',\n type: 'snippet',\n boost: 5,\n },\n {\n label: 'pie',\n detail: 'Mermaid pie chart',\n apply: '```mermaid\\npie title ${Distribution}\\n \"${Category A}\" : ${45}\\n \"${Category B}\" : ${30}\\n \"${Category C}\" : ${25}\\n```',\n type: 'snippet',\n boost: 5,\n },\n {\n label: 'mermaid-flowchart',\n detail: 'Mermaid flowchart (alias)',\n apply: '```mermaid\\nflowchart LR\\n A[${Start}] --> B{${Decision}}\\n B -->|Yes| C[${Option 1}]\\n B -->|No| D[${Option 2}]\\n```',\n type: 'snippet',\n },\n {\n label: 'mermaid-sequence',\n detail: 'Mermaid sequence diagram (alias)',\n apply: '```mermaid\\nsequenceDiagram\\n participant A as ${Alice}\\n participant B as ${Bob}\\n A->>B: ${Hello Bob}\\n B->>A: ${Hello Alice}\\n```',\n type: 'snippet',\n },\n ];\n\n // KaTeX 数学公式\n const katexSnippets = [\n {\n label: 'math',\n detail: 'Math block',\n apply: '```math\\n${formula}\\n```',\n type: 'snippet',\n },\n {\n label: 'inline-math',\n detail: 'Inline math $...$',\n apply: '$${formula}$',\n type: 'snippet',\n },\n {\n label: 'block-math',\n detail: 'Block math $$...$$',\n apply: '$$\\n${formula}\\n$$',\n type: 'snippet',\n },\n {\n label: 'fraction',\n detail: 'Fraction',\n apply: '\\\\frac{${numerator}}{${denominator}}',\n type: 'snippet',\n },\n {\n label: 'sqrt',\n detail: 'Square root',\n apply: '\\\\sqrt{${x}}',\n type: 'snippet',\n },\n {\n label: 'sum',\n detail: 'Summation',\n apply: '\\\\sum_{${i=1}}^{${n}} ${x_i}',\n type: 'snippet',\n },\n {\n label: 'integral',\n detail: 'Integral',\n apply: '\\\\int_{${a}}^{${b}} ${f(x)} dx',\n type: 'snippet',\n },\n {\n label: 'matrix',\n detail: 'Matrix',\n apply: '\\\\begin{bmatrix}\\n${a} & ${b} \\\\\\\\\\n${c} & ${d}\\n\\\\end{bmatrix}',\n type: 'snippet',\n },\n ];\n\n // Markdown 表格\n const tableSnippets = [\n {\n label: 'table',\n detail: 'Markdown table',\n apply: '| ${Column 1} | ${Column 2} | ${Column 3} |\\n|------------|------------|------------|\\n| ${Cell 1} | ${Cell 2} | ${Cell 3} |\\n| ${Cell 4} | ${Cell 5} | ${Cell 6} |',\n type: 'snippet',\n },\n {\n label: 'table-2col',\n detail: '2-column table',\n apply: '| ${Column 1} | ${Column 2} |\\n|------------|------------|\\n| ${Cell 1} | ${Cell 2} |\\n| ${Cell 3} | ${Cell 4} |',\n type: 'snippet',\n },\n {\n label: 'table-align',\n detail: 'Table with alignment',\n apply: '| ${Left} | ${Center} | ${Right} |\\n|:--------|:---------:|---------:|\\n| ${L1} | ${C1} | ${R1} |\\n| ${L2} | ${C2} | ${R2} |',\n type: 'snippet',\n },\n ];\n\n // 脚注\n const footnoteSnippets = [\n {\n label: 'footnote',\n detail: 'Footnote reference',\n apply: '[^${1}]',\n type: 'snippet',\n },\n {\n label: 'footnote-def',\n detail: 'Footnote definition',\n apply: '[^${1}]: ${definition}',\n type: 'snippet',\n },\n ];\n\n // 合并所有补全选项\n const allSnippets = [\n ...basicSnippets,\n ...mermaidSnippets,\n ...katexSnippets,\n ...tableSnippets,\n ...footnoteSnippets,\n ];\n\n // 过滤匹配的选项\n for (const snippet of allSnippets) {\n if (snippet.label.startsWith(wordText) || wordText === '' || context.explicit) {\n options.push(snippet);\n }\n }\n\n // 如果没有匹配项,返回 null 让其他补全源处理\n if (options.length === 0) {\n return null;\n }\n\n return {\n from: word.from,\n options,\n };\n },\n ],\n });\n};\n\n// Markdown 样式 - 改进选中背景和其他样式\nexport const markdownTheme = EditorView.baseTheme({\n // 活动行背景 - Light 模式(降低不透明度,让选中更明显)\n '&light .cm-activeLine': {\n backgroundColor: 'rgba(0, 0, 0, 0.03)',\n },\n\n // 活动行背景 - Dark 模式(降低不透明度,让选中更明显)\n '&dark .cm-activeLine': {\n backgroundColor: 'rgba(255, 255, 255, 0.05)',\n },\n\n // 选中文本背景由 CodeEditor 主主题统一控制,避免重复定义\n\n // Mermaid 块 - Light 模式\n '&light .cm-markdown-mermaid-marker': {\n color: '#10b981',\n fontWeight: 'bold',\n },\n '&light .cm-markdown-mermaid-content': {\n backgroundColor: 'rgba(16, 185, 129, 0.1)',\n color: '#059669',\n },\n\n // Mermaid 块 - Dark 模式 - 使用更亮的颜色\n '&dark .cm-markdown-mermaid-marker': {\n color: '#6ee7b7',\n fontWeight: 'bold',\n },\n '&dark .cm-markdown-mermaid-content': {\n backgroundColor: 'rgba(52, 211, 153, 0.15)',\n color: '#a7f3d0',\n },\n\n // KaTeX 块 - Light 模式\n '&light .cm-markdown-katex-marker': {\n color: '#3b82f6',\n fontWeight: 'bold',\n },\n '&light .cm-markdown-katex-content': {\n backgroundColor: 'rgba(59, 130, 246, 0.1)',\n color: '#2563eb',\n },\n '&light .cm-markdown-inline-katex': {\n backgroundColor: 'rgba(59, 130, 246, 0.15)',\n color: '#1d4ed8',\n borderRadius: '2px',\n padding: '1px 3px',\n },\n '&light .cm-markdown-block-katex': {\n backgroundColor: 'rgba(59, 130, 246, 0.15)',\n color: '#1d4ed8',\n borderRadius: '2px',\n padding: '2px 4px',\n display: 'inline-block',\n },\n\n // KaTeX 块 - Dark 模式 - 使用更亮的颜色\n '&dark .cm-markdown-katex-marker': {\n color: '#93c5fd',\n fontWeight: 'bold',\n },\n '&dark .cm-markdown-katex-content': {\n backgroundColor: 'rgba(96, 165, 250, 0.15)',\n color: '#bfdbfe',\n },\n '&dark .cm-markdown-inline-katex': {\n backgroundColor: 'rgba(96, 165, 250, 0.2)',\n color: '#e0f2fe',\n borderRadius: '2px',\n padding: '1px 3px',\n },\n '&dark .cm-markdown-block-katex': {\n backgroundColor: 'rgba(96, 165, 250, 0.2)',\n color: '#e0f2fe',\n borderRadius: '2px',\n padding: '2px 4px',\n display: 'inline-block',\n },\n\n // 代码块 - Light 模式\n '&light .cm-markdown-code-marker': {\n color: '#6b7280',\n fontWeight: 'bold',\n },\n '&light .cm-markdown-code-content': {\n backgroundColor: 'rgba(100, 116, 139, 0.08)',\n color: '#334155',\n fontFamily: 'monospace',\n },\n\n // 代码块 - Dark 模式 - 使用更亮的颜色\n '&dark .cm-markdown-code-marker': {\n color: '#d1d5db',\n fontWeight: 'bold',\n },\n '&dark .cm-markdown-code-content': {\n backgroundColor: 'rgba(148, 163, 184, 0.1)',\n color: '#e5e7eb',\n fontFamily: 'monospace',\n },\n\n // 表格 - Light 模式\n '&light .cm-markdown-table-row': {\n backgroundColor: 'rgba(100, 116, 139, 0.05)',\n },\n '&light .cm-markdown-table-pipe': {\n color: '#64748b',\n fontWeight: 'bold',\n },\n '&light .cm-markdown-table-separator': {\n color: '#94a3b8',\n fontWeight: 'bold',\n backgroundColor: 'rgba(100, 116, 139, 0.1)',\n },\n\n // 表格 - Dark 模式 - 使用更亮的颜色\n '&dark .cm-markdown-table-row': {\n backgroundColor: 'rgba(148, 163, 184, 0.08)',\n },\n '&dark .cm-markdown-table-pipe': {\n color: '#d1d5db',\n fontWeight: 'bold',\n },\n '&dark .cm-markdown-table-separator': {\n color: '#e5e7eb',\n fontWeight: 'bold',\n backgroundColor: 'rgba(148, 163, 184, 0.15)',\n },\n\n // 代码块标记\n '.cm-markdown-codeblock-marker': {\n fontWeight: 'bold',\n },\n\n // 目录面板样式 - 修复展开按钮遮挡\n '.toc-panel': {\n position: 'relative',\n zIndex: 1,\n },\n\n // 脚注样式\n '&light .cm-markdown-footnote-ref': {\n color: '#3b82f6',\n cursor: 'pointer',\n textDecoration: 'none',\n fontWeight: 'bold',\n },\n '&dark .cm-markdown-footnote-ref': {\n color: '#93c5fd',\n cursor: 'pointer',\n textDecoration: 'none',\n fontWeight: 'bold',\n },\n '&light .cm-markdown-footnote-def': {\n color: '#059669',\n cursor: 'pointer',\n fontWeight: 'bold',\n },\n '&dark .cm-markdown-footnote-def': {\n color: '#6ee7b7',\n cursor: 'pointer',\n fontWeight: 'bold',\n },\n});\n\n// 导出所有 Markdown 扩展\nexport const markdownExtensions = (): Extension[] => {\n return [\n codeBlockHighlight,\n tableHighlight,\n footnoteDecoration,\n footnoteClickHandler,\n markdownAutocompletion(),\n markdownTheme\n ];\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"contextMenu.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/extensions/contextMenu.ts"],"sourcesContent":["import type { ContextMenuItem } from '../types';\nimport type { EditorView } from '@codemirror/view';\n\n// 默认上下文菜单\nexport const defaultContextMenu: ContextMenuItem[] = [\n {\n label: '剪切',\n action: (view) => {\n const selection = view.state.selection.main;\n const text = view.state.sliceDoc(selection.from, selection.to);\n navigator.clipboard.writeText(text);\n view.dispatch({\n changes: { from: selection.from, to: selection.to, insert: '' },\n });\n },\n },\n {\n label: '复制',\n action: (view) => {\n const selection = view.state.selection.main;\n const text = view.state.sliceDoc(selection.from, selection.to);\n navigator.clipboard.writeText(text);\n },\n },\n {\n label: '粘贴',\n action: async (view) => {\n const text = await navigator.clipboard.readText();\n const selection = view.state.selection.main;\n view.dispatch({\n changes: { from: selection.from, to: selection.to, insert: text },\n });\n },\n },\n { label: '', action: () => { }, separator: true },\n {\n label: '全选',\n action: (view) => {\n view.dispatch({\n selection: { anchor: 0, head: view.state.doc.length },\n });\n },\n },\n {\n label: '查找',\n action: (view) => {\n const searchPanel = view.dom.querySelector('.cm-search');\n if (searchPanel) {\n (searchPanel as HTMLElement).focus();\n }\n },\n },\n];\n\n"],"mappings":";AAIA,IAAa,IAAwC;CACjD;EACI,OAAO;EACP,SAAS,MAAS;GACd,IAAM,IAAY,EAAK,MAAM,UAAU,MACjC,IAAO,EAAK,MAAM,SAAS,EAAU,MAAM,EAAU,EAAE;GAE7D,AADA,UAAU,UAAU,UAAU,CAAI,GAClC,EAAK,SAAS,EACV,SAAS;IAAE,MAAM,EAAU;IAAM,IAAI,EAAU;IAAI,QAAQ;GAAG,EAClE,CAAC;EACL;CACJ;CACA;EACI,OAAO;EACP,SAAS,MAAS;GACd,IAAM,IAAY,EAAK,MAAM,UAAU,MACjC,IAAO,EAAK,MAAM,SAAS,EAAU,MAAM,EAAU,EAAE;GAC7D,UAAU,UAAU,UAAU,CAAI;EACtC;CACJ;CACA;EACI,OAAO;EACP,QAAQ,OAAO,MAAS;GACpB,IAAM,IAAO,MAAM,UAAU,UAAU,SAAS,GAC1C,IAAY,EAAK,MAAM,UAAU;GACvC,EAAK,SAAS,EACV,SAAS;IAAE,MAAM,EAAU;IAAM,IAAI,EAAU;IAAI,QAAQ;GAAK,EACpE,CAAC;EACL;CACJ;CACA;EAAE,OAAO;EAAI,cAAc,CAAE;EAAG,WAAW;CAAK;CAChD;EACI,OAAO;EACP,SAAS,MAAS;GACd,EAAK,SAAS,EACV,WAAW;IAAE,QAAQ;IAAG,MAAM,EAAK,MAAM,IAAI;GAAO,EACxD,CAAC;EACL;CACJ;CACA;EACI,OAAO;EACP,SAAS,MAAS;GACd,IAAM,IAAc,EAAK,IAAI,cAAc,YAAY;GACvD,AAAI,KACA,EAA6B,MAAM;EAE3C;CACJ;AACJ"}
1
+ {"version":3,"file":"contextMenu.js","names":["defaultContextMenu","selection","view","text","searchPanel"],"sources":["../../../../../src/components/pro/CodeEditor/extensions/contextMenu.ts"],"sourcesContent":["import type { ContextMenuItem } from '../types';\nimport type { EditorView } from '@codemirror/view';\n\n// 默认上下文菜单\nexport const defaultContextMenu: ContextMenuItem[] = [\n {\n label: '剪切',\n action: (view) => {\n const selection = view.state.selection.main;\n const text = view.state.sliceDoc(selection.from, selection.to);\n navigator.clipboard.writeText(text);\n view.dispatch({\n changes: { from: selection.from, to: selection.to, insert: '' },\n });\n },\n },\n {\n label: '复制',\n action: (view) => {\n const selection = view.state.selection.main;\n const text = view.state.sliceDoc(selection.from, selection.to);\n navigator.clipboard.writeText(text);\n },\n },\n {\n label: '粘贴',\n action: async (view) => {\n const text = await navigator.clipboard.readText();\n const selection = view.state.selection.main;\n view.dispatch({\n changes: { from: selection.from, to: selection.to, insert: text },\n });\n },\n },\n { label: '', action: () => { }, separator: true },\n {\n label: '全选',\n action: (view) => {\n view.dispatch({\n selection: { anchor: 0, head: view.state.doc.length },\n });\n },\n },\n {\n label: '查找',\n action: (view) => {\n const searchPanel = view.dom.querySelector('.cm-search');\n if (searchPanel) {\n (searchPanel as HTMLElement).focus();\n }\n },\n },\n];\n\n"],"mappings":";AAIA,IAAaA,IAAwC;CACjD;EACI,OAAO;EACP,SAAS,MAAS;GACd,IAAMC,IAAYC,EAAK,MAAM,UAAU,MACjCC,IAAOD,EAAK,MAAM,SAASD,EAAU,MAAMA,EAAU,EAAE;GAE7D,AADA,UAAU,UAAU,UAAUE,CAAI,GAClCD,EAAK,SAAS,EACV,SAAS;IAAE,MAAMD,EAAU;IAAM,IAAIA,EAAU;IAAI,QAAQ;GAAG,EAClE,CAAC;EACL;CACJ;CACA;EACI,OAAO;EACP,SAAS,MAAS;GACd,IAAMA,IAAYC,EAAK,MAAM,UAAU,MACjCC,IAAOD,EAAK,MAAM,SAASD,EAAU,MAAMA,EAAU,EAAE;GAC7D,UAAU,UAAU,UAAUE,CAAI;EACtC;CACJ;CACA;EACI,OAAO;EACP,QAAQ,OAAO,MAAS;GACpB,IAAMA,IAAO,MAAM,UAAU,UAAU,SAAS,GAC1CF,IAAYC,EAAK,MAAM,UAAU;GACvC,EAAK,SAAS,EACV,SAAS;IAAE,MAAMD,EAAU;IAAM,IAAIA,EAAU;IAAI,QAAQE;GAAK,EACpE,CAAC;EACL;CACJ;CACA;EAAE,OAAO;EAAI,cAAc,CAAE;EAAG,WAAW;CAAK;CAChD;EACI,OAAO;EACP,SAAS,MAAS;GACd,EAAK,SAAS,EACV,WAAW;IAAE,QAAQ;IAAG,MAAMD,EAAK,MAAM,IAAI;GAAO,EACxD,CAAC;EACL;CACJ;CACA;EACI,OAAO;EACP,SAAS,MAAS;GACd,IAAME,IAAcF,EAAK,IAAI,cAAc,YAAY;GACvD,AAAIE,KACAA,EAA6B,MAAM;EAE3C;CACJ;AACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/extensions/index.ts"],"sourcesContent":["import { Extension } from '@codemirror/state';\nimport { EditorView, ViewPlugin, ViewUpdate, Decoration, DecorationSet } from '@codemirror/view';\nimport { CompletionContext, CompletionResult, autocompletion } from '@codemirror/autocomplete';\nimport { AutocompletionConfig, JumpToDefinitionConfig, CodeSnippet } from '../types';\nimport { getDefaultSnippets, getLanguageKeywords } from '../langs';\n\n// ============= 跳转到定义 =============\n\ninterface DefinitionPattern {\n pattern: RegExp;\n language?: string[];\n}\n\nconst defaultDefinitionPatterns: DefinitionPattern[] = [\n { pattern: /(?:function|const|let|var)\\s+IDENTIFIER\\s*[=(]/, language: ['javascript', 'typescript'] },\n { pattern: /class\\s+IDENTIFIER\\b/, language: ['javascript', 'typescript', 'python'] },\n { pattern: /interface\\s+IDENTIFIER\\b/, language: ['typescript'] },\n { pattern: /type\\s+IDENTIFIER\\b/, language: ['typescript'] },\n { pattern: /def\\s+IDENTIFIER\\s*\\(/, language: ['python'] },\n];\n\nconst findDefinition = (code: string, identifier: string, customFinder?: (code: string, id: string) => number): number => {\n if (customFinder) {\n return customFinder(code, identifier);\n }\n\n const lines = code.split('\\n');\n const escapedId = identifier.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n for (const defPattern of defaultDefinitionPatterns) {\n const patternStr = defPattern.pattern.source.replace('IDENTIFIER', escapedId);\n const regex = new RegExp(patternStr);\n\n for (let i = 0; i < lines.length; i++) {\n if (regex.test(lines[i])) {\n return i + 1;\n }\n }\n }\n\n return 0;\n};\n\nexport const jumpToDefinition = (\n onJump?: (line: number) => void,\n config: JumpToDefinitionConfig = {}\n) => {\n const {\n modifierKey = 'ctrl',\n highlightColor = 'rgba(59, 130, 246, 0.3)',\n customFinder\n } = config;\n\n let currentHighlight: { from: number; to: number } | null = null;\n\n return [\n // 点击跳转处理\n EditorView.domEventHandlers({\n mousedown: (event, view) => {\n const shouldTrigger = modifierKey === 'ctrl' \n ? (event.ctrlKey || event.metaKey)\n : event.altKey;\n \n if (shouldTrigger && event.button === 0) {\n const pos = view.posAtCoords({ x: event.clientX, y: event.clientY });\n if (pos !== null) {\n const word = view.state.wordAt(pos);\n if (word) {\n const wordText = view.state.sliceDoc(word.from, word.to);\n const line = findDefinition(view.state.doc.toString(), wordText, customFinder);\n if (line > 0 && onJump) {\n onJump(line);\n event.preventDefault();\n return true;\n }\n }\n }\n }\n return false;\n },\n }),\n \n // 悬浮高亮插件\n ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n modifierPressed: boolean;\n currentMousePos: number | null;\n\n constructor(view: EditorView) {\n this.decorations = Decoration.none;\n this.modifierPressed = false;\n this.currentMousePos = null;\n this.addEventListeners(view);\n }\n\n addEventListeners(view: EditorView) {\n // 监听键盘\n const handleKeyDown = (e: KeyboardEvent) => {\n const shouldHighlight = modifierKey === 'ctrl'\n ? (e.ctrlKey || e.metaKey)\n : e.altKey;\n \n if (shouldHighlight && !this.modifierPressed) {\n this.modifierPressed = true;\n if (this.currentMousePos !== null) {\n this.decorations = this.buildDecorations(view, this.currentMousePos);\n view.update([]);\n }\n }\n };\n\n const handleKeyUp = (e: KeyboardEvent) => {\n const wasModifier = modifierKey === 'ctrl'\n ? (e.key === 'Control' || e.key === 'Meta')\n : e.key === 'Alt';\n \n if (wasModifier) {\n this.modifierPressed = false;\n this.decorations = Decoration.none;\n view.update([]);\n }\n };\n\n // 监听鼠标移动\n const handleMouseMove = (e: MouseEvent) => {\n const pos = view.posAtCoords({ x: e.clientX, y: e.clientY });\n if (pos !== null) {\n this.currentMousePos = pos;\n if (this.modifierPressed) {\n this.decorations = this.buildDecorations(view, pos);\n view.update([]);\n }\n }\n };\n\n const handleMouseLeave = () => {\n this.currentMousePos = null;\n this.decorations = Decoration.none;\n if (this.modifierPressed) {\n view.update([]);\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n window.addEventListener('keyup', handleKeyUp);\n view.dom.addEventListener('mousemove', handleMouseMove);\n view.dom.addEventListener('mouseleave', handleMouseLeave);\n\n // 存储清理函数\n (this as any).cleanup = () => {\n window.removeEventListener('keydown', handleKeyDown);\n window.removeEventListener('keyup', handleKeyUp);\n view.dom.removeEventListener('mousemove', handleMouseMove);\n view.dom.removeEventListener('mouseleave', handleMouseLeave);\n };\n }\n\n update(update: ViewUpdate) {\n // 装饰在事件处理中更新,这里不需要额外操作\n }\n\n buildDecorations(view: EditorView, pos: number): DecorationSet {\n const word = view.state.wordAt(pos);\n if (!word) return Decoration.none;\n\n const wordText = view.state.sliceDoc(word.from, word.to);\n const line = findDefinition(view.state.doc.toString(), wordText, customFinder);\n \n // 只有找到定义时才高亮\n if (line > 0) {\n const jumpTargetMark = Decoration.mark({ class: 'cm-jump-target' });\n return Decoration.set([jumpTargetMark.range(word.from, word.to)]);\n }\n \n return Decoration.none;\n }\n\n destroy() {\n if ((this as any).cleanup) {\n (this as any).cleanup();\n }\n }\n },\n {\n decorations: (v) => v.decorations,\n }\n ),\n ];\n};\n\n// ============= 智能自动补全 =============\n\nexport const smartAutocompletion = (\n language: string,\n config: AutocompletionConfig = {}\n) => {\n const {\n keywords = getLanguageKeywords(language),\n snippets = getDefaultSnippets(language),\n customSource\n } = config;\n\n return autocompletion({\n override: [\n async (context: CompletionContext): Promise<CompletionResult | null> => {\n // 如果有自定义补全源,先尝试使用\n if (customSource) {\n const customResult = await Promise.resolve(customSource(context));\n if (customResult) return customResult;\n }\n\n const word = context.matchBefore(/\\w*/);\n if (!word || (word.from === word.to && !context.explicit)) {\n return null;\n }\n\n const options = [];\n\n // 关键字补全\n for (const keyword of keywords) {\n if (keyword.startsWith(word.text)) {\n options.push({\n label: keyword,\n type: 'keyword',\n boost: 2,\n });\n }\n }\n\n // 从文档中提取标识符\n const text = context.state.doc.toString();\n const identifiers = new Set<string>();\n const regex = language.includes('python')\n ? /\\b([a-zA-Z_][a-zA-Z0-9_]+)\\b/g\n : /\\b([a-zA-Z_$][a-zA-Z0-9_$]+)\\b/g;\n\n let match;\n while ((match = regex.exec(text)) !== null) {\n if (match[1].length > 2 && !keywords.includes(match[1])) {\n identifiers.add(match[1]);\n }\n }\n\n // 添加标识符补全\n for (const identifier of identifiers) {\n if (identifier.startsWith(word.text) && identifier !== word.text) {\n options.push({\n label: identifier,\n type: 'variable',\n boost: 1,\n });\n }\n }\n\n // 代码片段补全\n for (const snippet of snippets) {\n if (snippet.label.startsWith(word.text)) {\n options.push(snippet);\n }\n }\n\n return {\n from: word.from,\n options,\n };\n },\n ],\n });\n};\n\n// ============= 样式主题 =============\n\nexport const bracketMatchingStyle = EditorView.baseTheme({\n '&light .cm-matchingBracket': { backgroundColor: '#d7d4f0' },\n '&dark .cm-matchingBracket': { backgroundColor: '#515a6b' },\n});\n\nexport const lineHighlightStyle = EditorView.baseTheme({\n '.cm-line': {\n padding: '0 4px',\n },\n});\n\n// ============= 高亮跳转目标样式 =============\n\nexport const jumpTargetHighlight = EditorView.baseTheme({\n '.cm-jump-target': {\n backgroundColor: 'rgba(59, 130, 246, 0.15)',\n borderBottom: '1px solid rgba(59, 130, 246, 0.8)',\n cursor: 'pointer',\n textDecoration: 'underline',\n textDecorationColor: 'rgba(59, 130, 246, 0.6)',\n textDecorationStyle: 'dotted',\n transition: 'all 0.15s ease',\n },\n '.cm-jump-target:hover': {\n backgroundColor: 'rgba(59, 130, 246, 0.25)',\n borderBottomColor: 'rgb(59, 130, 246)',\n textDecorationStyle: 'solid',\n },\n // 深色模式\n '&dark .cm-jump-target': {\n backgroundColor: 'rgba(96, 165, 250, 0.15)',\n borderBottomColor: 'rgba(96, 165, 250, 0.8)',\n textDecorationColor: 'rgba(96, 165, 250, 0.6)',\n },\n '&dark .cm-jump-target:hover': {\n backgroundColor: 'rgba(96, 165, 250, 0.25)',\n borderBottomColor: 'rgb(96, 165, 250)',\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["defaultDefinitionPatterns","findDefinition","customFinder","code","identifier","lines","escapedId","defPattern","patternStr","regex","i","jumpToDefinition","config","EditorView","modifierKey","event","pos","view","word","wordText","line","onJump","ViewPlugin","Decoration","handleKeyDown","e","handleKeyUp","handleMouseMove","handleMouseLeave","jumpTargetMark","v","smartAutocompletion","getLanguageKeywords","language","getDefaultSnippets","autocompletion","customSource","customResult","context","options","keyword","keywords","text","identifiers","match","snippet","snippets","bracketMatchingStyle","lineHighlightStyle","jumpTargetHighlight"],"sources":["../../../../../src/components/pro/CodeEditor/extensions/index.ts"],"sourcesContent":["import { Extension } from '@codemirror/state';\nimport { EditorView, ViewPlugin, ViewUpdate, Decoration, DecorationSet } from '@codemirror/view';\nimport { CompletionContext, CompletionResult, autocompletion } from '@codemirror/autocomplete';\nimport { AutocompletionConfig, JumpToDefinitionConfig, CodeSnippet } from '../types';\nimport { getDefaultSnippets, getLanguageKeywords } from '../langs';\n\n// ============= 跳转到定义 =============\n\ninterface DefinitionPattern {\n pattern: RegExp;\n language?: string[];\n}\n\nconst defaultDefinitionPatterns: DefinitionPattern[] = [\n { pattern: /(?:function|const|let|var)\\s+IDENTIFIER\\s*[=(]/, language: ['javascript', 'typescript'] },\n { pattern: /class\\s+IDENTIFIER\\b/, language: ['javascript', 'typescript', 'python'] },\n { pattern: /interface\\s+IDENTIFIER\\b/, language: ['typescript'] },\n { pattern: /type\\s+IDENTIFIER\\b/, language: ['typescript'] },\n { pattern: /def\\s+IDENTIFIER\\s*\\(/, language: ['python'] },\n];\n\nconst findDefinition = (code: string, identifier: string, customFinder?: (code: string, id: string) => number): number => {\n if (customFinder) {\n return customFinder(code, identifier);\n }\n\n const lines = code.split('\\n');\n const escapedId = identifier.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n for (const defPattern of defaultDefinitionPatterns) {\n const patternStr = defPattern.pattern.source.replace('IDENTIFIER', escapedId);\n const regex = new RegExp(patternStr);\n\n for (let i = 0; i < lines.length; i++) {\n if (regex.test(lines[i])) {\n return i + 1;\n }\n }\n }\n\n return 0;\n};\n\nexport const jumpToDefinition = (\n onJump?: (line: number) => void,\n config: JumpToDefinitionConfig = {}\n) => {\n const {\n modifierKey = 'ctrl',\n highlightColor = 'rgba(59, 130, 246, 0.3)',\n customFinder\n } = config;\n\n let currentHighlight: { from: number; to: number } | null = null;\n\n return [\n // 点击跳转处理\n EditorView.domEventHandlers({\n mousedown: (event, view) => {\n const shouldTrigger = modifierKey === 'ctrl' \n ? (event.ctrlKey || event.metaKey)\n : event.altKey;\n \n if (shouldTrigger && event.button === 0) {\n const pos = view.posAtCoords({ x: event.clientX, y: event.clientY });\n if (pos !== null) {\n const word = view.state.wordAt(pos);\n if (word) {\n const wordText = view.state.sliceDoc(word.from, word.to);\n const line = findDefinition(view.state.doc.toString(), wordText, customFinder);\n if (line > 0 && onJump) {\n onJump(line);\n event.preventDefault();\n return true;\n }\n }\n }\n }\n return false;\n },\n }),\n \n // 悬浮高亮插件\n ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n modifierPressed: boolean;\n currentMousePos: number | null;\n\n constructor(view: EditorView) {\n this.decorations = Decoration.none;\n this.modifierPressed = false;\n this.currentMousePos = null;\n this.addEventListeners(view);\n }\n\n addEventListeners(view: EditorView) {\n // 监听键盘\n const handleKeyDown = (e: KeyboardEvent) => {\n const shouldHighlight = modifierKey === 'ctrl'\n ? (e.ctrlKey || e.metaKey)\n : e.altKey;\n \n if (shouldHighlight && !this.modifierPressed) {\n this.modifierPressed = true;\n if (this.currentMousePos !== null) {\n this.decorations = this.buildDecorations(view, this.currentMousePos);\n view.update([]);\n }\n }\n };\n\n const handleKeyUp = (e: KeyboardEvent) => {\n const wasModifier = modifierKey === 'ctrl'\n ? (e.key === 'Control' || e.key === 'Meta')\n : e.key === 'Alt';\n \n if (wasModifier) {\n this.modifierPressed = false;\n this.decorations = Decoration.none;\n view.update([]);\n }\n };\n\n // 监听鼠标移动\n const handleMouseMove = (e: MouseEvent) => {\n const pos = view.posAtCoords({ x: e.clientX, y: e.clientY });\n if (pos !== null) {\n this.currentMousePos = pos;\n if (this.modifierPressed) {\n this.decorations = this.buildDecorations(view, pos);\n view.update([]);\n }\n }\n };\n\n const handleMouseLeave = () => {\n this.currentMousePos = null;\n this.decorations = Decoration.none;\n if (this.modifierPressed) {\n view.update([]);\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n window.addEventListener('keyup', handleKeyUp);\n view.dom.addEventListener('mousemove', handleMouseMove);\n view.dom.addEventListener('mouseleave', handleMouseLeave);\n\n // 存储清理函数\n (this as any).cleanup = () => {\n window.removeEventListener('keydown', handleKeyDown);\n window.removeEventListener('keyup', handleKeyUp);\n view.dom.removeEventListener('mousemove', handleMouseMove);\n view.dom.removeEventListener('mouseleave', handleMouseLeave);\n };\n }\n\n update(update: ViewUpdate) {\n // 装饰在事件处理中更新,这里不需要额外操作\n }\n\n buildDecorations(view: EditorView, pos: number): DecorationSet {\n const word = view.state.wordAt(pos);\n if (!word) return Decoration.none;\n\n const wordText = view.state.sliceDoc(word.from, word.to);\n const line = findDefinition(view.state.doc.toString(), wordText, customFinder);\n \n // 只有找到定义时才高亮\n if (line > 0) {\n const jumpTargetMark = Decoration.mark({ class: 'cm-jump-target' });\n return Decoration.set([jumpTargetMark.range(word.from, word.to)]);\n }\n \n return Decoration.none;\n }\n\n destroy() {\n if ((this as any).cleanup) {\n (this as any).cleanup();\n }\n }\n },\n {\n decorations: (v) => v.decorations,\n }\n ),\n ];\n};\n\n// ============= 智能自动补全 =============\n\nexport const smartAutocompletion = (\n language: string,\n config: AutocompletionConfig = {}\n) => {\n const {\n keywords = getLanguageKeywords(language),\n snippets = getDefaultSnippets(language),\n customSource\n } = config;\n\n return autocompletion({\n override: [\n async (context: CompletionContext): Promise<CompletionResult | null> => {\n // 如果有自定义补全源,先尝试使用\n if (customSource) {\n const customResult = await Promise.resolve(customSource(context));\n if (customResult) return customResult;\n }\n\n const word = context.matchBefore(/\\w*/);\n if (!word || (word.from === word.to && !context.explicit)) {\n return null;\n }\n\n const options = [];\n\n // 关键字补全\n for (const keyword of keywords) {\n if (keyword.startsWith(word.text)) {\n options.push({\n label: keyword,\n type: 'keyword',\n boost: 2,\n });\n }\n }\n\n // 从文档中提取标识符\n const text = context.state.doc.toString();\n const identifiers = new Set<string>();\n const regex = language.includes('python')\n ? /\\b([a-zA-Z_][a-zA-Z0-9_]+)\\b/g\n : /\\b([a-zA-Z_$][a-zA-Z0-9_$]+)\\b/g;\n\n let match;\n while ((match = regex.exec(text)) !== null) {\n if (match[1].length > 2 && !keywords.includes(match[1])) {\n identifiers.add(match[1]);\n }\n }\n\n // 添加标识符补全\n for (const identifier of identifiers) {\n if (identifier.startsWith(word.text) && identifier !== word.text) {\n options.push({\n label: identifier,\n type: 'variable',\n boost: 1,\n });\n }\n }\n\n // 代码片段补全\n for (const snippet of snippets) {\n if (snippet.label.startsWith(word.text)) {\n options.push(snippet);\n }\n }\n\n return {\n from: word.from,\n options,\n };\n },\n ],\n });\n};\n\n// ============= 样式主题 =============\n\nexport const bracketMatchingStyle = EditorView.baseTheme({\n '&light .cm-matchingBracket': { backgroundColor: '#d7d4f0' },\n '&dark .cm-matchingBracket': { backgroundColor: '#515a6b' },\n});\n\nexport const lineHighlightStyle = EditorView.baseTheme({\n '.cm-line': {\n padding: '0 4px',\n },\n});\n\n// ============= 高亮跳转目标样式 =============\n\nexport const jumpTargetHighlight = EditorView.baseTheme({\n '.cm-jump-target': {\n backgroundColor: 'rgba(59, 130, 246, 0.15)',\n borderBottom: '1px solid rgba(59, 130, 246, 0.8)',\n cursor: 'pointer',\n textDecoration: 'underline',\n textDecorationColor: 'rgba(59, 130, 246, 0.6)',\n textDecorationStyle: 'dotted',\n transition: 'all 0.15s ease',\n },\n '.cm-jump-target:hover': {\n backgroundColor: 'rgba(59, 130, 246, 0.25)',\n borderBottomColor: 'rgb(59, 130, 246)',\n textDecorationStyle: 'solid',\n },\n // 深色模式\n '&dark .cm-jump-target': {\n backgroundColor: 'rgba(96, 165, 250, 0.15)',\n borderBottomColor: 'rgba(96, 165, 250, 0.8)',\n textDecorationColor: 'rgba(96, 165, 250, 0.6)',\n },\n '&dark .cm-jump-target:hover': {\n backgroundColor: 'rgba(96, 165, 250, 0.25)',\n borderBottomColor: 'rgb(96, 165, 250)',\n },\n});\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/langs/index.ts"],"sourcesContent":["// 语言配置统一导出\nexport * from './snippets';\nexport * from './javascript';\nexport * from './python';\n\nimport { jsKeywords, jsJumpableKeywords } from './javascript';\nimport { pyKeywords, pyJumpableKeywords } from './python';\n\n// 获取语言关键字\nexport const getLanguageKeywords = (language: string): string[] => {\n if (language.includes('python')) {\n return pyKeywords;\n }\n return jsKeywords;\n};\n\n// 获取可跳转关键字\nexport const getJumpableKeywords = (language: string): string[] => {\n if (language.includes('python')) {\n return pyJumpableKeywords;\n }\n return jsJumpableKeywords;\n};\n\n"],"mappings":";;;;AASA,IAAa,KAAuB,MAC9B,EAAS,SAAS,QAAQ,IACrB,IAEF,GAII,KAAuB,MAC9B,EAAS,SAAS,QAAQ,IACrB,IAEF"}
1
+ {"version":3,"file":"index.js","names":["getLanguageKeywords","language","pyKeywords","jsKeywords","getJumpableKeywords","pyJumpableKeywords","jsJumpableKeywords","getDefaultSnippets","javascriptSnippets","pythonSnippets"],"sources":["../../../../../src/components/pro/CodeEditor/langs/index.ts"],"sourcesContent":["// 语言配置统一导出\nexport * from './snippets';\nexport * from './javascript';\nexport * from './python';\n\nimport { jsKeywords, jsJumpableKeywords } from './javascript';\nimport { pyKeywords, pyJumpableKeywords } from './python';\n\n// 获取语言关键字\nexport const getLanguageKeywords = (language: string): string[] => {\n if (language.includes('python')) {\n return pyKeywords;\n }\n return jsKeywords;\n};\n\n// 获取可跳转关键字\nexport const getJumpableKeywords = (language: string): string[] => {\n if (language.includes('python')) {\n return pyJumpableKeywords;\n }\n return jsJumpableKeywords;\n};\n\n"],"mappings":";;;;AASA,IAAaA,KAAuB,MAC9BC,EAAS,SAAS,QAAQ,IACrBC,IAEFC,GAIIC,KAAuB,MAC9BH,EAAS,SAAS,QAAQ,IACrBI,IAEFC"}
@@ -1 +1 @@
1
- {"version":3,"file":"javascript.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/langs/javascript.ts"],"sourcesContent":["// JavaScript/TypeScript 语言配置\nexport const jsKeywords = [\n 'function', 'const', 'let', 'var', 'if', 'else', 'for', 'while', 'do', 'switch',\n 'case', 'break', 'continue', 'return', 'try', 'catch', 'finally', 'throw',\n 'class', 'extends', 'import', 'export', 'default', 'async', 'await', 'new',\n 'this', 'super', 'static', 'get', 'set', 'typeof', 'instanceof', 'in', 'of',\n];\n\n// 可跳转的关键字(函数、类、接口等定义)\nexport const jsJumpableKeywords = [\n 'function',\n 'class',\n 'interface',\n 'type',\n 'const',\n 'let',\n 'var',\n];\n\n// 定义模式\nexport const jsDefinitionPatterns = [\n { pattern: /(?:function|const|let|var)\\s+IDENTIFIER\\s*[=(]/ },\n { pattern: /class\\s+IDENTIFIER\\b/ },\n { pattern: /interface\\s+IDENTIFIER\\b/ },\n { pattern: /type\\s+IDENTIFIER\\b/ },\n];\n\n\n"],"mappings":";AACA,IAAa,IAAa,uOAK1B,GAGa,IAAqB;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"javascript.js","names":["jsKeywords","jsJumpableKeywords"],"sources":["../../../../../src/components/pro/CodeEditor/langs/javascript.ts"],"sourcesContent":["// JavaScript/TypeScript 语言配置\nexport const jsKeywords = [\n 'function', 'const', 'let', 'var', 'if', 'else', 'for', 'while', 'do', 'switch',\n 'case', 'break', 'continue', 'return', 'try', 'catch', 'finally', 'throw',\n 'class', 'extends', 'import', 'export', 'default', 'async', 'await', 'new',\n 'this', 'super', 'static', 'get', 'set', 'typeof', 'instanceof', 'in', 'of',\n];\n\n// 可跳转的关键字(函数、类、接口等定义)\nexport const jsJumpableKeywords = [\n 'function',\n 'class',\n 'interface',\n 'type',\n 'const',\n 'let',\n 'var',\n];\n\n// 定义模式\nexport const jsDefinitionPatterns = [\n { pattern: /(?:function|const|let|var)\\s+IDENTIFIER\\s*[=(]/ },\n { pattern: /class\\s+IDENTIFIER\\b/ },\n { pattern: /interface\\s+IDENTIFIER\\b/ },\n { pattern: /type\\s+IDENTIFIER\\b/ },\n];\n\n\n"],"mappings":";AACA,IAAaA,IAAa,uOAK1B,GAGaC,IAAqB;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"python.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/langs/python.ts"],"sourcesContent":["// Python 语言配置\nexport const pyKeywords = [\n 'def', 'class', 'if', 'elif', 'else', 'for', 'while', 'break', 'continue',\n 'return', 'try', 'except', 'finally', 'raise', 'import', 'from', 'as',\n 'with', 'pass', 'lambda', 'yield', 'async', 'await', 'assert', 'del',\n 'global', 'nonlocal', 'True', 'False', 'None', 'and', 'or', 'not', 'is',\n];\n\n// 可跳转的关键字\nexport const pyJumpableKeywords = [\n 'def',\n 'class',\n];\n\n// 定义模式\nexport const pyDefinitionPatterns = [\n { pattern: /def\\s+IDENTIFIER\\s*\\(/ },\n { pattern: /class\\s+IDENTIFIER\\b/ },\n];\n\n\n"],"mappings":";AACA,IAAa,IAAa,sNAK1B,GAGa,IAAqB,CAChC,OACA,OACF"}
1
+ {"version":3,"file":"python.js","names":["pyKeywords","pyJumpableKeywords"],"sources":["../../../../../src/components/pro/CodeEditor/langs/python.ts"],"sourcesContent":["// Python 语言配置\nexport const pyKeywords = [\n 'def', 'class', 'if', 'elif', 'else', 'for', 'while', 'break', 'continue',\n 'return', 'try', 'except', 'finally', 'raise', 'import', 'from', 'as',\n 'with', 'pass', 'lambda', 'yield', 'async', 'await', 'assert', 'del',\n 'global', 'nonlocal', 'True', 'False', 'None', 'and', 'or', 'not', 'is',\n];\n\n// 可跳转的关键字\nexport const pyJumpableKeywords = [\n 'def',\n 'class',\n];\n\n// 定义模式\nexport const pyDefinitionPatterns = [\n { pattern: /def\\s+IDENTIFIER\\s*\\(/ },\n { pattern: /class\\s+IDENTIFIER\\b/ },\n];\n\n\n"],"mappings":";AACA,IAAaA,IAAa,sNAK1B,GAGaC,IAAqB,CAChC,OACA,OACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"snippets.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/langs/snippets.ts"],"sourcesContent":["// 默认代码片段集合\nimport { CodeSnippet } from '../types';\n\n// JavaScript/TypeScript 片段\nexport const javascriptSnippets: CodeSnippet[] = [\n { label: 'log', detail: 'console.log()', apply: 'console.log(${})' },\n { label: 'func', detail: 'function', apply: 'function ${}() {\\n \\n}' },\n { label: 'arrow', detail: 'arrow function', apply: '(${}}) => {\\n \\n}' },\n { label: 'if', detail: 'if statement', apply: 'if (${}}) {\\n \\n}' },\n { label: 'for', detail: 'for loop', apply: 'for (let i = 0; i < ${}; i++) {\\n \\n}' },\n { label: 'foreach', detail: 'forEach', apply: '${}}.forEach((item) => {\\n \\n})' },\n { label: 'map', detail: 'map', apply: '${}}.map((item) => {\\n return item;\\n})' },\n { label: 'filter', detail: 'filter', apply: '${}}.filter((item) => {\\n return true;\\n})' },\n { label: 'try', detail: 'try-catch', apply: 'try {\\n ${}\\n} catch (error) {\\n console.error(error);\\n}' },\n { label: 'class', detail: 'class', apply: 'class ${} {\\n constructor() {\\n \\n }\\n}' },\n { label: 'import', detail: 'import', apply: 'import ${} from \\'${}\\'', boost: 2 },\n { label: 'export', detail: 'export', apply: 'export { ${} }', boost: 2 },\n];\n\n// Python 片段\nexport const pythonSnippets: CodeSnippet[] = [\n { label: 'print', detail: 'print()', apply: 'print(${}})' },\n { label: 'def', detail: 'function', apply: 'def ${}():\\n pass' },\n { label: 'class', detail: 'class', apply: 'class ${}:\\n def __init__(self):\\n pass' },\n { label: 'if', detail: 'if statement', apply: 'if ${}:\\n pass' },\n { label: 'for', detail: 'for loop', apply: 'for item in ${}:\\n pass' },\n { label: 'while', detail: 'while loop', apply: 'while ${}:\\n pass' },\n { label: 'try', detail: 'try-except', apply: 'try:\\n ${}\\nexcept Exception as e:\\n print(e)' },\n { label: 'with', detail: 'with statement', apply: 'with ${} as f:\\n pass' },\n { label: 'import', detail: 'import', apply: 'import ${}', boost: 2 },\n { label: 'from', detail: 'from import', apply: 'from ${} import ${}', boost: 2 },\n];\n\n// 获取语言默认片段\nexport const getDefaultSnippets = (language: string): CodeSnippet[] => {\n if (language.includes('javascript') || language.includes('typescript')) {\n return javascriptSnippets;\n } else if (language.includes('python')) {\n return pythonSnippets;\n }\n return [];\n};\n\n"],"mappings":";AAIA,IAAa,IAAoC;CAC/C;EAAE,OAAO;EAAO,QAAQ;EAAiB,OAAO;CAAmB;CACnE;EAAE,OAAO;EAAQ,QAAQ;EAAY,OAAO;CAA0B;CACtE;EAAE,OAAO;EAAS,QAAQ;EAAkB,OAAO;CAAqB;CACxE;EAAE,OAAO;EAAM,QAAQ;EAAgB,OAAO;CAAqB;CACnE;EAAE,OAAO;EAAO,QAAQ;EAAY,OAAO;CAAyC;CACpF;EAAE,OAAO;EAAW,QAAQ;EAAW,OAAO;CAAmC;CACjF;EAAE,OAAO;EAAO,QAAQ;EAAO,OAAO;CAA2C;CACjF;EAAE,OAAO;EAAU,QAAQ;EAAU,OAAO;CAA8C;CAC1F;EAAE,OAAO;EAAO,QAAQ;EAAa,OAAO;CAA8D;CAC1G;EAAE,OAAO;EAAS,QAAQ;EAAS,OAAO;CAA+C;CACzF;EAAE,OAAO;EAAU,QAAQ;EAAU,OAAO;EAA2B,OAAO;CAAE;CAChF;EAAE,OAAO;EAAU,QAAQ;EAAU,OAAO;EAAkB,OAAO;CAAE;AACzE,GAGa,IAAgC;CAC3C;EAAE,OAAO;EAAS,QAAQ;EAAW,OAAO;CAAc;CAC1D;EAAE,OAAO;EAAO,QAAQ;EAAY,OAAO;CAAuB;CAClE;EAAE,OAAO;EAAS,QAAQ;EAAS,OAAO;CAAoD;CAC9F;EAAE,OAAO;EAAM,QAAQ;EAAgB,OAAO;CAAoB;CAClE;EAAE,OAAO;EAAO,QAAQ;EAAY,OAAO;CAA6B;CACxE;EAAE,OAAO;EAAS,QAAQ;EAAc,OAAO;CAAuB;CACtE;EAAE,OAAO;EAAO,QAAQ;EAAc,OAAO;CAAsD;CACnG;EAAE,OAAO;EAAQ,QAAQ;EAAkB,OAAO;CAA2B;CAC7E;EAAE,OAAO;EAAU,QAAQ;EAAU,OAAO;EAAc,OAAO;CAAE;CACnE;EAAE,OAAO;EAAQ,QAAQ;EAAe,OAAO;EAAuB,OAAO;CAAE;AACjF,GAGa,KAAsB,MAC7B,EAAS,SAAS,YAAY,KAAK,EAAS,SAAS,YAAY,IAC5D,IACE,EAAS,SAAS,QAAQ,IAC5B,IAEF,CAAC"}
1
+ {"version":3,"file":"snippets.js","names":["javascriptSnippets","pythonSnippets","getDefaultSnippets","language"],"sources":["../../../../../src/components/pro/CodeEditor/langs/snippets.ts"],"sourcesContent":["// 默认代码片段集合\nimport { CodeSnippet } from '../types';\n\n// JavaScript/TypeScript 片段\nexport const javascriptSnippets: CodeSnippet[] = [\n { label: 'log', detail: 'console.log()', apply: 'console.log(${})' },\n { label: 'func', detail: 'function', apply: 'function ${}() {\\n \\n}' },\n { label: 'arrow', detail: 'arrow function', apply: '(${}}) => {\\n \\n}' },\n { label: 'if', detail: 'if statement', apply: 'if (${}}) {\\n \\n}' },\n { label: 'for', detail: 'for loop', apply: 'for (let i = 0; i < ${}; i++) {\\n \\n}' },\n { label: 'foreach', detail: 'forEach', apply: '${}}.forEach((item) => {\\n \\n})' },\n { label: 'map', detail: 'map', apply: '${}}.map((item) => {\\n return item;\\n})' },\n { label: 'filter', detail: 'filter', apply: '${}}.filter((item) => {\\n return true;\\n})' },\n { label: 'try', detail: 'try-catch', apply: 'try {\\n ${}\\n} catch (error) {\\n console.error(error);\\n}' },\n { label: 'class', detail: 'class', apply: 'class ${} {\\n constructor() {\\n \\n }\\n}' },\n { label: 'import', detail: 'import', apply: 'import ${} from \\'${}\\'', boost: 2 },\n { label: 'export', detail: 'export', apply: 'export { ${} }', boost: 2 },\n];\n\n// Python 片段\nexport const pythonSnippets: CodeSnippet[] = [\n { label: 'print', detail: 'print()', apply: 'print(${}})' },\n { label: 'def', detail: 'function', apply: 'def ${}():\\n pass' },\n { label: 'class', detail: 'class', apply: 'class ${}:\\n def __init__(self):\\n pass' },\n { label: 'if', detail: 'if statement', apply: 'if ${}:\\n pass' },\n { label: 'for', detail: 'for loop', apply: 'for item in ${}:\\n pass' },\n { label: 'while', detail: 'while loop', apply: 'while ${}:\\n pass' },\n { label: 'try', detail: 'try-except', apply: 'try:\\n ${}\\nexcept Exception as e:\\n print(e)' },\n { label: 'with', detail: 'with statement', apply: 'with ${} as f:\\n pass' },\n { label: 'import', detail: 'import', apply: 'import ${}', boost: 2 },\n { label: 'from', detail: 'from import', apply: 'from ${} import ${}', boost: 2 },\n];\n\n// 获取语言默认片段\nexport const getDefaultSnippets = (language: string): CodeSnippet[] => {\n if (language.includes('javascript') || language.includes('typescript')) {\n return javascriptSnippets;\n } else if (language.includes('python')) {\n return pythonSnippets;\n }\n return [];\n};\n\n"],"mappings":";AAIA,IAAaA,IAAoC;CAC/C;EAAE,OAAO;EAAO,QAAQ;EAAiB,OAAO;CAAmB;CACnE;EAAE,OAAO;EAAQ,QAAQ;EAAY,OAAO;CAA0B;CACtE;EAAE,OAAO;EAAS,QAAQ;EAAkB,OAAO;CAAqB;CACxE;EAAE,OAAO;EAAM,QAAQ;EAAgB,OAAO;CAAqB;CACnE;EAAE,OAAO;EAAO,QAAQ;EAAY,OAAO;CAAyC;CACpF;EAAE,OAAO;EAAW,QAAQ;EAAW,OAAO;CAAmC;CACjF;EAAE,OAAO;EAAO,QAAQ;EAAO,OAAO;CAA2C;CACjF;EAAE,OAAO;EAAU,QAAQ;EAAU,OAAO;CAA8C;CAC1F;EAAE,OAAO;EAAO,QAAQ;EAAa,OAAO;CAA8D;CAC1G;EAAE,OAAO;EAAS,QAAQ;EAAS,OAAO;CAA+C;CACzF;EAAE,OAAO;EAAU,QAAQ;EAAU,OAAO;EAA2B,OAAO;CAAE;CAChF;EAAE,OAAO;EAAU,QAAQ;EAAU,OAAO;EAAkB,OAAO;CAAE;AACzE,GAGaC,IAAgC;CAC3C;EAAE,OAAO;EAAS,QAAQ;EAAW,OAAO;CAAc;CAC1D;EAAE,OAAO;EAAO,QAAQ;EAAY,OAAO;CAAuB;CAClE;EAAE,OAAO;EAAS,QAAQ;EAAS,OAAO;CAAoD;CAC9F;EAAE,OAAO;EAAM,QAAQ;EAAgB,OAAO;CAAoB;CAClE;EAAE,OAAO;EAAO,QAAQ;EAAY,OAAO;CAA6B;CACxE;EAAE,OAAO;EAAS,QAAQ;EAAc,OAAO;CAAuB;CACtE;EAAE,OAAO;EAAO,QAAQ;EAAc,OAAO;CAAsD;CACnG;EAAE,OAAO;EAAQ,QAAQ;EAAkB,OAAO;CAA2B;CAC7E;EAAE,OAAO;EAAU,QAAQ;EAAU,OAAO;EAAc,OAAO;CAAE;CACnE;EAAE,OAAO;EAAQ,QAAQ;EAAe,OAAO;EAAuB,OAAO;CAAE;AACjF,GAGaC,KAAsB,MAC7BC,EAAS,SAAS,YAAY,KAAKA,EAAS,SAAS,YAAY,IAC5DH,IACEG,EAAS,SAAS,QAAQ,IAC5BF,IAEF,CAAC"}