remons-markdown-editor 1.0.0-beta.3 → 1.0.0-beta.5

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 (33) 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/Panel/SplitPanels.d.ts +7 -0
  8. package/dist/components/Preview/index.d.ts +10 -0
  9. package/dist/components/Toolbar/buttons.d.ts +34 -0
  10. package/dist/components/Toolbar/config.d.ts +6 -0
  11. package/dist/components/Toolbar/hooks/useToolbar.d.ts +13 -0
  12. package/dist/components/Toolbar/index.d.ts +13 -0
  13. package/dist/components/Toolbar/renderers/TablePicker/TableDropdown.d.ts +5 -0
  14. package/dist/components/Toolbar/renderers/TablePicker/index.d.ts +9 -0
  15. package/dist/components/Toolbar/renderers/ToolbarItemRenderer.d.ts +7 -0
  16. package/dist/hooks/useFullscreen.d.ts +4 -0
  17. package/dist/hooks/useRegisterToolbar.d.ts +51 -0
  18. package/dist/hooks/useScrollSync.d.ts +5 -0
  19. package/dist/index.cjs +1325 -1207
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.css +108 -88
  22. package/dist/index.d.ts +5 -105
  23. package/dist/index.js +1301 -1187
  24. package/dist/index.js.map +1 -1
  25. package/dist/main.d.ts +0 -0
  26. package/dist/registry/componentRegistry.d.ts +34 -0
  27. package/dist/types/index.d.ts +76 -0
  28. package/dist/utils/parseContainer.d.ts +18 -0
  29. package/dist/utils/writeContainer.d.ts +16 -0
  30. package/package.json +7 -7
  31. package/readme.md +103 -4
  32. package/dist/index.css.map +0 -1
  33. package/dist/index.d.cts +0 -105
