remons-markdown-editor 1.0.0-beta.2 → 1.0.0-beta.21

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 (34) hide show
  1. package/dist/App.d.ts +2 -0
  2. package/dist/MarkdownEditor.d.ts +23 -0
  3. package/dist/components/Dialog/EditDialog.d.ts +21 -0
  4. package/dist/components/Editor/codemirrorExtensions.d.ts +12 -0
  5. package/dist/components/Editor/containerWidget.d.ts +20 -0
  6. package/dist/components/Editor/index.d.ts +16 -0
  7. package/dist/components/Icon/index.d.ts +2 -0
  8. package/dist/components/Panel/SplitPanels.d.ts +7 -0
  9. package/dist/components/Preview/index.d.ts +10 -0
  10. package/dist/components/Toolbar/buttons.d.ts +59 -0
  11. package/dist/components/Toolbar/config.d.ts +6 -0
  12. package/dist/components/Toolbar/hooks/useToolbar.d.ts +14 -0
  13. package/dist/components/Toolbar/index.d.ts +13 -0
  14. package/dist/components/Toolbar/renderers/TablePicker/TableDropdown.d.ts +5 -0
  15. package/dist/components/Toolbar/renderers/TablePicker/index.d.ts +9 -0
  16. package/dist/components/Toolbar/renderers/ToolbarItemRenderer.d.ts +7 -0
  17. package/dist/hooks/useFullscreen.d.ts +4 -0
  18. package/dist/hooks/useRegisterToolbar.d.ts +101 -0
  19. package/dist/hooks/useScrollSync.d.ts +6 -0
  20. package/dist/index.cjs +1612 -1202
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.css +184 -113
  23. package/dist/index.d.ts +5 -98
  24. package/dist/index.js +1588 -1182
  25. package/dist/index.js.map +1 -1
  26. package/dist/main.d.ts +0 -0
  27. package/dist/registry/componentRegistry.d.ts +34 -0
  28. package/dist/types/index.d.ts +148 -0
  29. package/dist/utils/parseContainer.d.ts +18 -0
  30. package/dist/utils/writeContainer.d.ts +16 -0
  31. package/package.json +77 -81
  32. package/readme.md +309 -91
  33. package/dist/index.css.map +0 -1
  34. package/dist/index.d.cts +0 -98
