wendang 0.1.0 → 0.1.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/LICENSE +43 -2
- package/NOTICE.md +1 -1
- package/README.md +120 -52
- package/dist/cjs/document.js +1 -19
- package/dist/cjs/index.js +1 -25
- package/dist/cjs/mindmap.js +1 -22
- package/dist/cjs/schema.js +1 -11
- package/dist/cjs/shared/anchor.js +1 -201
- package/dist/cjs/shared/callout.js +1 -64
- package/dist/cjs/shared/code-block.js +1 -33
- package/dist/cjs/shared/code-languages.js +1 -51
- package/dist/cjs/shared/doc-compatibility.js +1 -23
- package/dist/cjs/shared/doc-text.js +1 -52
- package/dist/cjs/shared/document-colors.js +1 -61
- package/dist/cjs/shared/inline-comments.js +1 -179
- package/dist/cjs/shared/mind-map-folding.js +1 -14
- package/dist/cjs/shared/mind-map-phase2.js +1 -133
- package/dist/cjs/shared/mind-map.js +1 -445
- package/dist/cjs/shared/mind-topic-text.js +1 -57
- package/dist/cjs/shared/node-catalog.js +1 -62
- package/dist/cjs/shared/presence.js +1 -141
- package/dist/cjs/shared/safe-href.js +1 -36
- package/dist/cjs/shared/table-cell-format.js +1 -18
- package/dist/cjs/shared/table-layout.js +1 -28
- package/dist/cjs/shared/types.js +1 -2
- package/dist/cjs/shared/video-embed.js +1 -102
- package/dist/cjs/shared/workbook.js +1 -152
- package/dist/cjs/spreadsheet.js +1 -17
- package/dist/cjs/types.js +1 -17
- package/dist/cjs/validation/callout.js +1 -17
- package/dist/cjs/validation/doc-node-whitelist.js +1 -71
- package/dist/cjs/validation/error.js +1 -17
- package/dist/cjs/validation/mind-map.js +1 -129
- package/dist/cjs/validation/schema-version.js +1 -5
- package/dist/cjs/validation/schema.js +1 -376
- package/dist/cjs/validation/video-embed.js +1 -17
- package/dist/cjs/validation/workbook.js +1 -17
- package/dist/esm/document.js +1 -3
- package/dist/esm/index.js +1 -3
- package/dist/esm/mindmap.js +1 -4
- package/dist/esm/schema.js +1 -3
- package/dist/esm/shared/anchor.js +1 -192
- package/dist/esm/shared/callout.js +1 -56
- package/dist/esm/shared/code-block.js +1 -25
- package/dist/esm/shared/code-languages.js +1 -46
- package/dist/esm/shared/doc-compatibility.js +1 -20
- package/dist/esm/shared/doc-text.js +1 -48
- package/dist/esm/shared/document-colors.js +1 -56
- package/dist/esm/shared/inline-comments.js +1 -173
- package/dist/esm/shared/mind-map-folding.js +1 -10
- package/dist/esm/shared/mind-map-phase2.js +1 -121
- package/dist/esm/shared/mind-map.js +1 -427
- package/dist/esm/shared/mind-topic-text.js +1 -49
- package/dist/esm/shared/node-catalog.js +1 -57
- package/dist/esm/shared/presence.js +1 -130
- package/dist/esm/shared/safe-href.js +1 -32
- package/dist/esm/shared/table-cell-format.js +1 -14
- package/dist/esm/shared/table-layout.js +1 -23
- package/dist/esm/shared/types.js +1 -1
- package/dist/esm/shared/video-embed.js +1 -96
- package/dist/esm/shared/workbook.js +1 -144
- package/dist/esm/spreadsheet.js +1 -1
- package/dist/esm/types.js +1 -1
- package/dist/esm/validation/callout.js +1 -1
- package/dist/esm/validation/doc-node-whitelist.js +1 -68
- package/dist/esm/validation/error.js +1 -13
- package/dist/esm/validation/mind-map.js +1 -125
- package/dist/esm/validation/schema-version.js +1 -2
- package/dist/esm/validation/schema.js +1 -372
- package/dist/esm/validation/video-embed.js +1 -1
- package/dist/esm/validation/workbook.js +1 -1
- package/dist/types/shared/anchor.d.ts +0 -55
- package/dist/types/shared/callout.d.ts +0 -2
- package/dist/types/shared/code-block.d.ts +0 -1
- package/dist/types/shared/code-languages.d.ts +0 -19
- package/dist/types/shared/doc-text.d.ts +0 -14
- package/dist/types/shared/document-colors.d.ts +0 -4
- package/dist/types/shared/inline-comments.d.ts +0 -42
- package/dist/types/shared/mind-map-folding.d.ts +0 -2
- package/dist/types/shared/mind-map.d.ts +0 -4
- package/dist/types/shared/mind-topic-text.d.ts +0 -2
- package/dist/types/shared/node-catalog.d.ts +0 -17
- package/dist/types/shared/presence.d.ts +0 -51
- package/dist/types/shared/safe-href.d.ts +0 -1
- package/dist/types/shared/table-cell-format.d.ts +0 -1
- package/dist/types/shared/table-layout.d.ts +0 -3
- package/dist/types/shared/types.d.ts +0 -4
- package/dist/types/shared/video-embed.d.ts +0 -1
- package/dist/types/shared/workbook.d.ts +0 -2
- package/dist/types/validation/doc-node-whitelist.d.ts +0 -19
- package/dist/types/validation/mind-map.d.ts +0 -2
- package/dist/types/validation/schema-version.d.ts +0 -1
- package/dist/types/validation/schema.d.ts +0 -34
- package/package.json +3 -3
package/dist/cjs/spreadsheet.js
CHANGED
|
@@ -1,17 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./shared/workbook.js"), exports);
|
|
1
|
+
"use strict";var e=this&&this.__createBinding||(Object.create?function(e,t,r,o){void 0===o&&(o=r);var i=Object.getOwnPropertyDescriptor(t,r);i&&!("get"in i?!t.__esModule:i.writable||i.configurable)||(i={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,o,i)}:function(e,t,r,o){void 0===o&&(o=r),e[o]=t[r]}),t=this&&this.__exportStar||function(t,r){for(var o in t)"default"===o||Object.prototype.hasOwnProperty.call(r,o)||e(r,t,o)};Object.defineProperty(exports,"__esModule",{value:!0}),t(require("./shared/workbook.js"),exports);
|
package/dist/cjs/types.js
CHANGED
|
@@ -1,17 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./shared/types.js"), exports);
|
|
1
|
+
"use strict";var e=this&&this.__createBinding||(Object.create?function(e,t,r,i){void 0===i&&(i=r);var o=Object.getOwnPropertyDescriptor(t,r);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,o)}:function(e,t,r,i){void 0===i&&(i=r),e[i]=t[r]}),t=this&&this.__exportStar||function(t,r){for(var i in t)"default"===i||Object.prototype.hasOwnProperty.call(r,i)||e(r,t,i)};Object.defineProperty(exports,"__esModule",{value:!0}),t(require("./shared/types.js"),exports);
|
|
@@ -1,17 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("../shared/callout.js"), exports);
|
|
1
|
+
"use strict";var e=this&&this.__createBinding||(Object.create?function(e,t,r,i){void 0===i&&(i=r);var o=Object.getOwnPropertyDescriptor(t,r);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,o)}:function(e,t,r,i){void 0===i&&(i=r),e[i]=t[r]}),t=this&&this.__exportStar||function(t,r){for(var i in t)"default"===i||Object.prototype.hasOwnProperty.call(r,i)||e(r,t,i)};Object.defineProperty(exports,"__esModule",{value:!0}),t(require("../shared/callout.js"),exports);
|
|
@@ -1,71 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ALLOWED_MARKS = exports.ALLOWED_NODES = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* 文档节点白名单(**纯数据,无依赖**)。
|
|
6
|
-
*
|
|
7
|
-
* 为什么单独成文件:白名单需要被三处引用——
|
|
8
|
-
* 1) 服务端校验(doc-schema.service.ts)
|
|
9
|
-
* 2) 一致性测试(与前端 node-catalog 交叉核对)
|
|
10
|
-
* 3) 导出序列化器的防漂移测试
|
|
11
|
-
* 若把它放在 doc-schema.service.ts 里,测试导入会连带加载 Nest 依赖,
|
|
12
|
-
* 导致 spec 在测试环境下加载失败(实测:整个测试文件被静默跳过)。
|
|
13
|
-
*
|
|
14
|
-
* 因此这里只放数据,不放逻辑,任何一方都能安全引用。
|
|
15
|
-
*
|
|
16
|
-
* 新增节点时必须同时更新:
|
|
17
|
-
* 1) 本文件
|
|
18
|
-
* 2) 前端 web/src/shared/node-catalog.ts
|
|
19
|
-
* 3) 导出序列化器 markdown-serializer.ts 的处理分支
|
|
20
|
-
* 三处一致性由测试自动核对(读取真实文件,而非维护测试内副本)。
|
|
21
|
-
*/
|
|
22
|
-
exports.ALLOWED_NODES = new Set([
|
|
23
|
-
'mindMapDescription', 'mindMapNote', 'mindMapRelation',
|
|
24
|
-
'mindMap',
|
|
25
|
-
'mindMapTopic',
|
|
26
|
-
'doc',
|
|
27
|
-
'paragraph',
|
|
28
|
-
'text',
|
|
29
|
-
'heading',
|
|
30
|
-
'bulletList',
|
|
31
|
-
'orderedList',
|
|
32
|
-
'listItem',
|
|
33
|
-
// 待办列表:前端编辑器(TaskList/TaskItem)支持,导出序列化器也支持,
|
|
34
|
-
// 但白名单此前漏了这两个节点 —— 导致「用户插入待办列表后保存必被拒」。
|
|
35
|
-
// 由导入测试暴露(详见 doc-schema.service.spec.ts 的三方一致性断言)。
|
|
36
|
-
'taskList',
|
|
37
|
-
'taskItem',
|
|
38
|
-
'blockquote',
|
|
39
|
-
'codeBlock',
|
|
40
|
-
'horizontalRule',
|
|
41
|
-
'hardBreak',
|
|
42
|
-
'image',
|
|
43
|
-
'fileAttachment', // 视频或文件卡片(只存 attachmentId,不存存储地址)
|
|
44
|
-
'videoEmbed',
|
|
45
|
-
'callout', // 高亮块(容器,content: block+)
|
|
46
|
-
// 分栏:columns(行,content: column+)包 column(栏,content: block+)。
|
|
47
|
-
// 两个都要登记——只登记外层时,栏节点会在保存校验处被判为「不支持」而拒绝写入。
|
|
48
|
-
'columns',
|
|
49
|
-
'column',
|
|
50
|
-
'table',
|
|
51
|
-
'tableRow',
|
|
52
|
-
'tableHeader',
|
|
53
|
-
'tableCell',
|
|
54
|
-
'pageLink', // 内部页面引用 [[page]]
|
|
55
|
-
'mention', // @提及用户
|
|
56
|
-
'mathInline', // 行内公式(KaTeX)
|
|
57
|
-
'mathBlock', // 块级公式(KaTeX)
|
|
58
|
-
]);
|
|
59
|
-
/** 允许的标记类型。 */
|
|
60
|
-
exports.ALLOWED_MARKS = new Set([
|
|
61
|
-
'bold',
|
|
62
|
-
'italic',
|
|
63
|
-
'strike',
|
|
64
|
-
'code',
|
|
65
|
-
'link',
|
|
66
|
-
// 行内样式:文字颜色与背景高亮。两者的颜色属性必须在
|
|
67
|
-
// doc-schema.service.ts 的 ALLOWED_ATTRS 里同时登记,否则颜色值会被剥离、
|
|
68
|
-
// 只剩一个空标记(实测的"颜色丢失但标记还在"就是这么来的)。
|
|
69
|
-
'textStyle',
|
|
70
|
-
'highlight',
|
|
71
|
-
]);
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ALLOWED_MARKS=exports.ALLOWED_NODES=void 0,exports.ALLOWED_NODES=new Set(["mindMapDescription","mindMapNote","mindMapRelation","mindMap","mindMapTopic","doc","paragraph","text","heading","bulletList","orderedList","listItem","taskList","taskItem","blockquote","codeBlock","horizontalRule","hardBreak","image","fileAttachment","videoEmbed","callout","columns","column","table","tableRow","tableHeader","tableCell","pageLink","mention","mathInline","mathBlock"]),exports.ALLOWED_MARKS=new Set(["bold","italic","strike","code","link","textStyle","highlight"]);
|
|
@@ -1,17 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ContentValidationError = void 0;
|
|
4
|
-
class ContentValidationError extends Error {
|
|
5
|
-
code;
|
|
6
|
-
status;
|
|
7
|
-
details;
|
|
8
|
-
constructor(code, message, status = 422, details) {
|
|
9
|
-
super(message);
|
|
10
|
-
this.code = code;
|
|
11
|
-
this.status = status;
|
|
12
|
-
this.details = details;
|
|
13
|
-
this.name = 'ContentValidationError';
|
|
14
|
-
}
|
|
15
|
-
static validation(message) { return new ContentValidationError('validation.failed', message); }
|
|
16
|
-
}
|
|
17
|
-
exports.ContentValidationError = ContentValidationError;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ContentValidationError=void 0;class ContentValidationError extends Error{code;status;details;constructor(t,r,o=422,e){super(r),this.code=t,this.status=o,this.details=e,this.name="ContentValidationError"}static validation(t){return new ContentValidationError("validation.failed",t)}}exports.ContentValidationError=ContentValidationError;
|
|
@@ -1,129 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validateMindMap = validateMindMap;
|
|
4
|
-
exports.mindMapOutline = mindMapOutline;
|
|
5
|
-
const idOk = (v) => typeof v === 'string' && /^[\w-]{1,80}$/.test(v);
|
|
6
|
-
function validateMindMap(node) {
|
|
7
|
-
const a = node.attrs;
|
|
8
|
-
if (!a || ![1, 2, 3].includes(Number(a.formatVersion)) || !idOk(a.id) || !idOk(a.rootId) ||
|
|
9
|
-
!['right', 'left', 'both', 'down'].includes(String(a.layout)) ||
|
|
10
|
-
!['blue', 'teal', 'violet', 'amber'].includes(String(a.theme)) ||
|
|
11
|
-
typeof a.height !== 'number' || !Number.isFinite(a.height) || a.height < 240 || a.height > 800) {
|
|
12
|
-
throw new Error('思维导图属性或格式版本无效');
|
|
13
|
-
}
|
|
14
|
-
if (!Array.isArray(node.content) || node.content.length < 1 || node.content.filter(t => t?.type === 'mindMapTopic').length > 500 || node.content.length > 1500) {
|
|
15
|
-
throw new Error('思维导图需要 1~500 个主题');
|
|
16
|
-
}
|
|
17
|
-
const ids = new Set();
|
|
18
|
-
for (const t of node.content.filter(t => t?.type !== 'mindMapRelation')) {
|
|
19
|
-
const p = t?.attrs;
|
|
20
|
-
if (!t || t.type !== 'mindMapTopic' || !p || !idOk(p.id) || ids.has(p.id) ||
|
|
21
|
-
typeof p.parentId !== 'string' || (p.parentId !== '' && !idOk(p.parentId)) ||
|
|
22
|
-
typeof p.order !== 'number' || !Number.isFinite(p.order) || Math.abs(p.order) > 1e12 ||
|
|
23
|
-
(t.content !== undefined && !Array.isArray(t.content)))
|
|
24
|
-
throw new Error('思维导图主题结构无效');
|
|
25
|
-
ids.add(p.id);
|
|
26
|
-
for (const [key, values] of Object.entries({ shape: ['round', 'pill', 'text'], align: ['left', 'center', 'right'] })) {
|
|
27
|
-
if (p[key] !== undefined && p[key] !== null && !values.includes(String(p[key])))
|
|
28
|
-
throw new Error('导图主题样式无效');
|
|
29
|
-
}
|
|
30
|
-
for (const key of ['color', 'background'])
|
|
31
|
-
if (p[key] && !['#18243a', '#ffffff', '#3864ef', '#087f8c', '#7950c7', '#a66b08', '#d94848', '#f3f5fb', '#dce7ff', '#d3f4e9', '#ece0ff', '#fff0c2', '#ffe1e1', '#233044'].includes(String(p[key])))
|
|
32
|
-
throw new Error('导图颜色无效');
|
|
33
|
-
if (p.fontSize !== undefined && p.fontSize !== null && ![12, 14, 16, 18, 20].includes(Number(p.fontSize)))
|
|
34
|
-
throw new Error('导图字号无效');
|
|
35
|
-
if (p.icon && !['💡', '🎯', '📌', '🚩', '⭐', '✅', '⚠️', '💬', '📅', '🔎'].includes(String(p.icon)))
|
|
36
|
-
throw new Error('导图图标无效');
|
|
37
|
-
if (p.done !== undefined && p.done !== null && typeof p.done !== 'boolean')
|
|
38
|
-
throw new Error('导图状态无效');
|
|
39
|
-
if (p.side !== undefined && p.side !== null && p.side !== -1 && p.side !== 1)
|
|
40
|
-
throw new Error('导图分支方向无效');
|
|
41
|
-
if (p.attachmentId && (typeof p.attachmentId !== 'string' || !/^[0-9a-f-]{36}$/i.test(p.attachmentId)))
|
|
42
|
-
throw new Error('导图图片引用无效');
|
|
43
|
-
let length = 0;
|
|
44
|
-
const fields = new Set();
|
|
45
|
-
let fieldsStarted = false, noteStarted = false;
|
|
46
|
-
for (const c of t.content ?? []) {
|
|
47
|
-
if (c && ['mindMapDescription', 'mindMapNote'].includes(c.type ?? '')) {
|
|
48
|
-
if (c.type === 'mindMapDescription' && noteStarted)
|
|
49
|
-
throw new Error('主题描述必须位于备注之前');
|
|
50
|
-
fieldsStarted = true;
|
|
51
|
-
if (c.type === 'mindMapNote')
|
|
52
|
-
noteStarted = true;
|
|
53
|
-
if (fields.has(c.type) || (c.content !== undefined && !Array.isArray(c.content)) || c.content?.some(n => n?.type !== 'text' || typeof n.text !== 'string' || n.content !== undefined) || (c.content ?? []).reduce((n, x) => n + (x.text?.length ?? 0), 0) > 4000)
|
|
54
|
-
throw new Error('导图描述或备注无效');
|
|
55
|
-
fields.add(c.type);
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
if (!c || c.type !== 'text' || typeof c.text !== 'string' || c.content !== undefined) {
|
|
59
|
-
throw new Error('思维导图主题只支持纯文本');
|
|
60
|
-
}
|
|
61
|
-
if (fieldsStarted)
|
|
62
|
-
throw new Error('主题标题必须位于描述和备注之前');
|
|
63
|
-
length += c.text.length;
|
|
64
|
-
}
|
|
65
|
-
if (length > 2000)
|
|
66
|
-
throw new Error('单个主题文字不得超过 2000 字符');
|
|
67
|
-
}
|
|
68
|
-
if (!ids.has(a.rootId))
|
|
69
|
-
throw new Error('思维导图缺少中心主题');
|
|
70
|
-
if (a.branchStyle && !['curve', 'straight', 'step'].includes(String(a.branchStyle)))
|
|
71
|
-
throw new Error('分支样式无效');
|
|
72
|
-
const relationIds = new Set();
|
|
73
|
-
for (const r of node.content.filter(t => t?.type === 'mindMapRelation')) {
|
|
74
|
-
const p = r.attrs;
|
|
75
|
-
if (!p || !idOk(p.id) || ids.has(p.id) || relationIds.has(p.id) || !idOk(p.source) || !idOk(p.target) || p.source === p.target ||
|
|
76
|
-
!['related', 'depends', 'reference'].includes(String(p.kind)) || typeof p.label !== 'string' || p.label.length > 200 || r.content?.length)
|
|
77
|
-
throw new Error('导图关系线无效');
|
|
78
|
-
relationIds.add(p.id);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
/** Same deterministic tree projection as the reader; orphan/cycle conflicts never discard text. */
|
|
82
|
-
function mindMapOutline(node) {
|
|
83
|
-
const rootId = String(node.attrs?.rootId ?? '');
|
|
84
|
-
if (!idOk(rootId) || !Array.isArray(node.content) || node.content.filter(t => t?.type === 'mindMapTopic').length > 500 || node.content.length > 1500)
|
|
85
|
-
return [];
|
|
86
|
-
const topics = (node.content ?? []).filter(t => t.type === 'mindMapTopic').map(t => ({
|
|
87
|
-
id: String(t.attrs?.id ?? ''), parentId: String(t.attrs?.parentId ?? ''),
|
|
88
|
-
order: Number(t.attrs?.order) || 0, text: (t.content ?? []).filter(c => c.type === 'text').map(c => c.text ?? '').join(''),
|
|
89
|
-
...Object.fromEntries((t.content ?? []).filter(c => c.type === 'mindMapDescription' || c.type === 'mindMapNote')
|
|
90
|
-
.map(c => [c.type === 'mindMapDescription' ? 'description' : 'note', (c.content ?? []).map(n => n.text ?? '').join('')])),
|
|
91
|
-
...(t.attrs?.attachmentId ? { attachmentId: String(t.attrs.attachmentId) } : {}),
|
|
92
|
-
}));
|
|
93
|
-
if (!topics.some(t => t.id === rootId))
|
|
94
|
-
return [];
|
|
95
|
-
const byId = new Map(topics.map(t => [t.id, t]));
|
|
96
|
-
for (const t of topics) {
|
|
97
|
-
if (t.id === rootId)
|
|
98
|
-
t.parentId = '';
|
|
99
|
-
else if (!byId.has(t.parentId) || t.parentId === t.id)
|
|
100
|
-
t.parentId = rootId;
|
|
101
|
-
}
|
|
102
|
-
for (const start of [...topics].sort((a, b) => a.id.localeCompare(b.id))) {
|
|
103
|
-
const path = [], seen = new Set();
|
|
104
|
-
let current = start;
|
|
105
|
-
while (current && current.id !== rootId) {
|
|
106
|
-
if (seen.has(current.id)) {
|
|
107
|
-
byId.get(path.slice(path.indexOf(current.id)).sort()[0]).parentId = rootId;
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
path.push(current.id);
|
|
111
|
-
seen.add(current.id);
|
|
112
|
-
current = byId.get(current.parentId);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
topics.sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));
|
|
116
|
-
const result = [];
|
|
117
|
-
const visited = new Set();
|
|
118
|
-
const visit = (id, depth) => {
|
|
119
|
-
const topic = byId.get(id);
|
|
120
|
-
if (!topic || visited.has(id))
|
|
121
|
-
return;
|
|
122
|
-
visited.add(id);
|
|
123
|
-
result.push({ ...topic, depth });
|
|
124
|
-
for (const child of topics.filter(t => t.parentId === id))
|
|
125
|
-
visit(child.id, depth + 1);
|
|
126
|
-
};
|
|
127
|
-
visit(rootId, 0);
|
|
128
|
-
return result;
|
|
129
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.validateMindMap=function validateMindMap(t){const e=t.attrs;if(!e||![1,2,3].includes(Number(e.formatVersion))||!idOk(e.id)||!idOk(e.rootId)||!["right","left","both","down"].includes(String(e.layout))||!["blue","teal","violet","amber"].includes(String(e.theme))||"number"!=typeof e.height||!Number.isFinite(e.height)||e.height<240||e.height>800)throw new Error("思维导图属性或格式版本无效");if(!Array.isArray(t.content)||t.content.length<1||t.content.filter(t=>"mindMapTopic"===t?.type).length>500||t.content.length>1500)throw new Error("思维导图需要 1~500 个主题");const r=new Set;for(const e of t.content.filter(t=>"mindMapRelation"!==t?.type)){const t=e?.attrs;if(!e||"mindMapTopic"!==e.type||!t||!idOk(t.id)||r.has(t.id)||"string"!=typeof t.parentId||""!==t.parentId&&!idOk(t.parentId)||"number"!=typeof t.order||!Number.isFinite(t.order)||Math.abs(t.order)>1e12||void 0!==e.content&&!Array.isArray(e.content))throw new Error("思维导图主题结构无效");r.add(t.id);for(const[e,r]of Object.entries({shape:["round","pill","text"],align:["left","center","right"]}))if(void 0!==t[e]&&null!==t[e]&&!r.includes(String(t[e])))throw new Error("导图主题样式无效");for(const e of["color","background"])if(t[e]&&!["#18243a","#ffffff","#3864ef","#087f8c","#7950c7","#a66b08","#d94848","#f3f5fb","#dce7ff","#d3f4e9","#ece0ff","#fff0c2","#ffe1e1","#233044"].includes(String(t[e])))throw new Error("导图颜色无效");if(void 0!==t.fontSize&&null!==t.fontSize&&![12,14,16,18,20].includes(Number(t.fontSize)))throw new Error("导图字号无效");if(t.icon&&!["💡","🎯","📌","🚩","⭐","✅","⚠️","💬","📅","🔎"].includes(String(t.icon)))throw new Error("导图图标无效");if(void 0!==t.done&&null!==t.done&&"boolean"!=typeof t.done)throw new Error("导图状态无效");if(void 0!==t.side&&null!==t.side&&-1!==t.side&&1!==t.side)throw new Error("导图分支方向无效");if(t.attachmentId&&("string"!=typeof t.attachmentId||!/^[0-9a-f-]{36}$/i.test(t.attachmentId)))throw new Error("导图图片引用无效");let n=0;const o=new Set;let i=!1,d=!1;for(const t of e.content??[])if(t&&["mindMapDescription","mindMapNote"].includes(t.type??"")){if("mindMapDescription"===t.type&&d)throw new Error("主题描述必须位于备注之前");if(i=!0,"mindMapNote"===t.type&&(d=!0),o.has(t.type)||void 0!==t.content&&!Array.isArray(t.content)||t.content?.some(t=>"text"!==t?.type||"string"!=typeof t.text||void 0!==t.content)||(t.content??[]).reduce((t,e)=>t+(e.text?.length??0),0)>4e3)throw new Error("导图描述或备注无效");o.add(t.type)}else{if(!t||"text"!==t.type||"string"!=typeof t.text||void 0!==t.content)throw new Error("思维导图主题只支持纯文本");if(i)throw new Error("主题标题必须位于描述和备注之前");n+=t.text.length}if(n>2e3)throw new Error("单个主题文字不得超过 2000 字符")}if(!r.has(e.rootId))throw new Error("思维导图缺少中心主题");if(e.branchStyle&&!["curve","straight","step"].includes(String(e.branchStyle)))throw new Error("分支样式无效");const n=new Set;for(const e of t.content.filter(t=>"mindMapRelation"===t?.type)){const t=e.attrs;if(!t||!idOk(t.id)||r.has(t.id)||n.has(t.id)||!idOk(t.source)||!idOk(t.target)||t.source===t.target||!["related","depends","reference"].includes(String(t.kind))||"string"!=typeof t.label||t.label.length>200||e.content?.length)throw new Error("导图关系线无效");n.add(t.id)}},exports.mindMapOutline=function mindMapOutline(t){const e=String(t.attrs?.rootId??"");if(!idOk(e)||!Array.isArray(t.content)||t.content.filter(t=>"mindMapTopic"===t?.type).length>500||t.content.length>1500)return[];const r=(t.content??[]).filter(t=>"mindMapTopic"===t.type).map(t=>({id:String(t.attrs?.id??""),parentId:String(t.attrs?.parentId??""),order:Number(t.attrs?.order)||0,text:(t.content??[]).filter(t=>"text"===t.type).map(t=>t.text??"").join(""),...Object.fromEntries((t.content??[]).filter(t=>"mindMapDescription"===t.type||"mindMapNote"===t.type).map(t=>["mindMapDescription"===t.type?"description":"note",(t.content??[]).map(t=>t.text??"").join("")])),...t.attrs?.attachmentId?{attachmentId:String(t.attrs.attachmentId)}:{}}));if(!r.some(t=>t.id===e))return[];const n=new Map(r.map(t=>[t.id,t]));for(const t of r)t.id===e?t.parentId="":n.has(t.parentId)&&t.parentId!==t.id||(t.parentId=e);for(const t of[...r].sort((t,e)=>t.id.localeCompare(e.id))){const r=[],o=new Set;let i=t;for(;i&&i.id!==e;){if(o.has(i.id)){n.get(r.slice(r.indexOf(i.id)).sort()[0]).parentId=e;break}r.push(i.id),o.add(i.id),i=n.get(i.parentId)}}r.sort((t,e)=>t.order-e.order||t.id.localeCompare(e.id));const o=[],i=new Set,visit=(t,e)=>{const d=n.get(t);if(d&&!i.has(t)){i.add(t),o.push({...d,depth:e});for(const n of r.filter(e=>e.parentId===t))visit(n.id,e+1)}};return visit(e,0),o};const idOk=t=>"string"==typeof t&&/^[\w-]{1,80}$/.test(t);
|
|
@@ -1,5 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CONTENT_SCHEMA_VERSION = void 0;
|
|
4
|
-
/** 协同握手与正文写入共用,不依赖 Nest 服务。 */
|
|
5
|
-
exports.CONTENT_SCHEMA_VERSION = 10;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.CONTENT_SCHEMA_VERSION=void 0,exports.CONTENT_SCHEMA_VERSION=10;
|