package/readme.md CHANGED
@@ -31,6 +31,7 @@ export default function App() {
31
31
  | showPreview | boolean | true | 是否显示预览面板 |
32
32
  | fullscreen | boolean | false | 是否显示全屏按钮 |
33
33
  | previewOptions | PreviewOptions | - | 预览渲染配置,类型继承自 `RenderMarkdownProps` |
34
+ | uploadConfig | ImageUploadConfig | - | 图片上传配置 |
34
35
 
35
36
  ### MarkdownEditorRef
36
37
 
@@ -63,9 +64,20 @@ export type PreviewOptions = Omit<RenderMarkdownProps, 'content'> & {
63
64
  | mermaidDebounce | number | - | Mermaid 渲染防抖延迟(ms) |
64
65
  | cdn | Record<string, string> | - | 自定义 CDN 配置 |
65
66
  | chartConfig | (text: string) => string | - | 渲染前文本修改函数 |
67
+ | languages | Record<string, any> | - | 自定义代码高亮语言配置 |
66
68
 
67
69
  更多配置请参考 [remons-render-markdown](https://github.com/liRemons/render-markdown)。
68
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
+
69
81
  ## 使用示例
70
82
 
71
83
  ### 自定义预览配置
@@ -98,8 +110,71 @@ function App() {
98
110
  }
99
111
  ```
100
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
+
101
170
  ### 自定义容器
102
171
 
172
+ 支持两种注册模式:
173
+
174
+ #### 容器模式(支持弹窗编辑属性)
175
+
176
+ 插入 `:::name` 格式的容器,支持弹窗编辑属性:
177
+
103
178
  ```tsx
104
179
  import { MarkdownEditor, useRegisterToolbar } from 'remons-markdown-editor'
105
180
  import 'remons-markdown-editor/style.css'
@@ -125,6 +200,27 @@ export default function App() {
125
200
  }
126
201
  ```
127
202
 
203
+ #### 标签包裹模式
204
+
205
+ 插入简单的标签包裹文本,如 `<plugin-container>...</plugin-container>`,适合不需要弹窗编辑的场景:
206
+
207
+ ```tsx
208
+ import { MarkdownEditor, useRegisterToolbar } from 'remons-markdown-editor'
209
+ import 'remons-markdown-editor/style.css'
210
+
211
+ export default function App() {
212
+ useRegisterToolbar({
213
+ name: 'plugin-container',
214
+ label: '自定义容器',
215
+ icon: <AlertOutlined />,
216
+ wrapTags: ['<plugin-container>', '</plugin-container>'],
217
+ })
218
+ return <MarkdownEditor />
219
+ }
220
+ ```
221
+
222
+ 点击对应按钮会自动切换(添加/移除)标签包裹。
223
+
128
224
  ### 批量注册
129
225
 
130
226
  ```tsx
@@ -138,11 +234,14 @@ export default function App() {
138
234
 
139
235
  | 属性名 | 类型 | 必填 | 说明 |
140
236
  |--------|------|------|------|
141
- | name | string | 是 | 容器名称,对应 :::name 语法 |
237
+ | name | string | 是 | 容器/组件名称 |
142
238
  | label | string | 是 | 工具栏按钮显示的标签 |
143
- | icon | ReactNode | 否 | 工具栏按钮显示的图标,默认使用 ReadOutlined |
144
- | fields | DialogField[] | 是 | 弹窗属性字段配置 |
145
- | renderDialog | Function | 是 | 弹窗内容渲染函数,接收当前属性值和变更回调 |
239
+ | icon | ReactNode | 否 | 工具栏按钮显示的图标 |
240
+ | fields | DialogField[] | 容器模式必填 | 弹窗属性字段配置 |
241
+ | renderDialog | Function | 容器模式必填 | 弹窗内容渲染函数 |
242
+ | wrapTags | [string, string] | 标签模式必填 | 开闭标签对,如 `['<tag>', '</tag>']` |
243
+
244
+ 注:`wrapTags` 模式下不需要 `fields` 和 `renderDialog`。两种模式只需配置一种。
146
245
 
147
246
  ## 依赖
148
247
 
@@ -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: 100%;\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":"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","names":[]}
package/dist/index.d.cts DELETED
@@ -1,105 +0,0 @@
1
- import * as react from 'react';
2
- import react__default from 'react';
3
- import { RenderMarkdownProps } from 'remons-render-markdown';
4
- import { EditorView } from '@codemirror/view';
5
- import { EditorState } from '@codemirror/state';
6
-
7
- type PreviewOptions = Omit<RenderMarkdownProps, 'content'> & {
8
- languages?: Record<string, any> | null | undefined;
9
- };
10
-
11
- interface MarkdownEditorRef {
12
- getContent: () => string;
13
- }
14
- interface MarkdownEditorProps {
15
- /** 初始内容 */
16
- defaultValue?: string;
17
- /** 受控内容 */
18
- value?: string;
19
- /** 内容变化回调 */
20
- onChange?: (value: string) => void;
21
- /** 是否显示预览面板 */
22
- showPreview?: boolean;
23
- /** 是否支持全屏 */
24
- fullscreen?: boolean;
25
- /** Preview 渲染配置 */
26
- previewOptions?: PreviewOptions;
27
- }
28
- declare const _default: react.ForwardRefExoticComponent<MarkdownEditorProps & react.RefAttributes<MarkdownEditorRef>>;
29
-
30
- interface ToolbarButtonConfig {
31
- id?: string;
32
- icon?: react__default.ComponentType;
33
- label?: string;
34
- children?: ToolbarButtonConfig[];
35
- handler?: (view: EditorView, state: EditorState) => void;
36
- separatorBefore?: boolean;
37
- customRender?: () => react__default.ReactNode;
38
- }
39
- /**
40
- * 弹窗属性配置
41
- * 用于定义 Markdown 容器中需要填充的属性字段
42
- */
43
- interface DialogField {
44
- /** 字段键名,用于 Markdown 属性填充 */
45
- key: string;
46
- /** 默认值 */
47
- defaultValue?: string;
48
- }
49
- /**
50
- * 组件 Schema
51
- * 每个容器组件(如 :::linkCard)定义可编辑字段和弹窗渲染逻辑
52
- */
53
- interface ComponentSchema {
54
- /** 容器名称,对应 :::name 语法 */
55
- name: string;
56
- /** 工具栏按钮显示的标签 */
57
- label: string;
58
- /** 工具栏按钮显示的图标 */
59
- icon?: react__default.ReactNode;
60
- /** 弹窗属性配置 — 用于定义 Markdown 内容中需要填充的字段 */
61
- fields: DialogField[];
62
- /**
63
- * 弹窗内容渲染函数(必填)
64
- * 接收当前属性值和回调函数,由用户完全自定义弹窗内容的渲染
65
- * @param props 当前属性值,用于回显
66
- * @param onChange 属性变更回调,用于更新表单值
67
- * @returns 弹窗内容的 ReactNode
68
- */
69
- renderDialog: (props: Record<string, string>, onChange: (key: string, value: string) => void) => react__default.ReactNode;
70
- }
71
-
72
- /**
73
- * 注册自定义容器组件到工具栏。支持单个或批量注册。
74
- * 支持 linkCard 形式的 schema(name + fields + renderDialog)。
75
- * fields 定义 Markdown 属性字段,renderDialog 定义弹窗内容。
76
- *
77
- * @example 单个注册
78
- * ```tsx
79
- * const schema: ComponentSchema = {
80
- * name: 'alert',
81
- * label: '警告框',
82
- * icon: <AlertOutlined />,
83
- * fields: [{ key: 'level', defaultValue: 'info' }],
84
- * renderDialog: (props, onChange) => (
85
- * <Input value={props.level} onChange={e => onChange('level', e.target.value)} />
86
- * ),
87
- * }
88
- *
89
- * function MyPage() {
90
- * useRegisterToolbar(schema)
91
- * return <MarkdownEditor />
92
- * }
93
- * ```
94
- *
95
- * @example 批量注册
96
- * ```tsx
97
- * function MyPage() {
98
- * useRegisterToolbar([schema1, schema2, schema3])
99
- * return <MarkdownEditor />
100
- * }
101
- * ```
102
- */
103
- declare function useRegisterToolbar(schemas: ComponentSchema | ComponentSchema[]): void;
104
-
105
- export { type ComponentSchema, type DialogField, _default as MarkdownEditor, type MarkdownEditorProps, type MarkdownEditorRef, type PreviewOptions, type ToolbarButtonConfig, useRegisterToolbar };