remons-markdown-editor 1.0.0 → 2.0.0-beta.1
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.
- package/dist/MarkdownEditor.d.ts +24 -5
- package/dist/components/Dialog/EditDialog.d.ts +6 -3
- package/dist/components/Editor/codemirrorExtensions.d.ts +4 -4
- package/dist/components/Editor/containerWidget.d.ts +24 -8
- package/dist/components/Editor/index.d.ts +2 -1
- package/dist/components/Icon/config.d.ts +9 -0
- package/dist/components/Preview/index.d.ts +6 -5
- package/dist/components/Toolbar/buttons.d.ts +3 -3
- package/dist/components/Toolbar/config.d.ts +9 -2
- package/dist/components/Toolbar/hooks/useToolbar.d.ts +3 -1
- package/dist/components/Toolbar/index.d.ts +6 -3
- package/dist/components/Toolbar/renderers/TablePicker/TableDropdown.d.ts +1 -2
- package/dist/hooks/useRegisterToolbar.d.ts +3 -0
- package/dist/hooks/useScrollSync.d.ts +5 -2
- package/dist/index.cjs +2101 -406
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +51 -80
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2123 -409
- package/dist/index.js.map +1 -1
- package/dist/registry/componentRegistry.d.ts +17 -4
- package/dist/types/index.d.ts +19 -10
- package/dist/utils/parseContainer.d.ts +26 -6
- package/dist/utils/writeContainer.d.ts +11 -7
- package/package.json +12 -15
- package/readme.md +26 -22
- package/dist/App.d.ts +0 -2
- package/dist/main.d.ts +0 -0
|
@@ -2,13 +2,30 @@ import { ComponentSchema } from '../types';
|
|
|
2
2
|
/**
|
|
3
3
|
* 组件注册中心,用于管理自定义组件的 schema。
|
|
4
4
|
* 每个容器组件(如 :::linkCard)在此注册其可编辑字段。
|
|
5
|
+
* 内置版本计数 + 订阅:注册/移除后通知监听方(如编辑器工具栏)刷新。
|
|
5
6
|
*/
|
|
7
|
+
type Listener = (version: number) => void;
|
|
6
8
|
declare class ComponentRegistry {
|
|
7
9
|
private schemas;
|
|
10
|
+
private listeners;
|
|
11
|
+
private version;
|
|
8
12
|
/**
|
|
9
13
|
* 注册组件 schema
|
|
10
14
|
*/
|
|
11
15
|
register(name: string, schema: ComponentSchema): void;
|
|
16
|
+
/**
|
|
17
|
+
* 移除组件注册
|
|
18
|
+
*/
|
|
19
|
+
unregister(name: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* 当前版本号,任意注册变更都会自增
|
|
22
|
+
*/
|
|
23
|
+
getVersion(): number;
|
|
24
|
+
/**
|
|
25
|
+
* 订阅注册变更,返回退订函数
|
|
26
|
+
*/
|
|
27
|
+
subscribe(listener: Listener): () => void;
|
|
28
|
+
private emit;
|
|
12
29
|
/**
|
|
13
30
|
* 根据组件名获取已注册的 schema
|
|
14
31
|
*/
|
|
@@ -25,10 +42,6 @@ declare class ComponentRegistry {
|
|
|
25
42
|
* 获取所有已注册的 schema
|
|
26
43
|
*/
|
|
27
44
|
getAll(): ComponentSchema[];
|
|
28
|
-
/**
|
|
29
|
-
* 移除组件注册
|
|
30
|
-
*/
|
|
31
|
-
unregister(name: string): void;
|
|
32
45
|
}
|
|
33
46
|
declare const componentRegistry: ComponentRegistry;
|
|
34
47
|
export default componentRegistry;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { EditorView } from '@codemirror/view';
|
|
2
2
|
import { EditorState as CMEditorState } from '@codemirror/state';
|
|
3
|
-
import { FormInstance } from 'antd';
|
|
3
|
+
import { FormInstance, FormItemProps } from 'antd';
|
|
4
4
|
import { default as React } from 'react';
|
|
5
|
+
import { ContainerProps } from '../utils/parseContainer';
|
|
5
6
|
export interface ToolbarButtonConfig {
|
|
6
7
|
id?: string;
|
|
7
|
-
|
|
8
|
+
/** 图标统一为组件类型,由渲染层 <Icon /> 实例化 */
|
|
9
|
+
icon?: React.ComponentType;
|
|
8
10
|
label?: string;
|
|
9
11
|
children?: ToolbarButtonConfig[];
|
|
10
12
|
handler?: (view: EditorView, state: CMEditorState) => void;
|
|
@@ -28,7 +30,7 @@ export interface DialogField {
|
|
|
28
30
|
/** 字段显示名称(表单 label) */
|
|
29
31
|
name?: string;
|
|
30
32
|
/** 默认值 */
|
|
31
|
-
defaultValue?: string;
|
|
33
|
+
defaultValue?: string | number | boolean;
|
|
32
34
|
/**
|
|
33
35
|
* 表单组件类型(可选)
|
|
34
36
|
* 配置后 EditDialog 会自动渲染对应的 antd 表单组件,无需手写 Form 结构
|
|
@@ -36,10 +38,15 @@ export interface DialogField {
|
|
|
36
38
|
*/
|
|
37
39
|
componentType?: FormComponentType;
|
|
38
40
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
+
* 控件组件额外属性(可选),仅传给表单控件本身
|
|
42
|
+
* 如 Select 的 options、Input.TextArea 的 rows
|
|
41
43
|
*/
|
|
42
44
|
componentProps?: Record<string, any>;
|
|
45
|
+
/**
|
|
46
|
+
* Form.Item 额外属性(可选),仅传给 Form.Item
|
|
47
|
+
* 如 rules、required 等,不会污染控件 DOM
|
|
48
|
+
*/
|
|
49
|
+
formItemProps?: FormItemProps;
|
|
43
50
|
}
|
|
44
51
|
/**
|
|
45
52
|
* 组件 Schema
|
|
@@ -51,8 +58,8 @@ export interface ComponentSchema {
|
|
|
51
58
|
name: string;
|
|
52
59
|
/** 工具栏按钮显示的标签 */
|
|
53
60
|
label: string;
|
|
54
|
-
/**
|
|
55
|
-
icon?: React.
|
|
61
|
+
/** 工具栏按钮显示的图标(组件类型,与 ToolbarButtonConfig.icon 一致) */
|
|
62
|
+
icon?: React.ComponentType;
|
|
56
63
|
/**
|
|
57
64
|
* 标签包裹配置:设置为 [openTag, closeTag] 时,使用标签包裹模式(而非 :::name 容器)
|
|
58
65
|
* 配置后无需提供 fields 和 renderDialog
|
|
@@ -114,14 +121,16 @@ export interface ComponentSchema {
|
|
|
114
121
|
*/
|
|
115
122
|
export interface DialogRenderContext {
|
|
116
123
|
/** 当前属性值(合并默认值与当前的值) */
|
|
117
|
-
props:
|
|
124
|
+
props: ContainerProps;
|
|
118
125
|
/** 表单实例,用于 Form.Item 自动绑定 */
|
|
119
126
|
form: FormInstance;
|
|
120
127
|
/** 属性变更回调(手动控制方式) */
|
|
121
|
-
onChange: (key: string, value: string) => void;
|
|
128
|
+
onChange: (key: string, value: string | number | boolean) => void;
|
|
122
129
|
/** 直接保存属性(完全自定义方式,调用后弹窗不会自动关闭) */
|
|
123
|
-
onSave: (props:
|
|
130
|
+
onSave: (props: ContainerProps) => void;
|
|
124
131
|
}
|
|
132
|
+
/** 全局消息提示注入点(如 antd message.error),缺省用 console,宿主可接管 */
|
|
133
|
+
export type NotifyFn = (type: 'info' | 'warning' | 'error', content: string) => void;
|
|
125
134
|
/**
|
|
126
135
|
* 图片上传配置
|
|
127
136
|
*/
|
|
@@ -1,18 +1,38 @@
|
|
|
1
|
+
/** 容器属性对象:值保留原始类型(string/number/boolean),写回时统一序列化 */
|
|
2
|
+
export type ContainerProps = Record<string, string | number | boolean>;
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
+
* 解析容器属性行。
|
|
5
|
+
* 优先按 JSON5 解析(兼容标准 JSON 与 { key: 'value' } 宽松写法),
|
|
6
|
+
* 失败时返回空对象,保证往返编辑不丢数据。
|
|
4
7
|
*/
|
|
5
|
-
export declare function parseContainerProps(
|
|
8
|
+
export declare function parseContainerProps(line: string): ContainerProps;
|
|
6
9
|
/**
|
|
7
|
-
*
|
|
8
|
-
* 返回包含类型、属性和行位置的容器位置数组。
|
|
10
|
+
* 容器块位置信息(基于文档的绝对字符偏移)
|
|
9
11
|
*/
|
|
10
12
|
export interface ContainerBlock {
|
|
13
|
+
/** ::: 打开行行首位置 */
|
|
11
14
|
startPos: number;
|
|
15
|
+
/** 组件类型名称 (如 "linkCard") */
|
|
12
16
|
typeName: string;
|
|
17
|
+
/** 属性行起始位置(0 表示无属性行) */
|
|
13
18
|
propsLineFrom: number;
|
|
19
|
+
/** 属性行结束位置(0 表示无属性行) */
|
|
14
20
|
propsLineTo: number;
|
|
15
|
-
|
|
21
|
+
/** 解析出的属性 */
|
|
22
|
+
props: ContainerProps;
|
|
23
|
+
/** ::: 关闭行行首位置(0 表示未闭合) */
|
|
16
24
|
endPos: number;
|
|
25
|
+
/** 类型是否已在注册中心登记(未登记的仅装饰、不可编辑) */
|
|
26
|
+
registered: boolean;
|
|
27
|
+
/** 容器行首的引用前缀(如 "> ");嵌套在引用中的容器写回时需保留 */
|
|
28
|
+
quotePrefix?: string;
|
|
29
|
+
/** 属性行自身的引用前缀(懒延续时可为空);替换属性行时按它原样保留 */
|
|
30
|
+
propsQuotePrefix?: string;
|
|
17
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* 在编辑器文档中查找容器块。
|
|
34
|
+
* 单次遍历 + 预累计行偏移,复杂度 O(行数)。
|
|
35
|
+
* 支持整体嵌套在引用中的容器:头行、属性行、闭合行需具有相同的 "> " 前缀深度,
|
|
36
|
+
* 避免跨引用层级错误配对。闭合 ::: 改为按栈配对,嵌套容器不会被内层闭合误截断。
|
|
37
|
+
*/
|
|
18
38
|
export declare function findContainers(docText: string): ContainerBlock[];
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { EditorView } from '@codemirror/view';
|
|
2
|
+
import { ContainerProps } from './parseContainer';
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
4
|
+
* 从属性对象生成属性行。
|
|
5
|
+
* 使用 JSON5 序列化:单引号风格与旧格式兼容,特殊字符会被正确转义,
|
|
6
|
+
* 配合 parseContainerProps 保证读写往返无损。
|
|
5
7
|
*/
|
|
6
|
-
export declare function writeContainerProps(props:
|
|
8
|
+
export declare function writeContainerProps(props: ContainerProps): string;
|
|
7
9
|
/**
|
|
8
10
|
* 更新编辑器文档中的容器属性。
|
|
9
|
-
*
|
|
11
|
+
* 已有属性行则整行替换;没有属性行则在容器头行后插入一行。
|
|
12
|
+
* @param headerPos 容器头行(:::type)任意位置,用于无属性行时定位插入点
|
|
13
|
+
* @param quotePrefix 容器所处的引用前缀(如 "> "),嵌套在引用中时插入的属性行需保持一致
|
|
10
14
|
*/
|
|
11
|
-
export declare function updateContainerProps(view: EditorView, propsLineFrom: number, propsLineTo: number, newProps:
|
|
15
|
+
export declare function updateContainerProps(view: EditorView, headerPos: number, propsLineFrom: number, propsLineTo: number, newProps: ContainerProps, quotePrefix?: string): void;
|
|
12
16
|
/**
|
|
13
17
|
* 在当前光标位置插入新容器。
|
|
14
|
-
* 创建 :::type 打开行 +
|
|
18
|
+
* 创建 :::type 打开行 + 属性行 + ::: 关闭行的结构。
|
|
15
19
|
*/
|
|
16
|
-
export declare function insertContainer(view: EditorView, typeName: string, defaultProps:
|
|
20
|
+
export declare function insertContainer(view: EditorView, typeName: string, defaultProps: ContainerProps): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "remons-markdown-editor",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-beta.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "一个可复用的 React Markdown 编辑器组件,支持工具栏、预览和自定义容器",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -13,21 +13,17 @@
|
|
|
13
13
|
},
|
|
14
14
|
"homepage": "https://github.com/liRemons/markdown-editor#readme",
|
|
15
15
|
"sideEffects": [
|
|
16
|
-
"*.css"
|
|
16
|
+
"*.css",
|
|
17
|
+
"*.less"
|
|
17
18
|
],
|
|
18
19
|
"files": [
|
|
19
20
|
"dist"
|
|
20
21
|
],
|
|
21
22
|
"exports": {
|
|
22
23
|
".": {
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
},
|
|
27
|
-
"require": {
|
|
28
|
-
"types": "./dist/index.d.cts",
|
|
29
|
-
"default": "./dist/index.cjs"
|
|
30
|
-
}
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"import": "./dist/index.js",
|
|
26
|
+
"require": "./dist/index.cjs"
|
|
31
27
|
},
|
|
32
28
|
"./style.css": "./dist/index.css"
|
|
33
29
|
},
|
|
@@ -42,9 +38,7 @@
|
|
|
42
38
|
"registry": "https://registry.npmjs.org/"
|
|
43
39
|
},
|
|
44
40
|
"dependencies": {
|
|
45
|
-
"@ant-design/icons": "^6.3.4",
|
|
46
41
|
"@codemirror/commands": "^6.11.0",
|
|
47
|
-
"@codemirror/highlight": "^0.19.8",
|
|
48
42
|
"@codemirror/lang-markdown": "^6.3.2",
|
|
49
43
|
"@codemirror/language": "^6.12.4",
|
|
50
44
|
"@codemirror/state": "^6.5.2",
|
|
@@ -52,13 +46,16 @@
|
|
|
52
46
|
"@codemirror/view": "^6.36.4",
|
|
53
47
|
"@lezer/common": "^1.2.3",
|
|
54
48
|
"@lezer/highlight": "^1.2.3",
|
|
55
|
-
"antd": "^6.6.3",
|
|
56
49
|
"codemirror": "^6.0.1",
|
|
57
50
|
"highlight.js": "^11.12.0",
|
|
58
|
-
"
|
|
59
|
-
"remons-
|
|
51
|
+
"json5": "^2.2.3",
|
|
52
|
+
"remons-markdown-plugins": "^2.0.0-beta.2",
|
|
53
|
+
"remons-render-markdown": "^2.0.1-beta.6"
|
|
60
54
|
},
|
|
61
55
|
"peerDependencies": {
|
|
56
|
+
"antd": ">=5.21.6",
|
|
57
|
+
"@ant-design/icons": ">=5.0.0",
|
|
58
|
+
"dayjs": ">=1.11.13",
|
|
62
59
|
"react": "^18.0.0",
|
|
63
60
|
"react-dom": "^18.0.0"
|
|
64
61
|
},
|
package/readme.md
CHANGED
|
@@ -10,9 +10,10 @@ npm install remons-markdown-editor
|
|
|
10
10
|
|
|
11
11
|
## 基本用法
|
|
12
12
|
|
|
13
|
+
入口已自动携带组件样式,无需手动导入 CSS;若使用打包器的 sideEffects 裁剪,也可显式引入 `remons-markdown-editor/style.css`。
|
|
14
|
+
|
|
13
15
|
```tsx
|
|
14
16
|
import { MarkdownEditor } from 'remons-markdown-editor'
|
|
15
|
-
import 'remons-markdown-editor/style.css'
|
|
16
17
|
|
|
17
18
|
export default function App() {
|
|
18
19
|
return <MarkdownEditor />
|
|
@@ -25,13 +26,18 @@ export default function App() {
|
|
|
25
26
|
|
|
26
27
|
| 属性名 | 类型 | 默认值 | 说明 |
|
|
27
28
|
|--------|------|--------|------|
|
|
28
|
-
| value | string | - |
|
|
29
|
+
| value | string | - | 受控模式下的内容(需配合 onChange 使用) |
|
|
29
30
|
| defaultValue | string | '' | 非受控模式下的初始内容 |
|
|
30
31
|
| onChange | (value: string) => void | - | 内容变更回调 |
|
|
31
32
|
| showPreview | boolean | true | 是否显示预览面板 |
|
|
32
33
|
| fullscreen | boolean | true | 是否显示全屏按钮 |
|
|
33
34
|
| previewOptions | PreviewOptions | - | 预览渲染配置,类型继承自 `RenderMarkdownProps` |
|
|
35
|
+
| languages | Record<string, any> \| null | - | 代码高亮语言包(与内置 languagesCommon 合并注册) |
|
|
34
36
|
| uploadConfig | ImageUploadConfig | - | 图片上传配置 |
|
|
37
|
+
| schemas | ComponentSchema[] | - | 局部注册的容器 schema,仅对当前实例生效,同名时覆盖全局注册 |
|
|
38
|
+
| onNotify | (type, content) => void | - | 提示注入点,缺省使用 antd App 上下文的 message |
|
|
39
|
+
|
|
40
|
+
> 同页面存在多个编辑器实例时,推荐用 `schemas` 局部注册代替 `useRegisterToolbar`,避免全局注册表互相覆盖。
|
|
35
41
|
|
|
36
42
|
### MarkdownEditorRef
|
|
37
43
|
|
|
@@ -41,29 +47,32 @@ export default function App() {
|
|
|
41
47
|
|
|
42
48
|
### PreviewOptions
|
|
43
49
|
|
|
44
|
-
|
|
50
|
+
预览渲染配置,类型即 `Omit<RenderMarkdownProps, 'content'>`(来自 `remons-render-markdown` v2):
|
|
45
51
|
|
|
46
52
|
```typescript
|
|
47
53
|
import type { RenderMarkdownProps } from 'remons-render-markdown'
|
|
48
54
|
|
|
49
|
-
export type PreviewOptions = Omit<RenderMarkdownProps, 'content'>
|
|
50
|
-
languages?: Record<string, any> | null | undefined
|
|
51
|
-
}
|
|
55
|
+
export type PreviewOptions = Omit<RenderMarkdownProps, 'content'>
|
|
52
56
|
```
|
|
53
57
|
|
|
58
|
+
常用字段(v2 重命名后的新名,旧名仍可用但已废弃):
|
|
59
|
+
|
|
54
60
|
| 属性名 | 类型 | 默认值 | 说明 |
|
|
55
61
|
|--------|------|--------|------|
|
|
56
|
-
| languages | Record<string, any> | - | 自定义代码高亮语言配置 |
|
|
57
62
|
| customRenderers | MarkdownPlugin[] | - | 自定义 markdown-it 渲染插件 |
|
|
58
|
-
| excludedSelectors | string[] | - |
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
| defaultCollapsed | boolean | - |
|
|
63
|
+
| excludedSelectors | string[] | - | 图片预览排除名单(实例级) |
|
|
64
|
+
| enableMermaid | boolean | - | 是否将 mermaid 代码块渲染为图表(旧名 isSlotMermaid) |
|
|
65
|
+
| showCollapseButton | boolean | - | 是否显示代码折叠按钮(旧名 isShowCollapsed) |
|
|
66
|
+
| defaultCollapsed | boolean | - | 代码块默认是否折叠 |
|
|
62
67
|
| showBackTop | boolean | - | 是否显示返回顶部 |
|
|
68
|
+
| showToc | boolean | - | 是否显示目录(TOC) |
|
|
69
|
+
| incremental | boolean | - | 是否启用增量渲染(旧名 useIncremental) |
|
|
63
70
|
| isPrintPreview | boolean | - | 是否为打印模式 |
|
|
64
|
-
|
|
|
71
|
+
| toolbarDebounceMs | number | - | 工具栏/mermaid 扫描防抖延迟(旧名 mermaidDebounce) |
|
|
65
72
|
| cdn | Record<string, string> | - | 自定义 CDN 配置 |
|
|
66
|
-
|
|
|
73
|
+
| transformSource | (text: string) => string | - | 渲染前改写 mermaid 源码(旧名 chartConfig) |
|
|
74
|
+
| html | boolean | true | 是否渲染源码中的原生 HTML |
|
|
75
|
+
| validateLink | (url: string) => boolean | - | 覆盖链接校验 |
|
|
67
76
|
|
|
68
77
|
更多配置请参考 [remons-render-markdown](https://github.com/liRemons/render-markdown)。
|
|
69
78
|
|
|
@@ -85,27 +94,22 @@ export type PreviewOptions = Omit<RenderMarkdownProps, 'content'> & {
|
|
|
85
94
|
import { MarkdownEditor } from 'remons-markdown-editor'
|
|
86
95
|
import type { PreviewOptions } from 'remons-markdown-editor'
|
|
87
96
|
import { languagesCommon } from 'remons-render-markdown'
|
|
88
|
-
import 'remons-markdown-editor/style.css'
|
|
89
97
|
|
|
90
98
|
function App() {
|
|
91
99
|
const previewOptions: PreviewOptions = {
|
|
92
|
-
// 自定义高亮语言(在 languagesCommon 基础上扩展)
|
|
93
|
-
languages: {
|
|
94
|
-
...languagesCommon,
|
|
95
|
-
// 添加自定义语言配置
|
|
96
|
-
},
|
|
97
100
|
// 自定义 markdown-it 插件,可使用 remons-markdown-plugins 按需导入
|
|
98
101
|
// 参考 https://github.com/liRemons/markdown-plugin
|
|
99
102
|
customRenderers: [
|
|
100
103
|
(md) => md.use(yourCustomPlugin)
|
|
101
104
|
],
|
|
102
|
-
// 禁用 mermaid
|
|
103
|
-
|
|
105
|
+
// 禁用 mermaid 图表渲染
|
|
106
|
+
enableMermaid: false,
|
|
104
107
|
// 自定义排除选择器
|
|
105
108
|
excludedSelectors: ['.my-custom-class'],
|
|
106
109
|
}
|
|
107
110
|
|
|
108
|
-
|
|
111
|
+
// 高亮语言包通过独立的 languages prop 传入(在 languagesCommon 基础上扩展)
|
|
112
|
+
return <MarkdownEditor previewOptions={previewOptions} languages={{ ...languagesCommon }} />
|
|
109
113
|
}
|
|
110
114
|
```
|
|
111
115
|
|
package/dist/App.d.ts
DELETED
package/dist/main.d.ts
DELETED
|
File without changes
|