package/readme.md CHANGED
@@ -1,91 +1,309 @@
1
- # remons-markdown-editor
2
-
3
- 基于 React 的 Markdown 编辑器组件,支持工具栏编辑、实时预览、同步滚动和自定义容器等功能。
4
-
5
- ## 安装
6
-
7
- ```bash
8
- npm install remons-markdown-editor
9
- ```
10
-
11
- ## 基本用法
12
-
13
- ```tsx
14
- import { MarkdownEditor } from 'remons-markdown-editor'
15
- import 'remons-markdown-editor/style.css'
16
-
17
- export default function App() {
18
- return <MarkdownEditor />
19
- }
20
- ```
21
-
22
- ## API
23
-
24
- ### MarkdownEditorProps
25
-
26
- | 属性名 | 类型 | 默认值 | 说明 |
27
- |--------|------|--------|------|
28
- | value | string | - | 受控模式下的内容 |
29
- | defaultValue | string | '' | 非受控模式下的初始内容 |
30
- | onChange | (value: string) => void | - | 内容变更回调 |
31
- | showPreview | boolean | true | 是否显示预览面板 |
32
- | fullscreen | boolean | false | 是否显示全屏按钮 |
33
-
34
- ### MarkdownEditorRef
35
-
36
- | 方法名 | 返回类型 | 说明 |
37
- |--------|----------|------|
38
- | getContent | () => string | 获取当前编辑器内容 |
39
-
40
- ## 自定义容器
41
-
42
- 通过 `useRegisterToolbar` hook 注册自定义容器组件,支持单个或批量注册:
43
-
44
- ```tsx
45
- import { MarkdownEditor, useRegisterToolbar } from 'remons-markdown-editor'
46
- import 'remons-markdown-editor/style.css'
47
-
48
- const schema = {
49
- name: 'alert',
50
- label: '警告框',
51
- icon: <AlertOutlined />,
52
- fields: [{ key: 'level', defaultValue: 'info' }],
53
- renderDialog: (props, onChange) => (
54
- <div>
55
- <input
56
- value={props.level}
57
- onChange={e => onChange('level', e.target.value)}
58
- />
59
- </div>
60
- ),
61
- }
62
-
63
- export default function App() {
64
- // 单个注册
65
- useRegisterToolbar(schema)
66
- return <MarkdownEditor />
67
- }
68
- ```
69
-
70
- ### 批量注册
71
-
72
- ```tsx
73
- export default function App() {
74
- useRegisterToolbar([schema1, schema2, schema3])
75
- return <MarkdownEditor />
76
- }
77
- ```
78
-
79
- ### ComponentSchema
80
-
81
- | 属性名 | 类型 | 必填 | 说明 |
82
- |--------|------|------|------|
83
- | name | string | 是 | 容器名称,对应 :::name 语法 |
84
- | label | string | 是 | 工具栏按钮显示的标签 |
85
- | icon | ReactNode | 否 | 工具栏按钮显示的图标,默认使用 ReadOutlined |
86
- | fields | DialogField[] | 是 | 弹窗属性字段配置 |
87
- | renderDialog | Function | 是 | 弹窗内容渲染函数,接收当前属性值和变更回调 |
88
-
89
- ## 依赖
90
-
91
- 此包需要 React 18 或 19 作为 peer dependency。
1
+ # remons-markdown-editor
2
+
3
+ 基于 React 的 Markdown 编辑器组件,支持工具栏编辑、实时预览、同步滚动和自定义容器等功能。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install remons-markdown-editor
9
+ ```
10
+
11
+ ## 基本用法
12
+
13
+ ```tsx
14
+ import { MarkdownEditor } from 'remons-markdown-editor'
15
+ import 'remons-markdown-editor/style.css'
16
+
17
+ export default function App() {
18
+ return <MarkdownEditor />
19
+ }
20
+ ```
21
+
22
+ ## API
23
+
24
+ ### MarkdownEditorProps
25
+
26
+ | 属性名 | 类型 | 默认值 | 说明 |
27
+ |--------|------|--------|------|
28
+ | value | string | - | 受控模式下的内容 |
29
+ | defaultValue | string | '' | 非受控模式下的初始内容 |
30
+ | onChange | (value: string) => void | - | 内容变更回调 |
31
+ | showPreview | boolean | true | 是否显示预览面板 |
32
+ | fullscreen | boolean | false | 是否显示全屏按钮 |
33
+ | previewOptions | PreviewOptions | - | 预览渲染配置,类型继承自 `RenderMarkdownProps` |
34
+ | uploadConfig | ImageUploadConfig | - | 图片上传配置 |
35
+
36
+ ### MarkdownEditorRef
37
+
38
+ | 方法名 | 返回类型 | 说明 |
39
+ |--------|----------|------|
40
+ | getContent | () => string | 获取当前编辑器内容 |
41
+
42
+ ### PreviewOptions
43
+
44
+ 预览渲染配置,类型继承自 `RenderMarkdownProps`(来自 `remons-render-markdown`),并扩展了 `languages` 字段:
45
+
46
+ ```typescript
47
+ import type { RenderMarkdownProps } from 'remons-render-markdown'
48
+
49
+ export type PreviewOptions = Omit<RenderMarkdownProps, 'content'> & {
50
+ languages?: Record<string, any> | null | undefined
51
+ }
52
+ ```
53
+
54
+ | 属性名 | 类型 | 默认值 | 说明 |
55
+ |--------|------|--------|------|
56
+ | languages | Record<string, any> | - | 自定义代码高亮语言配置 |
57
+ | customRenderers | MarkdownPlugin[] | - | 自定义 markdown-it 渲染插件 |
58
+ | excludedSelectors | string[] | - | 图片预览排除名单 |
59
+ | isSlotMermaid | boolean | - | 是否使用 slot 方式渲染 mermaid |
60
+ | isShowCollapsed | boolean | - | 是否显示代码折叠 |
61
+ | defaultCollapsed | boolean | - | 默认识否折叠代码 |
62
+ | showBackTop | boolean | - | 是否显示返回顶部 |
63
+ | isPrintPreview | boolean | - | 是否为打印模式 |
64
+ | mermaidDebounce | number | - | Mermaid 渲染防抖延迟(ms) |
65
+ | cdn | Record<string, string> | - | 自定义 CDN 配置 |
66
+ | chartConfig | (text: string) => string | - | 渲染前文本修改函数 |
67
+ | languages | Record<string, any> | - | 自定义代码高亮语言配置 |
68
+
69
+ 更多配置请参考 [remons-render-markdown](https://github.com/liRemons/render-markdown)。
70
+
71
+ ### ImageUploadConfig
72
+
73
+ 图片上传配置:
74
+
75
+ | 属性名 | 类型 | 默认值 | 说明 |
76
+ |--------|------|--------|------|
77
+ | uploadUrl | string | - | 图片上传接口地址(需与 onUploadImage 二选一) |
78
+ | onUploadImage | (file: File) => Promise<string \| null> | - | 自定义图片上传函数(优先级高于 uploadUrl) |
79
+ | onGetUploadUrl | (result: any) => string \| null | - | 处理服务器返回结果的回调,用于自定义 URL 提取逻辑 |
80
+
81
+ ## 使用示例
82
+
83
+ ### 自定义预览配置
84
+
85
+ ```tsx
86
+ import { MarkdownEditor } from 'remons-markdown-editor'
87
+ import type { PreviewOptions } from 'remons-markdown-editor'
88
+ import { languagesCommon } from 'remons-render-markdown'
89
+ import 'remons-markdown-editor/style.css'
90
+
91
+ function App() {
92
+ const previewOptions: PreviewOptions = {
93
+ // 自定义高亮语言(在 languagesCommon 基础上扩展)
94
+ languages: {
95
+ ...languagesCommon,
96
+ // 添加自定义语言配置
97
+ },
98
+ // 自定义 markdown-it 插件,可使用 remons-markdown-plugins 按需导入
99
+ // 参考 https://github.com/liRemons/markdown-plugin
100
+ customRenderers: [
101
+ (md) => md.use(yourCustomPlugin)
102
+ ],
103
+ // 禁用 mermaid slot 渲染
104
+ isSlotMermaid: false,
105
+ // 自定义排除选择器
106
+ excludedSelectors: ['.my-custom-class'],
107
+ }
108
+
109
+ return <MarkdownEditor previewOptions={previewOptions} />
110
+ }
111
+ ```
112
+
113
+ ### 自定义图片上传
114
+
115
+ ```tsx
116
+ import { MarkdownEditor } from 'remons-markdown-editor'
117
+ import type { ImageUploadConfig } from 'remons-markdown-editor'
118
+ import 'remons-markdown-editor/style.css'
119
+
120
+ function App() {
121
+ // 方式一:配置上传地址
122
+ const uploadConfig: ImageUploadConfig = {
123
+ uploadUrl: 'https://your-api.com/upload/image'
124
+ }
125
+ return <MarkdownEditor uploadConfig={uploadConfig} />
126
+
127
+ // 方式二:自定义上传函数(完全接管上传逻辑)
128
+ const customUpload: ImageUploadConfig = {
129
+ onUploadImage: async (file) => {
130
+ const formData = new FormData()
131
+ formData.append('file', file)
132
+
133
+ const response = await fetch('/api/upload', {
134
+ method: 'POST',
135
+ body: formData,
136
+ headers: {
137
+ 'Authorization': 'Bearer your-token'
138
+ }
139
+ })
140
+
141
+ const result = await response.json()
142
+ // 返回图片 URL,失败返回 null
143
+ return result.url || null
144
+ }
145
+ }
146
+ return <MarkdownEditor uploadConfig={customUpload} />
147
+
148
+ // 方式三:自定义 URL 提取逻辑(服务器返回相对路径时)
149
+ const uploadWithTransform: ImageUploadConfig = {
150
+ uploadUrl: 'https://your-api.com/upload/image',
151
+ onGetUploadUrl: (result) => {
152
+ const path = result.data?.path
153
+ // 如果返回的是相对路径,拼接为完整 URL
154
+ if (path && path.startsWith('/')) {
155
+ return `https://your-api.com${path}`
156
+ }
157
+ return path || null
158
+ }
159
+ }
160
+ return <MarkdownEditor uploadConfig={uploadWithTransform} />
161
+ }
162
+ ```
163
+
164
+ `uploadUrl` 或 `onUploadImage` 至少需要配置一个,否则图片上传按钮将被禁用。
165
+
166
+ - **uploadUrl**:配置后,编辑器会使用 `FormData` 格式发送 `POST` 请求,`file` 字段为图片文件。接口返回的 `data.path` 将作为图片地址。
167
+ - **onUploadImage**:自定义上传函数,完全接管上传逻辑。接收 `File` 对象,返回 `Promise<string | null>`,返回的图片 URL 会直接插入到编辑器中。
168
+ - **onGetUploadUrl**:处理服务器返回结果的回调,用于自定义 URL 提取逻辑。当服务器返回的数据格式与默认格式不一致时,可通过此回调提取和转换 URL。
169
+
170
+ ### 自定义容器
171
+
172
+ 支持两种注册模式:
173
+
174
+ #### 自动表单模式(推荐)
175
+
176
+ 如果字段的 `componentType` 已配置,弹窗会自动生成对应表单,无需手动编写 `renderDialog`:
177
+
178
+ ```tsx
179
+ import { MarkdownEditor, useRegisterToolbar } from 'remons-markdown-editor'
180
+ import { AlertOutlined } from '@ant-design/icons'
181
+ import 'remons-markdown-editor/style.css'
182
+
183
+ const schema = {
184
+ name: 'alert',
185
+ label: '警告框',
186
+ icon: <AlertOutlined />,
187
+ fields: [
188
+ { key: 'type', name: '类型', componentType: 'select', defaultValue: 'info',
189
+ componentProps: { options: [
190
+ { label: '信息', value: 'info' },
191
+ { label: '成功', value: 'success' },
192
+ { label: '警告', value: 'warning' },
193
+ { label: '错误', value: 'error' },
194
+ ]} },
195
+ { key: 'content', name: '内容', componentType: 'textarea', defaultValue: '',
196
+ componentProps: { rows: 3 } },
197
+ { key: 'enabled', name: '启用', componentType: 'switch', defaultValue: true },
198
+ ],
199
+ }
200
+
201
+ export default function App() {
202
+ useRegisterToolbar(schema)
203
+ return <MarkdownEditor />
204
+ }
205
+ ```
206
+
207
+ 支持的 componentType:
208
+ - `input` - 文本输入框
209
+ - `textarea` - 多行文本框
210
+ - `number` - 数字输入框
211
+ - `select` - 下拉选择(需配置 `componentProps.options`)
212
+ - `switch` - 开关
213
+ - `slider` - 滑块
214
+ - `rate` - 评分
215
+ - `color` - 颜色选择器
216
+ - `date` - 日期选择
217
+ - `dateRange` - 日期范围选择
218
+
219
+ #### 容器模式(自定义渲染)
220
+
221
+ 插入 `:::name` 格式的容器,支持弹窗编辑属性。需要手动编写 `renderDialog` 自定义渲染弹窗内容:
222
+
223
+ ```tsx
224
+ import { MarkdownEditor, useRegisterToolbar } from 'remons-markdown-editor'
225
+ import 'remons-markdown-editor/style.css'
226
+
227
+ const schema = {
228
+ name: 'alert',
229
+ label: '警告框',
230
+ icon: <AlertOutlined />,
231
+ fields: [{ key: 'level', defaultValue: 'info' }],
232
+ renderDialog: (props, onChange) => (
233
+ <div>
234
+ <input
235
+ value={props.level}
236
+ onChange={e => onChange('level', e.target.value)}
237
+ />
238
+ </div>
239
+ ),
240
+ }
241
+
242
+ export default function App() {
243
+ useRegisterToolbar(schema)
244
+ return <MarkdownEditor />
245
+ }
246
+ ```
247
+
248
+ #### 标签包裹模式
249
+
250
+ 插入简单的标签包裹文本,如 `<plugin-container>...</plugin-container>`,适合不需要弹窗编辑的场景:
251
+
252
+ ```tsx
253
+ import { MarkdownEditor, useRegisterToolbar } from 'remons-markdown-editor'
254
+ import 'remons-markdown-editor/style.css'
255
+
256
+ export default function App() {
257
+ useRegisterToolbar({
258
+ name: 'plugin-container',
259
+ label: '自定义容器',
260
+ icon: <AlertOutlined />,
261
+ wrapTags: ['<plugin-container>', '</plugin-container>'],
262
+ })
263
+ return <MarkdownEditor />
264
+ }
265
+ ```
266
+
267
+ 点击对应按钮会自动切换(添加/移除)标签包裹。
268
+
269
+ ### 批量注册
270
+
271
+ ```tsx
272
+ export default function App() {
273
+ useRegisterToolbar([schema1, schema2, schema3])
274
+ return <MarkdownEditor />
275
+ }
276
+ ```
277
+
278
+ ### ComponentSchema
279
+
280
+ | 属性名 | 类型 | 必填 | 说明 |
281
+ |--------|------|------|------|
282
+ | name | string | 是 | 容器/组件名称 |
283
+ | label | string | 是 | 工具栏按钮显示的标签 |
284
+ | icon | ReactNode | 否 | 工具栏按钮显示的图标 |
285
+ | fields | DialogField[] | 容器模式可选(自动表单模式需要 componentType) | 弹窗属性字段配置 |
286
+ | renderDialog | Function | 容器模式可选(自动表单模式不需要) | 弹窗内容渲染函数 |
287
+ | wrapTags | [string, string] | 标签模式必填 | 开闭标签对,如 `['<tag>', '</tag>']` |
288
+
289
+ 注:`wrapTags` 模式下不需要 `fields` 和 `renderDialog`。两种模式只需配置一种。
290
+
291
+ 如果 `fields` 中的字段配置了 `componentType`,则会自动生成表单,无需 `renderDialog`。
292
+
293
+ ### DialogField
294
+
295
+ 弹窗属性字段配置:
296
+
297
+ | 属性名 | 类型 | 必填 | 说明 |
298
+ |--------|------|------|------|
299
+ | key | string | 是 | 字段唯一标识 |
300
+ | name | string | 否 | 字段标签(默认使用 key) |
301
+ | componentType | string | 否 | 组件类型,支持:`input`、`textarea`、`number`、`select`、`switch`、`slider`、`rate`、`color`、`date`、`dateRange` |
302
+ | componentProps | object | 否 | 传递给组件的属性 |
303
+ | defaultValue | any | 否 | 字段默认值 |
304
+
305
+ 当 `fields` 中的字段配置了 `componentType` 时,弹窗会自动生成对应表单,无需手动编写 `renderDialog`。
306
+
307
+ ## 依赖
308
+
309
+ 此包需要 React 18 作为 peer dependency。
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/Toolbar/renderers/TablePicker/index.module.less","../src/App.css"],"sourcesContent":[".container {\n padding: 4px;\n display: block;\n min-width: 200px;\n background: #fff;\n border: 1px solid #e5e7eb;\n border-radius: 6px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n}\n.grid {\n display: grid;\n gap: 2px;\n transition: all 0.1s ease;\n justify-content: flex-start;\n}\n.grid .cell {\n width: 24px;\n height: 24px;\n border: 1px solid #e8e8e8;\n border-radius: 2px;\n background: transparent;\n cursor: pointer;\n transition: all 0.1s ease;\n}\n.grid .cell.cellActive {\n border-color: #91caff;\n background: #ddf4ff;\n}\n.hint {\n padding: 12px 16px;\n color: #999;\n font-size: 12px;\n text-align: center;\n cursor: pointer;\n}\n.label {\n margin-top: 8px;\n font-size: 13px;\n color: #666;\n font-weight: 500;\n min-height: 20px;\n text-align: center;\n}\n","@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Noto+Sans+SC:wght@400;500;600;700&display=swap');\n\n\n.app {\n height: 100vh;\n display: flex;\n flex-direction: column;\n}\n\n.app.fullscreen {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 9999;\n background: #fff;\n width: 100vw;\n height: 100vh;\n}\n\n.toolbar {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n padding: 4px 8px;\n background: #f6f8fa;\n border-bottom: 1px solid #d0d7de;\n gap: 4px;\n overflow-x: auto;\n}\n\n.toolbar-group {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n\n.toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 32px;\n height: 32px;\n padding: 0 8px;\n border: none;\n border-radius: 6px;\n background: transparent;\n cursor: pointer;\n font-size: 16px;\n font-weight: 500;\n color: #24292f;\n transition: background-color 0.15s, color 0.15s;\n white-space: nowrap;\n}\n\n.toolbar-button:hover {\n background: #e1e4e8;\n color: #0969da;\n}\n\n.toolbar-button:active {\n background: #d0d7de;\n}\n\n.toolbar-button.ant-btn {\n min-width: 32px;\n height: 32px;\n padding: 0 8px;\n border-color: transparent !important;\n box-shadow: none !important;\n}\n\n.toolbar-button.ant-btn:hover {\n background: #e1e4e8;\n color: #0969da;\n border-color: transparent !important;\n box-shadow: none !important;\n}\n\n.toolbar-button.ant-btn:active {\n border-color: transparent !important;\n box-shadow: none !important;\n}\n\n:where(.css-dev-only-do-not-override-u6izyw).ant-btn:not(:disabled):not(.ant-btn-disabled):hover {\n border: none !important\n}\n\n.toolbar-separator {\n width: 1px;\n height: 24px;\n background: #d0d7de;\n margin: 0 4px;\n}\n\n.split-panels {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.split-panels .ant-splitter {\n height: 100%;\n}\n\n.split-panels .ant-splitter-panel {\n min-height: 0;\n}\n\n.editor {\n height: 100%;\n \n}\n\n.cm-scroller {\n font-family: Consolas,Inter,Noto Sans SC,-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Microsoft YaHei,sans-serif !important;\n}\n\n.cm-editor {\n height: 100%;\n}\n\n.preview {\n height: 100%;\n overflow: auto;\n}\n\n\n/* 通用容器基类 */\n.md-container {\n margin: 16px 0;\n border-radius: 6px;\n border: 1px solid #d0d7de;\n overflow: hidden;\n}\n\n/* 链接卡片 */\n.link-card {\n background: #f6f8fa;\n}\n\n.link-card-content {\n padding: 16px;\n}\n\n.link-card-title {\n margin: 0 0 4px;\n font-size: 16px;\n font-weight: 600;\n}\n\n.link-card-title a {\n color: #0969da;\n text-decoration: none;\n}\n\n.link-card-title a:hover {\n text-decoration: underline;\n}\n\n.link-card-desc {\n margin: 0;\n font-size: 14px;\n color: #57606a;\n line-height: 1.5;\n}\n\n.link-card-primary {\n background: #ddf4ff;\n border-color: #54aeff;\n}\n\n.link-card-primary .link-card-title a {\n color: #0550ae;\n}\n\n.link-card-warning {\n background: #fff8c5;\n border-color: #d4a72c;\n}\n\n.link-card-warning .link-card-title a {\n color: #7d4e00;\n}\n\n/* 注释组件 */\n.note {\n padding: 12px 16px;\n}\n\n.note-info {\n background: #ddf4ff;\n border-color: #54aeff;\n}\n\n.note-tip {\n background: #dafbe1;\n border-color: #4ac26b;\n}\n\n.note-warning {\n background: #fff8c5;\n border-color: #d4a72c;\n}\n\n.note-danger {\n background: #ffebe9;\n border-color: #fb857b;\n}\n\n.note-title {\n margin: 0 0 4px;\n font-size: 14px;\n font-weight: 600;\n}\n\n.note-text {\n font-size: 14px;\n line-height: 1.5;\n}\n\n/* 编辑弹窗样式 */\n.edit-dialog {\n padding: 8px 0;\n}\n\n.edit-dialog-field {\n margin-bottom: 16px;\n}\n\n.edit-dialog-label {\n display: block;\n margin-bottom: 6px;\n font-size: 14px;\n font-weight: 500;\n color: #24292f;\n}\n\n.edit-dialog-input {\n width: 100%;\n padding: 6px 10px;\n font-size: 14px;\n border: 1px solid #d0d7de;\n border-radius: 6px;\n outline: none;\n transition: border-color 0.15s;\n}\n\n.edit-dialog-input:focus {\n border-color: #0969da;\n box-shadow: 0 0 0 3px rgba(9, 105, 218, 0.1);\n}\n\n.edit-dialog-textarea {\n resize: vertical;\n font-family: inherit;\n}\n"],"mappings":";;;AAAA,CAAC;AACC,WAAS;AACT,WAAS;AACT,aAAW;AACX,cAAY;AACZ,UAAQ,IAAI,MAAM;AAClB,iBAAe;AACf,cAAY,EAAE,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACvC;AACA,CAAC;AACC,WAAS;AACT,OAAK;AACL,cAAY,IAAI,KAAK;AACrB,mBAAiB;AACnB;AACA,CANC,KAMK,CAAC;AACL,SAAO;AACP,UAAQ;AACR,UAAQ,IAAI,MAAM;AAClB,iBAAe;AACf,cAAY;AACZ,UAAQ;AACR,cAAY,IAAI,KAAK;AACvB;AACA,CAfC,KAeK,CATC,IASI,CAAC;AACV,gBAAc;AACd,cAAY;AACd;AACA,CAAC;AACC,WAAS,KAAK;AACd,SAAO;AACP,aAAW;AACX,cAAY;AACZ,UAAQ;AACV;AACA,CAAC;AACC,cAAY;AACZ,aAAW;AACX,SAAO;AACP,eAAa;AACb,cAAY;AACZ,cAAY;AACd;;;ACvCA,CAAC;AACC,UAAQ;AACR,WAAS;AACT,kBAAgB;AAClB;AAEA,CANC,GAMG,CAAC;AACH,YAAU;AACV,OAAK;AACL,QAAM;AACN,SAAO;AACP,UAAQ;AACR,WAAS;AACT,cAAY;AACZ,SAAO;AACP,UAAQ;AACV;AAEA,CAAC;AACC,eAAa;AACb,WAAS;AACT,eAAa;AACb,WAAS,IAAI;AACb,cAAY;AACZ,iBAAe,IAAI,MAAM;AACzB,OAAK;AACL,cAAY;AACd;AAEA,CAAC;AACC,WAAS;AACT,eAAa;AACb,OAAK;AACP;AAEA,CAAC;AACC,WAAS;AACT,eAAa;AACb,mBAAiB;AACjB,aAAW;AACX,UAAQ;AACR,WAAS,EAAE;AACX,UAAQ;AACR,iBAAe;AACf,cAAY;AACZ,UAAQ;AACR,aAAW;AACX,eAAa;AACb,SAAO;AACP,cAAY,iBAAiB,KAAK,EAAE,MAAM;AAC1C,eAAa;AACf;AAEA,CAlBC,cAkBc;AACb,cAAY;AACZ,SAAO;AACT;AAEA,CAvBC,cAuBc;AACb,cAAY;AACd;AAEA,CA3BC,cA2Bc,CAAC;AACd,aAAW;AACX,UAAQ;AACR,WAAS,EAAE;AACX,gBAAc;AACd,cAAY;AACd;AAEA,CAnCC,cAmCc,CARC,OAQO;AACrB,cAAY;AACZ,SAAO;AACP,gBAAc;AACd,cAAY;AACd;AAEA,CA1CC,cA0Cc,CAfC,OAeO;AACrB,gBAAc;AACd,cAAY;AACd;AAEA,OAAO,CAAC,oCAAoC,CApB5B,OAoBoC,KAAK,UAAU,KAAK,CAAC,iBAAiB;AACxF,UAAQ;AACV;AAEA,CAAC;AACC,SAAO;AACP,UAAQ;AACR,cAAY;AACZ,UAAQ,EAAE;AACZ;AAEA,CAAC;AACC,QAAM;AACN,cAAY;AACZ,YAAU;AACZ;AAEA,CANC,aAMa,CAAC;AACb,UAAQ;AACV;AAEA,CAVC,aAUa,CAAC;AACb,cAAY;AACd;AAEA,CAAC;AACC,UAAQ;AAEV;AAEA,CAAC;AACA;AAAA,IAAa,QAAQ;AAAA,IAAC,KAAK;AAAA,IAAC,KAAK,KAAK,EAAE;AAAA,IAAC,aAAa;AAAA,IAAC,kBAAkB;AAAA,IAAC,MAAM,EAAE;AAAA,IAAC,SAAS,EAAE;AAAA,IAAC,UAAU,KAAK;AAAA,IAAC;AAChH;AAEA,CAAC;AACC,UAAQ;AACV;AAEA,CAAC;AACC,UAAQ;AACR,YAAU;AACZ;AAIA,CAAC;AACC,UAAQ,KAAK;AACb,iBAAe;AACf,UAAQ,IAAI,MAAM;AAClB,YAAU;AACZ;AAGA,CAAC;AACC,cAAY;AACd;AAEA,CAAC;AACC,WAAS;AACX;AAEA,CAAC;AACC,UAAQ,EAAE,EAAE;AACZ,aAAW;AACX,eAAa;AACf;AAEA,CANC,gBAMgB;AACf,SAAO;AACP,mBAAiB;AACnB;AAEA,CAXC,gBAWgB,CAAC;AAChB,mBAAiB;AACnB;AAEA,CAAC;AACC,UAAQ;AACR,aAAW;AACX,SAAO;AACP,eAAa;AACf;AAEA,CAAC;AACC,cAAY;AACZ,gBAAc;AAChB;AAEA,CALC,kBAKkB,CA3BlB,gBA2BmC;AAClC,SAAO;AACT;AAEA,CAAC;AACC,cAAY;AACZ,gBAAc;AAChB;AAEA,CALC,kBAKkB,CApClB,gBAoCmC;AAClC,SAAO;AACT;AAGA,CAAC;AACC,WAAS,KAAK;AAChB;AAEA,CAAC;AACC,cAAY;AACZ,gBAAc;AAChB;AAEA,CAAC;AACC,cAAY;AACZ,gBAAc;AAChB;AAEA,CAAC;AACC,cAAY;AACZ,gBAAc;AAChB;AAEA,CAAC;AACC,cAAY;AACZ,gBAAc;AAChB;AAEA,CAAC;AACC,UAAQ,EAAE,EAAE;AACZ,aAAW;AACX,eAAa;AACf;AAEA,CAAC;AACC,aAAW;AACX,eAAa;AACf;AAGA,CAAC;AACC,WAAS,IAAI;AACf;AAEA,CAAC;AACC,iBAAe;AACjB;AAEA,CAAC;AACC,WAAS;AACT,iBAAe;AACf,aAAW;AACX,eAAa;AACb,SAAO;AACT;AAEA,CAAC;AACC,SAAO;AACP,WAAS,IAAI;AACb,aAAW;AACX,UAAQ,IAAI,MAAM;AAClB,iBAAe;AACf,WAAS;AACT,cAAY,aAAa;AAC3B;AAEA,CAVC,iBAUiB;AAChB,gBAAc;AACd,cAAY,EAAE,EAAE,EAAE,IAAI,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE;AAC1C;AAEA,CAAC;AACC,UAAQ;AACR,eAAa;AACf;","names":[]}
package/dist/index.d.cts DELETED
@@ -1,98 +0,0 @@
1
- import * as React from 'react';
2
- import React__default from 'react';
3
- import { EditorView } from '@codemirror/view';
4
- import { EditorState } from '@codemirror/state';
5
-
6
- interface MarkdownEditorRef {
7
- getContent: () => string;
8
- }
9
- interface MarkdownEditorProps {
10
- /** 初始内容 */
11
- defaultValue?: string;
12
- /** 受控内容 */
13
- value?: string;
14
- /** 内容变化回调 */
15
- onChange?: (value: string) => void;
16
- /** 是否显示预览面板 */
17
- showPreview?: boolean;
18
- /** 是否支持全屏 */
19
- fullscreen?: boolean;
20
- }
21
- declare const _default: React.ForwardRefExoticComponent<MarkdownEditorProps & React.RefAttributes<MarkdownEditorRef>>;
22
-
23
- interface ToolbarButtonConfig {
24
- id?: string;
25
- icon?: React__default.ComponentType;
26
- label?: string;
27
- children?: ToolbarButtonConfig[];
28
- handler?: (view: EditorView, state: EditorState) => void;
29
- separatorBefore?: boolean;
30
- customRender?: () => React__default.ReactNode;
31
- }
32
- /**
33
- * 弹窗属性配置
34
- * 用于定义 Markdown 容器中需要填充的属性字段
35
- */
36
- interface DialogField {
37
- /** 字段键名,用于 Markdown 属性填充 */
38
- key: string;
39
- /** 默认值 */
40
- defaultValue?: string;
41
- }
42
- /**
43
- * 组件 Schema
44
- * 每个容器组件(如 :::linkCard)定义可编辑字段和弹窗渲染逻辑
45
- */
46
- interface ComponentSchema {
47
- /** 容器名称,对应 :::name 语法 */
48
- name: string;
49
- /** 工具栏按钮显示的标签 */
50
- label: string;
51
- /** 工具栏按钮显示的图标 */
52
- icon?: React__default.ReactNode;
53
- /** 弹窗属性配置 — 用于定义 Markdown 内容中需要填充的字段 */
54
- fields: DialogField[];
55
- /**
56
- * 弹窗内容渲染函数(必填)
57
- * 接收当前属性值和回调函数,由用户完全自定义弹窗内容的渲染
58
- * @param props 当前属性值,用于回显
59
- * @param onChange 属性变更回调,用于更新表单值
60
- * @returns 弹窗内容的 ReactNode
61
- */
62
- renderDialog: (props: Record<string, string>, onChange: (key: string, value: string) => void) => React__default.ReactNode;
63
- }
64
-
65
- /**
66
- * 注册自定义容器组件到工具栏。支持单个或批量注册。
67
- * 支持 linkCard 形式的 schema(name + fields + renderDialog)。
68
- * fields 定义 Markdown 属性字段,renderDialog 定义弹窗内容。
69
- *
70
- * @example 单个注册
71
- * ```tsx
72
- * const schema: ComponentSchema = {
73
- * name: 'alert',
74
- * label: '警告框',
75
- * icon: <AlertOutlined />,
76
- * fields: [{ key: 'level', defaultValue: 'info' }],
77
- * renderDialog: (props, onChange) => (
78
- * <Input value={props.level} onChange={e => onChange('level', e.target.value)} />
79
- * ),
80
- * }
81
- *
82
- * function MyPage() {
83
- * useRegisterToolbar(schema)
84
- * return <MarkdownEditor />
85
- * }
86
- * ```
87
- *
88
- * @example 批量注册
89
- * ```tsx
90
- * function MyPage() {
91
- * useRegisterToolbar([schema1, schema2, schema3])
92
- * return <MarkdownEditor />
93
- * }
94
- * ```
95
- */
96
- declare function useRegisterToolbar(schemas: ComponentSchema | ComponentSchema[]): void;
97
-
98
- export { type ComponentSchema, type DialogField, _default as MarkdownEditor, type MarkdownEditorProps, type MarkdownEditorRef, type ToolbarButtonConfig, useRegisterToolbar };