remons-markdown-editor 2.0.0-beta.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/components/Dialog/EditDialog.d.ts +3 -1
- package/dist/components/Editor/containerWidget.d.ts +12 -1
- package/dist/index.cjs +121 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +122 -45
- package/dist/index.js.map +1 -1
- package/dist/utils/parseContainer.d.ts +6 -0
- package/dist/utils/writeContainer.d.ts +2 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
2
2
|
import { App, Button, ColorPicker, DatePicker, Dropdown, Form, Input, InputNumber, Modal, Rate, Select, Slider, Splitter, Switch, Tooltip, message } from "antd";
|
|
3
3
|
import { EditorView, basicSetup } from "codemirror";
|
|
4
|
-
import { EditorState, Facet } from "@codemirror/state";
|
|
4
|
+
import { EditorState, Facet, StateEffect } from "@codemirror/state";
|
|
5
5
|
import { Decoration, EditorView as EditorView$1, ViewPlugin, WidgetType, keymap } from "@codemirror/view";
|
|
6
6
|
import { defaultKeymap, indentWithTab } from "@codemirror/commands";
|
|
7
7
|
import { markdown } from "@codemirror/lang-markdown";
|
|
@@ -1274,8 +1274,25 @@ function parseContainerProps(line) {
|
|
|
1274
1274
|
}
|
|
1275
1275
|
}
|
|
1276
1276
|
/**
|
|
1277
|
+
* 解析行首的引用(blockquote)嵌套前缀。
|
|
1278
|
+
* markdown-it 解析引用内部内容时会剥掉一层 "> ",因此 "> :::badge" 在渲染侧
|
|
1279
|
+
* 等同于 ":::badge";编辑器侧需同样识别,否则嵌套引用的容器匹配不到标签。
|
|
1280
|
+
* 返回 [前缀文本(含 "> " 及尾随空格), 去掉前缀后的内容],无前缀时返回 ['', 原文本]。
|
|
1281
|
+
*/
|
|
1282
|
+
function splitQuotePrefix(line) {
|
|
1283
|
+
const m = line.match(/^((?:>\s*)+)(\S.*)$/);
|
|
1284
|
+
if (!m) return ["", line];
|
|
1285
|
+
return [m[1], m[2]];
|
|
1286
|
+
}
|
|
1287
|
+
/** 引用嵌套深度("> > x" 为 2,无前缀为 0) */
|
|
1288
|
+
function quoteDepth(prefix) {
|
|
1289
|
+
return (prefix.match(/>/g) ?? []).length;
|
|
1290
|
+
}
|
|
1291
|
+
/**
|
|
1277
1292
|
* 在编辑器文档中查找容器块。
|
|
1278
1293
|
* 单次遍历 + 预累计行偏移,复杂度 O(行数)。
|
|
1294
|
+
* 支持整体嵌套在引用中的容器:头行、属性行、闭合行需具有相同的 "> " 前缀深度,
|
|
1295
|
+
* 避免跨引用层级错误配对。闭合 ::: 改为按栈配对,嵌套容器不会被内层闭合误截断。
|
|
1279
1296
|
*/
|
|
1280
1297
|
function findContainers(docText) {
|
|
1281
1298
|
const containers = [];
|
|
@@ -1286,34 +1303,53 @@ function findContainers(docText) {
|
|
|
1286
1303
|
offsets[i] = pos;
|
|
1287
1304
|
pos += lines[i].length + 1;
|
|
1288
1305
|
}
|
|
1306
|
+
const stack = [];
|
|
1289
1307
|
for (let i = 0; i < lines.length; i++) {
|
|
1290
|
-
const
|
|
1308
|
+
const [prefix, body] = splitQuotePrefix(lines[i]);
|
|
1309
|
+
const depth = quoteDepth(prefix);
|
|
1310
|
+
if (/^:::$/.test(body)) {
|
|
1311
|
+
let top = stack.length - 1;
|
|
1312
|
+
while (top >= 0 && stack[top].depth !== depth) top--;
|
|
1313
|
+
if (top >= 0) {
|
|
1314
|
+
stack[top].block.endPos = offsets[i];
|
|
1315
|
+
stack.length = top;
|
|
1316
|
+
}
|
|
1317
|
+
continue;
|
|
1318
|
+
}
|
|
1319
|
+
const match = body.match(/^:::(\w+)$/);
|
|
1291
1320
|
if (!match) continue;
|
|
1292
1321
|
const typeName = match[1];
|
|
1293
1322
|
const headerPos = offsets[i];
|
|
1294
1323
|
let props = {};
|
|
1295
1324
|
let propsLineFrom = 0;
|
|
1296
1325
|
let propsLineTo = 0;
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1326
|
+
let propsQuotePrefix = "";
|
|
1327
|
+
const nextLine = lines[i + 1];
|
|
1328
|
+
if (nextLine) {
|
|
1329
|
+
const [nextPrefix, nextBody] = splitQuotePrefix(nextLine);
|
|
1330
|
+
if ((quoteDepth(nextPrefix) === depth || nextPrefix === "") && nextBody.trimStart().startsWith("{") && nextBody.trimEnd().endsWith("}")) {
|
|
1331
|
+
props = parseContainerProps(nextBody);
|
|
1332
|
+
propsLineFrom = offsets[i + 1];
|
|
1333
|
+
propsLineTo = propsLineFrom + nextLine.length;
|
|
1334
|
+
propsQuotePrefix = nextPrefix;
|
|
1335
|
+
i += 1;
|
|
1336
|
+
}
|
|
1308
1337
|
}
|
|
1309
|
-
|
|
1338
|
+
const block = {
|
|
1310
1339
|
startPos: headerPos,
|
|
1311
1340
|
typeName,
|
|
1312
1341
|
propsLineFrom,
|
|
1313
1342
|
propsLineTo,
|
|
1314
1343
|
props,
|
|
1315
|
-
endPos,
|
|
1316
|
-
registered: componentRegistry.has(typeName)
|
|
1344
|
+
endPos: 0,
|
|
1345
|
+
registered: componentRegistry.has(typeName),
|
|
1346
|
+
quotePrefix: prefix,
|
|
1347
|
+
propsQuotePrefix
|
|
1348
|
+
};
|
|
1349
|
+
containers.push(block);
|
|
1350
|
+
stack.push({
|
|
1351
|
+
block,
|
|
1352
|
+
depth
|
|
1317
1353
|
});
|
|
1318
1354
|
}
|
|
1319
1355
|
return containers;
|
|
@@ -1321,6 +1357,14 @@ function findContainers(docText) {
|
|
|
1321
1357
|
//#endregion
|
|
1322
1358
|
//#region src/components/Editor/containerWidget.ts
|
|
1323
1359
|
/**
|
|
1360
|
+
* 唤醒容器装饰重建的状态 effect(不改变文档)。
|
|
1361
|
+
* 编辑按钮是否展示取决于容器类型是否已注册,而宿主常在编辑器挂载之后才
|
|
1362
|
+
* 通过 useRegisterToolbar 异步注册 schema;注册不是 CodeMirror 事务,默认不会触发
|
|
1363
|
+
* ViewPlugin.update,导致初始化时烘焙的 registered=false 无法刷新(需手动改一个字才出现)。
|
|
1364
|
+
* 宿主在注册中心版本变化时 dispatch 本 effect,驱动插件重新求值 registered。
|
|
1365
|
+
*/
|
|
1366
|
+
var refreshContainers = StateEffect.define();
|
|
1367
|
+
/**
|
|
1324
1368
|
* 自定义 facet 用于传递编辑回调
|
|
1325
1369
|
*/
|
|
1326
1370
|
var containerEditCallback = Facet.define({ combine: (values) => values.length ? values[values.length - 1] : null });
|
|
@@ -1333,18 +1377,20 @@ var ContainerHeaderWidget = class extends WidgetType {
|
|
|
1333
1377
|
typeName;
|
|
1334
1378
|
containerIndex;
|
|
1335
1379
|
registered;
|
|
1336
|
-
|
|
1380
|
+
quotePrefix;
|
|
1381
|
+
constructor(typeName, containerIndex, registered, quotePrefix) {
|
|
1337
1382
|
super();
|
|
1338
1383
|
this.typeName = typeName;
|
|
1339
1384
|
this.containerIndex = containerIndex;
|
|
1340
1385
|
this.registered = registered;
|
|
1386
|
+
this.quotePrefix = quotePrefix;
|
|
1341
1387
|
}
|
|
1342
1388
|
toDOM() {
|
|
1343
1389
|
const container = document.createElement("span");
|
|
1344
1390
|
container.className = "container-widget-header";
|
|
1345
1391
|
const text = document.createElement("span");
|
|
1346
1392
|
text.className = "container-widget-text";
|
|
1347
|
-
text.textContent =
|
|
1393
|
+
text.textContent = `${this.quotePrefix}:::${this.typeName}`;
|
|
1348
1394
|
container.appendChild(text);
|
|
1349
1395
|
if (this.registered) {
|
|
1350
1396
|
const button = document.createElement("button");
|
|
@@ -1358,7 +1404,7 @@ var ContainerHeaderWidget = class extends WidgetType {
|
|
|
1358
1404
|
return container;
|
|
1359
1405
|
}
|
|
1360
1406
|
eq(other) {
|
|
1361
|
-
return this.typeName === other.typeName && this.containerIndex === other.containerIndex && this.registered === other.registered;
|
|
1407
|
+
return this.typeName === other.typeName && this.containerIndex === other.containerIndex && this.registered === other.registered && this.quotePrefix === other.quotePrefix;
|
|
1362
1408
|
}
|
|
1363
1409
|
ignoreEvent() {
|
|
1364
1410
|
return false;
|
|
@@ -1366,38 +1412,46 @@ var ContainerHeaderWidget = class extends WidgetType {
|
|
|
1366
1412
|
};
|
|
1367
1413
|
/**
|
|
1368
1414
|
* 只读的容器属性行 Widget(显示 { key: value, ... })
|
|
1415
|
+
* 嵌套在引用中时原始行带 "> " 前缀,展示时剔除,与头行 widget 风格一致
|
|
1369
1416
|
*/
|
|
1370
1417
|
var ContainerPropsWidget = class extends WidgetType {
|
|
1371
1418
|
propsText;
|
|
1372
|
-
|
|
1419
|
+
quotePrefix;
|
|
1420
|
+
constructor(propsText, quotePrefix) {
|
|
1373
1421
|
super();
|
|
1374
1422
|
this.propsText = propsText;
|
|
1423
|
+
this.quotePrefix = quotePrefix;
|
|
1375
1424
|
}
|
|
1376
1425
|
toDOM() {
|
|
1377
1426
|
const span = document.createElement("span");
|
|
1378
1427
|
span.className = "container-widget-props";
|
|
1379
|
-
span.textContent = this.propsText;
|
|
1428
|
+
span.textContent = this.propsText.startsWith(this.quotePrefix) ? this.propsText.slice(this.quotePrefix.length) : this.propsText;
|
|
1380
1429
|
return span;
|
|
1381
1430
|
}
|
|
1382
1431
|
eq(other) {
|
|
1383
|
-
return this.propsText === other.propsText;
|
|
1432
|
+
return this.propsText === other.propsText && this.quotePrefix === other.quotePrefix;
|
|
1384
1433
|
}
|
|
1385
1434
|
ignoreEvent() {
|
|
1386
1435
|
return false;
|
|
1387
1436
|
}
|
|
1388
1437
|
};
|
|
1389
1438
|
/**
|
|
1390
|
-
* 只读的容器结束行 Widget(显示
|
|
1439
|
+
* 只读的容器结束行 Widget(显示 :::,嵌套引用时保留 "> " 前缀)
|
|
1391
1440
|
*/
|
|
1392
1441
|
var ContainerCloseWidget = class extends WidgetType {
|
|
1442
|
+
text;
|
|
1443
|
+
constructor(text) {
|
|
1444
|
+
super();
|
|
1445
|
+
this.text = text;
|
|
1446
|
+
}
|
|
1393
1447
|
toDOM() {
|
|
1394
1448
|
const span = document.createElement("span");
|
|
1395
1449
|
span.className = "container-widget-text";
|
|
1396
|
-
span.textContent =
|
|
1450
|
+
span.textContent = this.text;
|
|
1397
1451
|
return span;
|
|
1398
1452
|
}
|
|
1399
|
-
eq() {
|
|
1400
|
-
return
|
|
1453
|
+
eq(other) {
|
|
1454
|
+
return this.text === other.text;
|
|
1401
1455
|
}
|
|
1402
1456
|
ignoreEvent() {
|
|
1403
1457
|
return false;
|
|
@@ -1415,14 +1469,14 @@ function findContainerDecorations(state) {
|
|
|
1415
1469
|
decorations.push({
|
|
1416
1470
|
from: headerLine.from,
|
|
1417
1471
|
to: headerLine.to,
|
|
1418
|
-
value: Decoration.replace({ widget: new ContainerHeaderWidget(container.typeName, index, container.registered) })
|
|
1472
|
+
value: Decoration.replace({ widget: new ContainerHeaderWidget(container.typeName, index, container.registered, container.quotePrefix ?? "") })
|
|
1419
1473
|
});
|
|
1420
1474
|
if (container.propsLineFrom > 0 && container.propsLineTo > 0) {
|
|
1421
1475
|
const propsLine = state.doc.lineAt(container.propsLineFrom);
|
|
1422
1476
|
decorations.push({
|
|
1423
1477
|
from: propsLine.from,
|
|
1424
1478
|
to: propsLine.to,
|
|
1425
|
-
value: Decoration.replace({ widget: new ContainerPropsWidget(propsLine.text) })
|
|
1479
|
+
value: Decoration.replace({ widget: new ContainerPropsWidget(propsLine.text, container.quotePrefix ?? "") })
|
|
1426
1480
|
});
|
|
1427
1481
|
}
|
|
1428
1482
|
if (container.endPos > 0) {
|
|
@@ -1430,10 +1484,11 @@ function findContainerDecorations(state) {
|
|
|
1430
1484
|
decorations.push({
|
|
1431
1485
|
from: endLine.from,
|
|
1432
1486
|
to: endLine.to,
|
|
1433
|
-
value: Decoration.replace({ widget: new ContainerCloseWidget() })
|
|
1487
|
+
value: Decoration.replace({ widget: new ContainerCloseWidget(endLine.text) })
|
|
1434
1488
|
});
|
|
1435
1489
|
}
|
|
1436
1490
|
});
|
|
1491
|
+
decorations.sort((a, b) => a.from - b.from || b.to - a.to);
|
|
1437
1492
|
return decorations;
|
|
1438
1493
|
}
|
|
1439
1494
|
/**
|
|
@@ -1462,11 +1517,19 @@ function handleEditButtonClick(event, view) {
|
|
|
1462
1517
|
*/
|
|
1463
1518
|
var containerWidgetPlugin = ViewPlugin.fromClass(class {
|
|
1464
1519
|
decorations;
|
|
1520
|
+
/** 上次构建装饰时的注册中心版本,用于感知异步注册(不能标 private,否则导出匿名类的 dts 报 TS4094) */
|
|
1521
|
+
registryVersion;
|
|
1465
1522
|
constructor(view) {
|
|
1523
|
+
this.registryVersion = componentRegistry.getVersion();
|
|
1466
1524
|
this.decorations = Decoration.set(findContainerDecorations(view.state), true);
|
|
1467
1525
|
}
|
|
1468
1526
|
update(update) {
|
|
1469
|
-
|
|
1527
|
+
const registryChanged = componentRegistry.getVersion() !== this.registryVersion;
|
|
1528
|
+
const woken = update.transactions.some((tr) => tr.effects.some((e) => e.is(refreshContainers)));
|
|
1529
|
+
if (update.docChanged || registryChanged || woken) {
|
|
1530
|
+
this.registryVersion = componentRegistry.getVersion();
|
|
1531
|
+
this.decorations = Decoration.set(findContainerDecorations(update.state), true);
|
|
1532
|
+
}
|
|
1470
1533
|
}
|
|
1471
1534
|
}, {
|
|
1472
1535
|
decorations: (value) => value.decorations,
|
|
@@ -2857,13 +2920,17 @@ function renderFormItemComponent(field) {
|
|
|
2857
2920
|
}
|
|
2858
2921
|
/**
|
|
2859
2922
|
* 根据 fields 自动生成 Form.Item 列表
|
|
2923
|
+
* 初始值走 <Form initialValues> + 按次打开的 key:
|
|
2924
|
+
* initialValues 在字段实体注册时消费,天然避开“Modal 首次挂载前 setFieldsValue 落空”的时序竞态;
|
|
2925
|
+
* key 每次打开变化触发 Form 重挂载,确保切换到不同容器时重新取值。
|
|
2860
2926
|
*/
|
|
2861
|
-
function renderAutoForm(form, fields) {
|
|
2927
|
+
function renderAutoForm(form, fields, initialValues, initKey) {
|
|
2862
2928
|
if (!fields || fields.length === 0) return null;
|
|
2863
2929
|
return /* @__PURE__ */ jsx(Form, {
|
|
2864
2930
|
form,
|
|
2865
2931
|
layout: "vertical",
|
|
2866
2932
|
preserve: false,
|
|
2933
|
+
initialValues,
|
|
2867
2934
|
children: fields.map((field) => {
|
|
2868
2935
|
if (!field.componentType) return null;
|
|
2869
2936
|
const formItemProps = {
|
|
@@ -2877,7 +2944,7 @@ function renderAutoForm(form, fields) {
|
|
|
2877
2944
|
children: renderFormItemComponent(field)
|
|
2878
2945
|
}, field.key);
|
|
2879
2946
|
})
|
|
2880
|
-
});
|
|
2947
|
+
}, initKey);
|
|
2881
2948
|
}
|
|
2882
2949
|
/** 字符串形式的历史属性值('true'/'false')还原为布尔,供 Switch 初始化 */
|
|
2883
2950
|
function toFormInitialValue(field, value) {
|
|
@@ -2916,7 +2983,7 @@ function normalizeValue(field, value) {
|
|
|
2916
2983
|
* 属性编辑弹窗组件
|
|
2917
2984
|
* 根据组件 schema 的 renderDialog 函数渲染弹窗内容
|
|
2918
2985
|
*/
|
|
2919
|
-
function EditDialog({ visible, typeName, currentProps, onSave, onClose }) {
|
|
2986
|
+
function EditDialog({ visible, typeName, currentProps, initKey, onSave, onClose }) {
|
|
2920
2987
|
const schema = componentRegistry.get(typeName);
|
|
2921
2988
|
const [formProps, setFormProps] = useState({});
|
|
2922
2989
|
const [form] = Form.useForm();
|
|
@@ -2932,16 +2999,19 @@ function EditDialog({ visible, typeName, currentProps, onSave, onClose }) {
|
|
|
2932
2999
|
...currentProps
|
|
2933
3000
|
};
|
|
2934
3001
|
}, [schema, currentProps]);
|
|
3002
|
+
const initialValues = useMemo(() => {
|
|
3003
|
+
const initial = {};
|
|
3004
|
+
for (const [key, value] of Object.entries(mergedProps)) {
|
|
3005
|
+
const field = schema?.fields?.find((f) => f.key === key);
|
|
3006
|
+
const formValue = toFormInitialValue(field ?? { key }, value);
|
|
3007
|
+
if (formValue !== void 0) initial[key] = formValue;
|
|
3008
|
+
}
|
|
3009
|
+
return initial;
|
|
3010
|
+
}, [mergedProps, schema]);
|
|
2935
3011
|
useEffect(() => {
|
|
2936
3012
|
if (visible) {
|
|
2937
3013
|
setFormProps({});
|
|
2938
|
-
|
|
2939
|
-
for (const [key, value] of Object.entries(mergedProps)) {
|
|
2940
|
-
const field = schema?.fields?.find((f) => f.key === key);
|
|
2941
|
-
const formValue = toFormInitialValue(field ?? { key }, value);
|
|
2942
|
-
if (formValue !== void 0) initial[key] = formValue;
|
|
2943
|
-
}
|
|
2944
|
-
form.setFieldsValue(initial);
|
|
3014
|
+
form.setFieldsValue(initialValues);
|
|
2945
3015
|
dirtyRef.current = false;
|
|
2946
3016
|
}
|
|
2947
3017
|
}, [visible, form]);
|
|
@@ -2996,7 +3066,7 @@ function EditDialog({ visible, typeName, currentProps, onSave, onClose }) {
|
|
|
2996
3066
|
};
|
|
2997
3067
|
const renderDialogContent = () => {
|
|
2998
3068
|
if (schema.renderDialog) return schema.renderDialog(context);
|
|
2999
|
-
if (schema.fields?.some((f) => f.componentType) && schema.fields) return renderAutoForm(form, schema.fields);
|
|
3069
|
+
if (schema.fields?.some((f) => f.componentType) && schema.fields) return renderAutoForm(form, schema.fields, initialValues, initKey);
|
|
3000
3070
|
return null;
|
|
3001
3071
|
};
|
|
3002
3072
|
return /* @__PURE__ */ jsx(Modal, {
|
|
@@ -3023,19 +3093,20 @@ function writeContainerProps(props) {
|
|
|
3023
3093
|
* 更新编辑器文档中的容器属性。
|
|
3024
3094
|
* 已有属性行则整行替换;没有属性行则在容器头行后插入一行。
|
|
3025
3095
|
* @param headerPos 容器头行(:::type)任意位置,用于无属性行时定位插入点
|
|
3096
|
+
* @param quotePrefix 容器所处的引用前缀(如 "> "),嵌套在引用中时插入的属性行需保持一致
|
|
3026
3097
|
*/
|
|
3027
|
-
function updateContainerProps(view, headerPos, propsLineFrom, propsLineTo, newProps) {
|
|
3098
|
+
function updateContainerProps(view, headerPos, propsLineFrom, propsLineTo, newProps, quotePrefix = "") {
|
|
3028
3099
|
const newPropsLine = writeContainerProps(newProps);
|
|
3029
3100
|
if (propsLineTo > propsLineFrom) view.dispatch({ changes: {
|
|
3030
3101
|
from: propsLineFrom,
|
|
3031
3102
|
to: propsLineTo,
|
|
3032
|
-
insert: newPropsLine
|
|
3103
|
+
insert: `${quotePrefix}${newPropsLine}`
|
|
3033
3104
|
} });
|
|
3034
3105
|
else {
|
|
3035
3106
|
const headerLine = view.state.doc.lineAt(headerPos);
|
|
3036
3107
|
view.dispatch({ changes: {
|
|
3037
3108
|
from: headerLine.to,
|
|
3038
|
-
insert: `\n${newPropsLine}`
|
|
3109
|
+
insert: `\n${quotePrefix}${newPropsLine}`
|
|
3039
3110
|
} });
|
|
3040
3111
|
}
|
|
3041
3112
|
}
|
|
@@ -3160,6 +3231,7 @@ var MarkdownEditorInner = ({ defaultValue = "", value, onChange, showPreview = t
|
|
|
3160
3231
|
const [dialogVisible, setDialogVisible] = useState(false);
|
|
3161
3232
|
const [dialogTypeName, setDialogTypeName] = useState("");
|
|
3162
3233
|
const [dialogContainer, setDialogContainer] = useState(null);
|
|
3234
|
+
const [dialogSeq, setDialogSeq] = useState(0);
|
|
3163
3235
|
const app = App.useApp();
|
|
3164
3236
|
const notify = useCallback((type, text) => {
|
|
3165
3237
|
if (onNotify) {
|
|
@@ -3179,6 +3251,9 @@ var MarkdownEditorInner = ({ defaultValue = "", value, onChange, showPreview = t
|
|
|
3179
3251
|
}, [onChange]);
|
|
3180
3252
|
useImperativeHandle(ref, () => ({ getContent: () => content }), [content]);
|
|
3181
3253
|
const registryVersion = useRegistryVersion();
|
|
3254
|
+
useEffect(() => {
|
|
3255
|
+
editorView?.dispatch({ effects: refreshContainers.of(null) });
|
|
3256
|
+
}, [registryVersion, editorView]);
|
|
3182
3257
|
const extraToolbarItems = useMemo(() => {
|
|
3183
3258
|
const merged = /* @__PURE__ */ new Map();
|
|
3184
3259
|
for (const schema of componentRegistry.getAll()) merged.set(schema.name, schema);
|
|
@@ -3212,10 +3287,11 @@ var MarkdownEditorInner = ({ defaultValue = "", value, onChange, showPreview = t
|
|
|
3212
3287
|
const handleEditContainer = useCallback((_view, container) => {
|
|
3213
3288
|
setDialogTypeName(container.typeName);
|
|
3214
3289
|
setDialogContainer(container);
|
|
3290
|
+
setDialogSeq((seq) => seq + 1);
|
|
3215
3291
|
setDialogVisible(true);
|
|
3216
3292
|
}, []);
|
|
3217
3293
|
const handleDialogSave = useCallback((newProps) => {
|
|
3218
|
-
if (editorView && dialogContainer) updateContainerProps(editorView, dialogContainer.startPos, dialogContainer.propsLineFrom, dialogContainer.propsLineTo, newProps);
|
|
3294
|
+
if (editorView && dialogContainer) updateContainerProps(editorView, dialogContainer.startPos, dialogContainer.propsLineFrom, dialogContainer.propsLineTo, newProps, dialogContainer.quotePrefix);
|
|
3219
3295
|
}, [editorView, dialogContainer]);
|
|
3220
3296
|
const handleDialogClose = useCallback(() => {
|
|
3221
3297
|
setDialogVisible(false);
|
|
@@ -3252,6 +3328,7 @@ var MarkdownEditorInner = ({ defaultValue = "", value, onChange, showPreview = t
|
|
|
3252
3328
|
visible: dialogVisible,
|
|
3253
3329
|
typeName: dialogTypeName,
|
|
3254
3330
|
currentProps: dialogContainer?.props ?? {},
|
|
3331
|
+
initKey: dialogSeq,
|
|
3255
3332
|
onSave: handleDialogSave,
|
|
3256
3333
|
onClose: handleDialogClose
|
|
3257
3334
|
})
|