wendang 0.1.0 → 0.2.0
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/headings.js +1 -0
- 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/headings.js +1 -0
- 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/document.d.ts +1 -0
- package/dist/types/shared/anchor.d.ts +0 -55
- package/dist/types/shared/callout.d.ts +39 -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/headings.d.ts +7 -0
- 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 +9 -2
- 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 +9 -9
|
@@ -1,64 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CALLOUT_FILLS = exports.CALLOUT_COLORS = exports.CALLOUT_ICONS = exports.CALLOUT_TONES = void 0;
|
|
4
|
-
exports.validCalloutAttrs = validCalloutAttrs;
|
|
5
|
-
exports.effectiveCallout = effectiveCallout;
|
|
6
|
-
exports.calloutDOMAttributes = calloutDOMAttributes;
|
|
7
|
-
exports.calloutMetadata = calloutMetadata;
|
|
8
|
-
exports.readCalloutMetadata = readCalloutMetadata;
|
|
9
|
-
/** Document attributes only; shared with server validation by a source parity test. */
|
|
10
|
-
exports.CALLOUT_TONES = ['info', 'success', 'warning', 'danger'];
|
|
11
|
-
exports.CALLOUT_ICONS = ['💡', 'ℹ️', '✅', '⚠️', '❗', '📌', '🎯', '💬', '📖', '📝', '🚀', '🔔', '🔎', '⭐', '🌅', '🛠️', '📅', '🔒', '❤️', '🎉', '❓', '📎', '🏁', '🔥'];
|
|
12
|
-
exports.CALLOUT_COLORS = ['gray', 'red', 'orange', 'yellow', 'green', 'blue', 'purple'];
|
|
13
|
-
exports.CALLOUT_FILLS = [...exports.CALLOUT_COLORS, ...exports.CALLOUT_COLORS.map(c => `${c}-strong`)];
|
|
14
|
-
function validCalloutAttrs(raw) {
|
|
15
|
-
if (!raw || typeof raw !== 'object' || Array.isArray(raw))
|
|
16
|
-
return false;
|
|
17
|
-
const attrs = raw;
|
|
18
|
-
const valid = (key, values) => attrs[key] === undefined || attrs[key] === null ||
|
|
19
|
-
(typeof attrs[key] === 'string' && values.includes(attrs[key]));
|
|
20
|
-
return valid('tone', exports.CALLOUT_TONES) && valid('icon', ['', ...exports.CALLOUT_ICONS]) && valid('textColor', exports.CALLOUT_COLORS) &&
|
|
21
|
-
valid('borderColor', ['none', ...exports.CALLOUT_COLORS]) && valid('backgroundColor', ['none', ...exports.CALLOUT_FILLS]);
|
|
22
|
-
}
|
|
23
|
-
function effectiveCallout(attrs = {}) {
|
|
24
|
-
const tone = exports.CALLOUT_TONES.includes(attrs.tone) ? attrs.tone : 'info';
|
|
25
|
-
const hue = { info: 'blue', success: 'green', warning: 'orange', danger: 'red' }[tone];
|
|
26
|
-
return { tone, icon: attrs.icon === null || attrs.icon === undefined ? { info: '💡', success: '✅', warning: '⚠️', danger: '❗' }[tone] :
|
|
27
|
-
['', ...exports.CALLOUT_ICONS].includes(attrs.icon) ? attrs.icon : '💡',
|
|
28
|
-
textColor: exports.CALLOUT_COLORS.includes(attrs.textColor) ? attrs.textColor : null,
|
|
29
|
-
borderColor: ['none', ...exports.CALLOUT_COLORS].includes(attrs.borderColor) ? attrs.borderColor : hue,
|
|
30
|
-
backgroundColor: ['none', ...exports.CALLOUT_FILLS].includes(attrs.backgroundColor) ? attrs.backgroundColor : hue };
|
|
31
|
-
}
|
|
32
|
-
function calloutDOMAttributes(attrs = {}) {
|
|
33
|
-
const value = effectiveCallout(attrs);
|
|
34
|
-
return { 'data-callout': 'true', 'data-tone': value.tone, 'data-callout-icon': attrs.icon ?? 'default',
|
|
35
|
-
...Object.fromEntries(['textColor', 'borderColor', 'backgroundColor'].filter(key => attrs[key] != null)
|
|
36
|
-
.map(key => [`data-callout-${key.toLowerCase()}`, String(attrs[key])])),
|
|
37
|
-
...(value.icon === '' ? { 'data-icon-hidden': 'true' } : {}),
|
|
38
|
-
style: [`--callout-border:${value.borderColor === 'none' ? 'transparent' : `var(--callout-border-${value.borderColor})`}`,
|
|
39
|
-
`--callout-fill:${value.backgroundColor === 'none' ? 'transparent' : `var(--doc-highlight-${value.backgroundColor === 'gray' ? 'gray-soft' : value.backgroundColor})`}`,
|
|
40
|
-
`--callout-text:${value.textColor ? `var(--doc-text-${value.textColor})` : 'var(--content-text-color, var(--color-text))'}`].join(';') };
|
|
41
|
-
}
|
|
42
|
-
/** Optional Markdown metadata never contains free CSS or HTML. */
|
|
43
|
-
function calloutMetadata(attrs) {
|
|
44
|
-
if (!validCalloutAttrs(attrs))
|
|
45
|
-
return '';
|
|
46
|
-
const extra = Object.fromEntries(['icon', 'textColor', 'borderColor', 'backgroundColor']
|
|
47
|
-
.filter(key => attrs[key] !== undefined && attrs[key] !== null)
|
|
48
|
-
.map(key => [key, attrs[key]]));
|
|
49
|
-
return Object.keys(extra).length ? ` <!--ywiki-callout:${encodeURIComponent(JSON.stringify(extra))}-->` : '';
|
|
50
|
-
}
|
|
51
|
-
function readCalloutMetadata(text) {
|
|
52
|
-
const match = /^\s*<!--ywiki-callout:([^\s<>]{1,4096})-->\s*/.exec(text);
|
|
53
|
-
if (!match)
|
|
54
|
-
return null;
|
|
55
|
-
try {
|
|
56
|
-
const attrs = JSON.parse(decodeURIComponent(match[1]));
|
|
57
|
-
if (!validCalloutAttrs(attrs) || Object.keys(attrs).some(k => !['icon', 'textColor', 'borderColor', 'backgroundColor'].includes(k)))
|
|
58
|
-
return null;
|
|
59
|
-
return { attrs, length: match[0].length };
|
|
60
|
-
}
|
|
61
|
-
catch {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
1
|
+
"use strict";function calloutColorToken(o,r){return"textColor"===o?`--doc-text-${r}`:"borderColor"===o?`--callout-border-${r}`:`--doc-highlight-${"gray"===r?"gray-soft":r}`}function validCalloutAttrs(o){if(!o||"object"!=typeof o||Array.isArray(o))return!1;const r=o,valid=(o,e)=>void 0===r[o]||null===r[o]||"string"==typeof r[o]&&e.includes(r[o]);return valid("tone",exports.CALLOUT_TONES)&&valid("icon",["",...exports.CALLOUT_ICONS])&&valid("textColor",exports.CALLOUT_COLORS)&&valid("borderColor",["none",...exports.CALLOUT_COLORS])&&valid("backgroundColor",["none",...exports.CALLOUT_FILLS])}function effectiveCallout(o={}){const r=exports.CALLOUT_TONES.includes(o.tone)?o.tone:"info",e={info:"blue",success:"green",warning:"orange",danger:"red"}[r];return{tone:r,icon:null===o.icon||void 0===o.icon?{info:"💡",success:"✅",warning:"⚠️",danger:"❗"}[r]:["",...exports.CALLOUT_ICONS].includes(o.icon)?o.icon:"💡",textColor:exports.CALLOUT_COLORS.includes(o.textColor)?o.textColor:null,borderColor:["none",...exports.CALLOUT_COLORS].includes(o.borderColor)?o.borderColor:e,backgroundColor:["none",...exports.CALLOUT_FILLS].includes(o.backgroundColor)?o.backgroundColor:e}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.CALLOUT_SWATCH_FALLBACKS=exports.CALLOUT_FILLS=exports.CALLOUT_COLORS=exports.CALLOUT_ICONS=exports.CALLOUT_TONES=void 0,exports.calloutColorToken=calloutColorToken,exports.calloutSwatchStyle=function calloutSwatchStyle(o,r){if(null===r||"none"===r)return{};const e=exports.CALLOUT_SWATCH_FALLBACKS[o][r],t=e?`var(${calloutColorToken(o,r)}, ${e})`:`var(${calloutColorToken(o,r)})`;return"textColor"===o?{color:t}:{backgroundColor:t}},exports.validCalloutAttrs=validCalloutAttrs,exports.effectiveCallout=effectiveCallout,exports.calloutDOMAttributes=function calloutDOMAttributes(o={}){const r=effectiveCallout(o),token=(o,r)=>`var(${o}, ${r})`,e="none"===r.borderColor?"transparent":token(calloutColorToken("borderColor",r.borderColor),exports.CALLOUT_SWATCH_FALLBACKS.borderColor[r.borderColor]??"#9ac5ef"),t="none"===r.backgroundColor?"transparent":token(calloutColorToken("backgroundColor",r.backgroundColor),exports.CALLOUT_SWATCH_FALLBACKS.backgroundColor[r.backgroundColor]??"#d0ebff"),l=r.textColor?token(calloutColorToken("textColor",r.textColor),exports.CALLOUT_SWATCH_FALLBACKS.textColor[r.textColor]??"#1f2937"):"var(--content-text-color, var(--color-text))";return{"data-callout":"true","data-tone":r.tone,"data-callout-icon":o.icon??"default",...Object.fromEntries(["textColor","borderColor","backgroundColor"].filter(r=>null!=o[r]).map(r=>[`data-callout-${r.toLowerCase()}`,String(o[r])])),...""===r.icon?{"data-icon-hidden":"true"}:{},style:[`--callout-border:${e}`,`--callout-fill:${t}`,`--callout-text:${l}`].join(";")}},exports.calloutMetadata=function calloutMetadata(o){if(!validCalloutAttrs(o))return"";const r=Object.fromEntries(["icon","textColor","borderColor","backgroundColor"].filter(r=>void 0!==o[r]&&null!==o[r]).map(r=>[r,o[r]]));return Object.keys(r).length?` \x3c!--ywiki-callout:${encodeURIComponent(JSON.stringify(r))}--\x3e`:""},exports.readCalloutMetadata=function readCalloutMetadata(o){const r=/^\s*<!--ywiki-callout:([^\s<>]{1,4096})-->\s*/.exec(o);if(!r)return null;try{const o=JSON.parse(decodeURIComponent(r[1]));return!validCalloutAttrs(o)||Object.keys(o).some(o=>!["icon","textColor","borderColor","backgroundColor"].includes(o))?null:{attrs:o,length:r[0].length}}catch{return null}},exports.CALLOUT_TONES=["info","success","warning","danger"],exports.CALLOUT_ICONS=["💡","ℹ️","✅","⚠️","❗","📌","🎯","💬","📖","📝","🚀","🔔","🔎","⭐","🌅","🛠️","📅","🔒","❤️","🎉","❓","📎","🏁","🔥"],exports.CALLOUT_COLORS=["gray","red","orange","yellow","green","blue","purple"],exports.CALLOUT_FILLS=[...exports.CALLOUT_COLORS,...exports.CALLOUT_COLORS.map(o=>`${o}-strong`)],exports.CALLOUT_SWATCH_FALLBACKS={textColor:{gray:"#646a73",red:"#d92c2c",orange:"#b95d0b",yellow:"#8a6c0a",green:"#237b35",blue:"#1971c2",purple:"#7048e8"},borderColor:{gray:"#c7cbd1",red:"#f0a2a2",orange:"#ffc078",yellow:"#e3ca71",green:"#91d4a0",blue:"#9ac5ef",purple:"#c0a4ed"},backgroundColor:{gray:"#f1f3f5",red:"#ffe3e3",orange:"#fff0db",yellow:"#fff3bf",green:"#d3f9d8",blue:"#d0ebff",purple:"#e5dbff","gray-strong":"#ced4da","red-strong":"#ffc9c9","orange-strong":"#ffd8a8","yellow-strong":"#ffec99","green-strong":"#b2f2bb","blue-strong":"#a5d8ff","purple-strong":"#d0bfff"}};
|
|
@@ -1,33 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CODE_THEMES = void 0;
|
|
4
|
-
exports.codeBlockDisplay = codeBlockDisplay;
|
|
5
|
-
exports.rememberCodeTheme = rememberCodeTheme;
|
|
6
|
-
exports.codeLineCount = codeLineCount;
|
|
7
|
-
exports.codeLineNumbers = codeLineNumbers;
|
|
8
|
-
exports.codeBlockClass = codeBlockClass;
|
|
9
|
-
/** Presentation metadata only; code, whitespace and the document schema remain unchanged. */
|
|
10
|
-
exports.CODE_THEMES = [
|
|
11
|
-
{ value: 'auto', label: '跟随页面' },
|
|
12
|
-
{ value: 'paper', label: '纸白' },
|
|
13
|
-
{ value: 'soft', label: '柔和' },
|
|
14
|
-
{ value: 'night', label: '深色' },
|
|
15
|
-
];
|
|
16
|
-
function codeBlockDisplay() {
|
|
17
|
-
return { collapsed: false, lineNumbers: true, limited: true, theme: 'auto' };
|
|
18
|
-
}
|
|
19
|
-
function rememberCodeTheme(_theme) { }
|
|
20
|
-
function codeLineCount(text) {
|
|
21
|
-
let count = 1;
|
|
22
|
-
for (let i = 0; i < text.length; i++)
|
|
23
|
-
if (text[i] === '\n')
|
|
24
|
-
count++;
|
|
25
|
-
return count;
|
|
26
|
-
}
|
|
27
|
-
function codeLineNumbers(text) {
|
|
28
|
-
return Array.from({ length: codeLineCount(text) }, (_, i) => String(i + 1)).join('\n');
|
|
29
|
-
}
|
|
30
|
-
function codeBlockClass(display) {
|
|
31
|
-
return ['ywiki-code-panel', `code-theme-${display.theme}`, ...(display.collapsed ? ['is-collapsed'] : []),
|
|
32
|
-
...(display.lineNumbers ? [] : ['without-line-numbers']), ...(display.limited ? [] : ['is-unlimited'])];
|
|
33
|
-
}
|
|
1
|
+
"use strict";function codeLineCount(e){let o=1;for(let t=0;t<e.length;t++)"\n"===e[t]&&o++;return o}Object.defineProperty(exports,"__esModule",{value:!0}),exports.CODE_THEMES=void 0,exports.codeBlockDisplay=function codeBlockDisplay(){return{collapsed:!1,lineNumbers:!0,limited:!0,theme:"auto"}},exports.rememberCodeTheme=function rememberCodeTheme(e){},exports.codeLineCount=codeLineCount,exports.codeLineNumbers=function codeLineNumbers(e){return Array.from({length:codeLineCount(e)},(e,o)=>String(o+1)).join("\n")},exports.codeBlockClass=function codeBlockClass(e){return["ywiki-code-panel",`code-theme-${e.theme}`,...e.collapsed?["is-collapsed"]:[],...e.lineNumbers?[]:["without-line-numbers"],...e.limited?[]:["is-unlimited"]]},exports.CODE_THEMES=[{value:"auto",label:"跟随页面"},{value:"paper",label:"纸白"},{value:"soft",label:"柔和"},{value:"night",label:"深色"}];
|
|
@@ -1,51 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CODE_LANGUAGES = void 0;
|
|
4
|
-
exports.codeLanguageLabel = codeLanguageLabel;
|
|
5
|
-
exports.isKnownCodeLanguage = isKnownCodeLanguage;
|
|
6
|
-
/** 空字符串表示「纯文本 / 不指定」。 */
|
|
7
|
-
exports.CODE_LANGUAGES = [
|
|
8
|
-
{ value: '', label: '纯文本' },
|
|
9
|
-
{ value: 'bash', label: 'Bash / Shell' },
|
|
10
|
-
{ value: 'json', label: 'JSON' },
|
|
11
|
-
{ value: 'yaml', label: 'YAML' },
|
|
12
|
-
{ value: 'sql', label: 'SQL' },
|
|
13
|
-
{ value: 'markdown', label: 'Markdown' },
|
|
14
|
-
{ value: 'diff', label: 'Diff' },
|
|
15
|
-
{ value: 'javascript', label: 'JavaScript' },
|
|
16
|
-
{ value: 'typescript', label: 'TypeScript' },
|
|
17
|
-
{ value: 'jsx', label: 'JSX' },
|
|
18
|
-
{ value: 'tsx', label: 'TSX' },
|
|
19
|
-
{ value: 'python', label: 'Python' },
|
|
20
|
-
{ value: 'java', label: 'Java' },
|
|
21
|
-
{ value: 'go', label: 'Go' },
|
|
22
|
-
{ value: 'rust', label: 'Rust' },
|
|
23
|
-
{ value: 'c', label: 'C' },
|
|
24
|
-
{ value: 'cpp', label: 'C++' },
|
|
25
|
-
{ value: 'csharp', label: 'C#' },
|
|
26
|
-
{ value: 'php', label: 'PHP' },
|
|
27
|
-
{ value: 'ruby', label: 'Ruby' },
|
|
28
|
-
{ value: 'kotlin', label: 'Kotlin' },
|
|
29
|
-
{ value: 'swift', label: 'Swift' },
|
|
30
|
-
{ value: 'html', label: 'HTML' },
|
|
31
|
-
{ value: 'css', label: 'CSS' },
|
|
32
|
-
{ value: 'xml', label: 'XML' },
|
|
33
|
-
{ value: 'dockerfile', label: 'Dockerfile' },
|
|
34
|
-
{ value: 'ini', label: 'INI / TOML' },
|
|
35
|
-
];
|
|
36
|
-
const LABEL_BY_VALUE = new Map(exports.CODE_LANGUAGES.map((l) => [l.value, l.label]));
|
|
37
|
-
/**
|
|
38
|
-
* 取语言的展示标签。
|
|
39
|
-
*
|
|
40
|
-
* 未知语言(如用户从 Markdown 导入的少见围栏标记)直接显示原值——
|
|
41
|
-
* 不隐藏、不改写,避免"我明明标了语言却看不到"。
|
|
42
|
-
*/
|
|
43
|
-
function codeLanguageLabel(value) {
|
|
44
|
-
if (!value)
|
|
45
|
-
return '';
|
|
46
|
-
return LABEL_BY_VALUE.get(value) ?? value;
|
|
47
|
-
}
|
|
48
|
-
/** 是否为目录内已知语言(用于选择器回显:未知值时追加一个临时选项)。 */
|
|
49
|
-
function isKnownCodeLanguage(value) {
|
|
50
|
-
return LABEL_BY_VALUE.has(value);
|
|
51
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.CODE_LANGUAGES=void 0,exports.codeLanguageLabel=function codeLanguageLabel(e){return e?l.get(e)??e:""},exports.isKnownCodeLanguage=function isKnownCodeLanguage(e){return l.has(e)},exports.CODE_LANGUAGES=[{value:"",label:"纯文本"},{value:"bash",label:"Bash / Shell"},{value:"json",label:"JSON"},{value:"yaml",label:"YAML"},{value:"sql",label:"SQL"},{value:"markdown",label:"Markdown"},{value:"diff",label:"Diff"},{value:"javascript",label:"JavaScript"},{value:"typescript",label:"TypeScript"},{value:"jsx",label:"JSX"},{value:"tsx",label:"TSX"},{value:"python",label:"Python"},{value:"java",label:"Java"},{value:"go",label:"Go"},{value:"rust",label:"Rust"},{value:"c",label:"C"},{value:"cpp",label:"C++"},{value:"csharp",label:"C#"},{value:"php",label:"PHP"},{value:"ruby",label:"Ruby"},{value:"kotlin",label:"Kotlin"},{value:"swift",label:"Swift"},{value:"html",label:"HTML"},{value:"css",label:"CSS"},{value:"xml",label:"XML"},{value:"dockerfile",label:"Dockerfile"},{value:"ini",label:"INI / TOML"}];const l=new Map(exports.CODE_LANGUAGES.map(l=>[l.value,l.label]));
|
|
@@ -1,23 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.supportsDocument = supportsDocument;
|
|
4
|
-
const node_catalog_js_1 = require("./node-catalog.js");
|
|
5
|
-
const schema_js_1 = require("../schema.js");
|
|
6
|
-
const mind_map_js_1 = require("./mind-map.js");
|
|
7
|
-
const callout_js_1 = require("./callout.js");
|
|
8
|
-
function supportsDocument(raw, version = 1) {
|
|
9
|
-
if (version > schema_js_1.SCHEMA_VERSION)
|
|
10
|
-
return false;
|
|
11
|
-
if (!raw)
|
|
12
|
-
return true;
|
|
13
|
-
if (typeof raw !== 'object')
|
|
14
|
-
return false;
|
|
15
|
-
const doc = raw;
|
|
16
|
-
if (!doc.type || !(0, node_catalog_js_1.nodeMeta)(doc.type))
|
|
17
|
-
return false;
|
|
18
|
-
if (doc.type === 'mindMap' && !(0, mind_map_js_1.readMindMap)(doc))
|
|
19
|
-
return false;
|
|
20
|
-
if (doc.type === 'callout' && !(0, callout_js_1.validCalloutAttrs)(doc.attrs ?? {}))
|
|
21
|
-
return false;
|
|
22
|
-
return !doc.content || Array.isArray(doc.content) && doc.content.every(node => supportsDocument(node));
|
|
23
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.supportsDocument=function supportsDocument(n,s=1){if(s>t.SCHEMA_VERSION)return!1;if(!n)return!0;if("object"!=typeof n)return!1;const u=n;return!(!u.type||!(0,e.nodeMeta)(u.type))&&!("mindMap"===u.type&&!(0,r.readMindMap)(u))&&!("callout"===u.type&&!(0,o.validCalloutAttrs)(u.attrs??{}))&&(!u.content||Array.isArray(u.content)&&u.content.every(e=>supportsDocument(e)))};const e=require("./node-catalog.js"),t=require("../schema.js"),r=require("./mind-map.js"),o=require("./callout.js");
|
|
@@ -1,52 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* 从 ProseMirror 文档提取用于锚点定位的块级纯文本。
|
|
4
|
-
*
|
|
5
|
-
* 与 anchor.ts 配合:锚点用「在扁平文本中的字符偏移」表达,
|
|
6
|
-
* 这里负责把文档结构摊平,并保留「块 → 字符区间」的映射,
|
|
7
|
-
* 以便把定位结果映射回具体的块(前端据此在对应块上加高亮)。
|
|
8
|
-
*
|
|
9
|
-
* 与后端 DocSchemaService.extractPlainText 保持一致的遍历顺序(先文本、后子节点),
|
|
10
|
-
* 否则同一段内容在提交锚点与解析锚点时会得到不同的字符偏移。
|
|
11
|
-
*/
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.extractBlockTexts = extractBlockTexts;
|
|
14
|
-
exports.plainTextOf = plainTextOf;
|
|
15
|
-
/** 提取顶层块(含嵌套块)的纯文本。列表会递归取出每一项。 */
|
|
16
|
-
function extractBlockTexts(doc) {
|
|
17
|
-
const blocks = [];
|
|
18
|
-
const walk = (node, topIndex) => {
|
|
19
|
-
// 块级容器(段落/标题/列表项/引用/代码块等)各自作为一个「块」
|
|
20
|
-
const isBlockContainer = [
|
|
21
|
-
'paragraph',
|
|
22
|
-
'heading',
|
|
23
|
-
'codeBlock',
|
|
24
|
-
'blockquote',
|
|
25
|
-
'listItem',
|
|
26
|
-
'taskItem',
|
|
27
|
-
'tableCell',
|
|
28
|
-
'tableHeader',
|
|
29
|
-
'mindMapTopic',
|
|
30
|
-
].includes(node.type ?? '');
|
|
31
|
-
if (isBlockContainer) {
|
|
32
|
-
blocks.push({ index: topIndex, text: plainTextOf(node) });
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
for (const child of node.content ?? [])
|
|
36
|
-
walk(child, topIndex);
|
|
37
|
-
};
|
|
38
|
-
(doc?.content ?? []).forEach((node, i) => walk(node, i));
|
|
39
|
-
return blocks.filter((b) => b.text.length > 0);
|
|
40
|
-
}
|
|
41
|
-
/** 取节点的全部文本(含后代)。 */
|
|
42
|
-
function plainTextOf(node) {
|
|
43
|
-
const buf = [];
|
|
44
|
-
const walk = (n) => {
|
|
45
|
-
if (typeof n.text === 'string')
|
|
46
|
-
buf.push(n.text);
|
|
47
|
-
for (const c of n.content ?? [])
|
|
48
|
-
walk(c);
|
|
49
|
-
};
|
|
50
|
-
walk(node);
|
|
51
|
-
return buf.join('');
|
|
52
|
-
}
|
|
1
|
+
"use strict";function plainTextOf(t){const e=[],walk=t=>{"string"==typeof t.text&&e.push(t.text);for(const e of t.content??[])walk(e)};return walk(t),e.join("")}Object.defineProperty(exports,"__esModule",{value:!0}),exports.extractBlockTexts=function extractBlockTexts(t){const e=[],walk=(t,n)=>{if(["paragraph","heading","codeBlock","blockquote","listItem","taskItem","tableCell","tableHeader","mindMapTopic"].includes(t.type??""))e.push({index:n,text:plainTextOf(t)});else for(const e of t.content??[])walk(e,n)};return(t?.content??[]).forEach((t,e)=>walk(t,e)),e.filter(t=>t.text.length>0)},exports.plainTextOf=plainTextOf;
|
|
@@ -1,61 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.HIGHLIGHT_COLORS = exports.TEXT_COLORS = void 0;
|
|
4
|
-
exports.paletteColor = paletteColor;
|
|
5
|
-
exports.documentColorAttributes = documentColorAttributes;
|
|
6
|
-
/**
|
|
7
|
-
* 文档文字与高亮的受限调色板。存储值保持原始 hex,显示色通过主题变量切换;
|
|
8
|
-
* 阅读路径复用此模块,不引入 Tiptap。历史色值均保留,复制时 data-color 可往返。
|
|
9
|
-
*/
|
|
10
|
-
exports.TEXT_COLORS = [
|
|
11
|
-
{ name: '默认', value: null, token: null },
|
|
12
|
-
{ name: '灰', value: '#868e96', token: 'gray' },
|
|
13
|
-
{ name: '红', value: '#d92c2c', token: 'red' },
|
|
14
|
-
{ name: '橙', value: '#e07b1a', token: 'orange' },
|
|
15
|
-
{ name: '黄褐', value: '#9a7b12', token: 'yellow' },
|
|
16
|
-
{ name: '绿', value: '#2f9e44', token: 'green' },
|
|
17
|
-
{ name: '蓝', value: '#1971c2', token: 'blue' },
|
|
18
|
-
{ name: '紫', value: '#7048e8', token: 'purple' },
|
|
19
|
-
];
|
|
20
|
-
exports.HIGHLIGHT_COLORS = [
|
|
21
|
-
{ name: '无', value: null, token: null },
|
|
22
|
-
{ name: '浅灰', value: '#f1f3f5', token: 'gray-soft' },
|
|
23
|
-
{ name: '浅红', value: '#ffe3e3', token: 'red' },
|
|
24
|
-
{ name: '浅橙', value: '#fff0db', token: 'orange' },
|
|
25
|
-
{ name: '浅黄', value: '#fff3bf', token: 'yellow' },
|
|
26
|
-
{ name: '浅绿', value: '#d3f9d8', token: 'green' },
|
|
27
|
-
{ name: '浅蓝', value: '#d0ebff', token: 'blue' },
|
|
28
|
-
{ name: '浅紫', value: '#e5dbff', token: 'purple' },
|
|
29
|
-
{ name: '灰', value: '#dee2e6', token: 'gray' },
|
|
30
|
-
{ name: '深灰', value: '#ced4da', token: 'gray-strong' },
|
|
31
|
-
{ name: '红', value: '#ffc9c9', token: 'red-strong' },
|
|
32
|
-
{ name: '橙', value: '#ffd8a8', token: 'orange-strong' },
|
|
33
|
-
{ name: '黄', value: '#ffec99', token: 'yellow-strong' },
|
|
34
|
-
{ name: '绿', value: '#b2f2bb', token: 'green-strong' },
|
|
35
|
-
{ name: '蓝', value: '#a5d8ff', token: 'blue-strong' },
|
|
36
|
-
{ name: '紫', value: '#d0bfff', token: 'purple-strong' },
|
|
37
|
-
];
|
|
38
|
-
function paletteColor(value, palette) {
|
|
39
|
-
const hex = value.trim().toLowerCase();
|
|
40
|
-
const rgb = /^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/.exec(hex);
|
|
41
|
-
if (rgb && rgb.slice(1).some(channel => Number(channel) > 255))
|
|
42
|
-
return null;
|
|
43
|
-
const normalized = rgb
|
|
44
|
-
? `#${rgb.slice(1).map(channel => Number(channel).toString(16).padStart(2, '0')).join('')}`
|
|
45
|
-
: hex;
|
|
46
|
-
return palette.some(color => color.value === normalized) ? normalized : null;
|
|
47
|
-
}
|
|
48
|
-
function documentColorAttributes(kind, value) {
|
|
49
|
-
if (typeof value !== 'string')
|
|
50
|
-
return {};
|
|
51
|
-
const palette = kind === 'text' ? exports.TEXT_COLORS : exports.HIGHLIGHT_COLORS;
|
|
52
|
-
const normalized = paletteColor(value, palette);
|
|
53
|
-
const color = palette.find(item => item.value === normalized);
|
|
54
|
-
if (!color?.value)
|
|
55
|
-
return {};
|
|
56
|
-
const property = kind === 'text' ? 'color' : 'background-color';
|
|
57
|
-
return {
|
|
58
|
-
'data-color': color.value,
|
|
59
|
-
style: `${property}: var(--doc-${kind}-${color.token}, ${color.value})`,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
1
|
+
"use strict";function paletteColor(e,n){const t=e.trim().toLowerCase(),o=/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/.exec(t);if(o&&o.slice(1).some(e=>Number(e)>255))return null;const a=o?`#${o.slice(1).map(e=>Number(e).toString(16).padStart(2,"0")).join("")}`:t;return n.some(e=>e.value===a)?a:null}Object.defineProperty(exports,"__esModule",{value:!0}),exports.HIGHLIGHT_COLORS=exports.TEXT_COLORS=void 0,exports.paletteColor=paletteColor,exports.documentColorAttributes=function documentColorAttributes(e,n){if("string"!=typeof n)return{};const t="text"===e?exports.TEXT_COLORS:exports.HIGHLIGHT_COLORS,o=paletteColor(n,t),a=t.find(e=>e.value===o);if(!a?.value)return{};const l="text"===e?"color":"background-color";return{"data-color":a.value,style:`${l}: var(--doc-${e}-${a.token}, ${a.value})`}},exports.TEXT_COLORS=[{name:"默认",value:null,token:null},{name:"灰",value:"#868e96",token:"gray"},{name:"红",value:"#d92c2c",token:"red"},{name:"橙",value:"#e07b1a",token:"orange"},{name:"黄褐",value:"#9a7b12",token:"yellow"},{name:"绿",value:"#2f9e44",token:"green"},{name:"蓝",value:"#1971c2",token:"blue"},{name:"紫",value:"#7048e8",token:"purple"}],exports.HIGHLIGHT_COLORS=[{name:"无",value:null,token:null},{name:"浅灰",value:"#f1f3f5",token:"gray-soft"},{name:"浅红",value:"#ffe3e3",token:"red"},{name:"浅橙",value:"#fff0db",token:"orange"},{name:"浅黄",value:"#fff3bf",token:"yellow"},{name:"浅绿",value:"#d3f9d8",token:"green"},{name:"浅蓝",value:"#d0ebff",token:"blue"},{name:"浅紫",value:"#e5dbff",token:"purple"},{name:"灰",value:"#dee2e6",token:"gray"},{name:"深灰",value:"#ced4da",token:"gray-strong"},{name:"红",value:"#ffc9c9",token:"red-strong"},{name:"橙",value:"#ffd8a8",token:"orange-strong"},{name:"黄",value:"#ffec99",token:"yellow-strong"},{name:"绿",value:"#b2f2bb",token:"green-strong"},{name:"蓝",value:"#a5d8ff",token:"blue-strong"},{name:"紫",value:"#d0bfff",token:"purple-strong"}];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.extractHeadings=function extractHeadings(e){const n=[];if(!e||!Array.isArray(e.content))return n;const walk=e=>{if("codeBlock"!==e.type){if("heading"===e.type){const r=Number(e.attrs?.level??1),o=plainTextOf(e).trim();return void(o&&n.push({level:t.has(r)?r:1,text:o,order:n.length}))}for(const t of e.content??[])walk(t)}};for(const t of e.content)walk(t);return n};const t=new Set([1,2,3,4,5,6]);function plainTextOf(t){if("string"==typeof t.text&&t.text)return t.text;let e="";for(const n of t.content??[])e+=plainTextOf(n);return e}
|
|
@@ -1,179 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildTextRuns = buildTextRuns;
|
|
4
|
-
exports.buildFlatText = buildFlatText;
|
|
5
|
-
exports.resolveInlineComments = resolveInlineComments;
|
|
6
|
-
exports.splitTextByMarks = splitTextByMarks;
|
|
7
|
-
const anchor_js_1 = require("./anchor.js");
|
|
8
|
-
const doc_text_js_1 = require("./doc-text.js");
|
|
9
|
-
function buildTextRuns(doc) {
|
|
10
|
-
const runs = [];
|
|
11
|
-
let offset = 0;
|
|
12
|
-
/** 上一次是否为"块级片段结尾",用于决定是否插入分隔符 */
|
|
13
|
-
const blockTexts = [];
|
|
14
|
-
const collect = (node, out) => {
|
|
15
|
-
if (typeof node.text === 'string') {
|
|
16
|
-
out.push(node);
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
for (const c of node.content ?? [])
|
|
20
|
-
collect(c, out);
|
|
21
|
-
};
|
|
22
|
-
// 与 anchor 的 flattenDocText 一致:以「顶层块」为单位,块间插入分隔符,
|
|
23
|
-
// 防止块尾与块首被误连成一个匹配。
|
|
24
|
-
for (const top of doc?.content ?? []) {
|
|
25
|
-
const textNodes = [];
|
|
26
|
-
collect(top, textNodes);
|
|
27
|
-
const blockText = textNodes.map((n) => n.text ?? '').join('');
|
|
28
|
-
if (blockText.length === 0)
|
|
29
|
-
continue;
|
|
30
|
-
blockTexts.push(blockText);
|
|
31
|
-
const base = blockTexts.length > 1 ? offset + 1 : offset; // +1 为块间分隔符
|
|
32
|
-
let inner = 0;
|
|
33
|
-
for (const n of textNodes) {
|
|
34
|
-
const t = n.text ?? '';
|
|
35
|
-
if (t.length === 0)
|
|
36
|
-
continue;
|
|
37
|
-
runs.push({
|
|
38
|
-
index: runs.length,
|
|
39
|
-
text: t,
|
|
40
|
-
flatStart: base + inner,
|
|
41
|
-
flatEnd: base + inner + t.length,
|
|
42
|
-
});
|
|
43
|
-
inner += t.length;
|
|
44
|
-
}
|
|
45
|
-
offset = base + inner;
|
|
46
|
-
}
|
|
47
|
-
return runs;
|
|
48
|
-
}
|
|
49
|
-
/** 文档的扁平文本(与 buildTextRuns 的偏移体系一致)。 */
|
|
50
|
-
function buildFlatText(doc) {
|
|
51
|
-
const blocks = (doc?.content ?? [])
|
|
52
|
-
.map((top) => (0, doc_text_js_1.plainTextOf)(top))
|
|
53
|
-
.filter((t) => t.length > 0);
|
|
54
|
-
return (0, anchor_js_1.flattenDocText)(blocks).text;
|
|
55
|
-
}
|
|
56
|
-
/** 仅有锚点的评论才参与定位(页级评论不属于行内)。 */
|
|
57
|
-
function resolveInlineComments(doc, comments) {
|
|
58
|
-
const runs = buildTextRuns(doc);
|
|
59
|
-
const flatText = buildFlatText(doc);
|
|
60
|
-
const marks = [];
|
|
61
|
-
const orphanCommentIds = [];
|
|
62
|
-
// 只处理顶层评论:回复共用顶层锚点,不单独定位
|
|
63
|
-
for (const c of comments) {
|
|
64
|
-
if (c.deleted || !c.anchor)
|
|
65
|
-
continue;
|
|
66
|
-
if (c.anchor.prefix?.startsWith('mind:')) {
|
|
67
|
-
let exists = false;
|
|
68
|
-
const walk = (node) => {
|
|
69
|
-
if (node.type === 'mindMap' && node.attrs?.id === c.anchor.prefix.slice(5)) {
|
|
70
|
-
exists = !!node.content?.some(t => t.type === 'mindMapTopic' && t.attrs?.id === c.anchor.suffix);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
for (const child of node.content ?? [])
|
|
74
|
-
walk(child);
|
|
75
|
-
};
|
|
76
|
-
if (doc)
|
|
77
|
-
walk(doc);
|
|
78
|
-
if (!exists)
|
|
79
|
-
orphanCommentIds.push(c.id);
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
if (c.parentId !== null)
|
|
83
|
-
continue;
|
|
84
|
-
const resolved = (0, anchor_js_1.resolveAnchor)(flatText, {
|
|
85
|
-
quote: c.anchor.quote,
|
|
86
|
-
prefix: c.anchor.prefix,
|
|
87
|
-
suffix: c.anchor.suffix,
|
|
88
|
-
start: c.anchor.start,
|
|
89
|
-
});
|
|
90
|
-
if (!resolved) {
|
|
91
|
-
orphanCommentIds.push(c.id);
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* 把扁平区间映射到「文本节点 + 节点内偏移」。
|
|
96
|
-
*
|
|
97
|
-
* 锚点可能跨越多个文本节点(例如引用跨越两个段落、或跨过一个行内原子
|
|
98
|
-
* 节点如 `[[页面引用]]`)。**每个被覆盖的文本节点都要产出一条 mark**,
|
|
99
|
-
* 否则高亮会在第一个节点末尾断掉——表现为「引用了两段,只有第一段有
|
|
100
|
-
* 底色」,用户会以为评论只针对半句话。
|
|
101
|
-
*
|
|
102
|
-
* 这里不再"跨节点时只取首个",而是逐节点裁剪区间:
|
|
103
|
-
* 节点内起点 = max(0, 锚点起点 - 该节点扁平起点)
|
|
104
|
-
* 节点内终点 = min(节点长度, 锚点终点 - 该节点扁平起点)
|
|
105
|
-
*/
|
|
106
|
-
const targets = runs.filter((r) => r.flatEnd > resolved.from && r.flatStart <= resolved.to);
|
|
107
|
-
if (targets.length === 0) {
|
|
108
|
-
orphanCommentIds.push(c.id);
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* 零宽落点(shifted):原文已被改动、仅靠上下文降级定位。
|
|
113
|
-
* `resolveAnchor` 用 from === to 表示这种状态,其语义是「在这一点的位置
|
|
114
|
-
* 插一个标记」而非覆盖一段文字,因此只在首个节点上产出一条零宽 mark。
|
|
115
|
-
* (不能用下面的逐节点裁剪——零宽区间会被 `to <= from` 全部过滤掉。)
|
|
116
|
-
*/
|
|
117
|
-
if (resolved.to <= resolved.from) {
|
|
118
|
-
const first = targets[0];
|
|
119
|
-
marks.push({
|
|
120
|
-
commentId: c.id,
|
|
121
|
-
textIndex: first.index,
|
|
122
|
-
from: Math.max(0, resolved.from - first.flatStart),
|
|
123
|
-
to: Math.max(0, resolved.from - first.flatStart),
|
|
124
|
-
state: 'shifted',
|
|
125
|
-
hasReplies: c.replies.length > 0,
|
|
126
|
-
});
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
const state = 'exact';
|
|
130
|
-
let produced = 0;
|
|
131
|
-
for (const run of targets) {
|
|
132
|
-
const from = Math.max(0, resolved.from - run.flatStart);
|
|
133
|
-
const to = Math.min(run.text.length, resolved.to - run.flatStart);
|
|
134
|
-
if (to <= from)
|
|
135
|
-
continue;
|
|
136
|
-
marks.push({
|
|
137
|
-
commentId: c.id,
|
|
138
|
-
textIndex: run.index,
|
|
139
|
-
from,
|
|
140
|
-
to,
|
|
141
|
-
state,
|
|
142
|
-
hasReplies: c.replies.length > 0,
|
|
143
|
-
});
|
|
144
|
-
produced += 1;
|
|
145
|
-
}
|
|
146
|
-
// 区间落在节点边界上、没有任何实际覆盖 → 视为失联(宁可提示,不误标)
|
|
147
|
-
if (produced === 0)
|
|
148
|
-
orphanCommentIds.push(c.id);
|
|
149
|
-
}
|
|
150
|
-
const byTextIndex = new Map();
|
|
151
|
-
for (const m of marks) {
|
|
152
|
-
const arr = byTextIndex.get(m.textIndex) ?? [];
|
|
153
|
-
arr.push(m);
|
|
154
|
-
byTextIndex.set(m.textIndex, arr);
|
|
155
|
-
}
|
|
156
|
-
return { marks, orphanCommentIds, byTextIndex };
|
|
157
|
-
}
|
|
158
|
-
function splitTextByMarks(text, marks) {
|
|
159
|
-
if (marks.length === 0 || text.length === 0) {
|
|
160
|
-
return [{ text, marks: [] }];
|
|
161
|
-
}
|
|
162
|
-
// 收集切分点
|
|
163
|
-
const points = new Set([0, text.length]);
|
|
164
|
-
for (const m of marks) {
|
|
165
|
-
points.add(Math.max(0, Math.min(m.from, text.length)));
|
|
166
|
-
points.add(Math.max(0, Math.min(m.to, text.length)));
|
|
167
|
-
}
|
|
168
|
-
const sorted = [...points].sort((a, b) => a - b);
|
|
169
|
-
const pieces = [];
|
|
170
|
-
for (let i = 0; i < sorted.length - 1; i += 1) {
|
|
171
|
-
const start = sorted[i];
|
|
172
|
-
const end = sorted[i + 1];
|
|
173
|
-
if (end <= start)
|
|
174
|
-
continue;
|
|
175
|
-
const covering = marks.filter((m) => m.from <= start && m.to >= end);
|
|
176
|
-
pieces.push({ text: text.slice(start, end), marks: covering });
|
|
177
|
-
}
|
|
178
|
-
return pieces.length > 0 ? pieces : [{ text, marks: [] }];
|
|
179
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.buildTextRuns=buildTextRuns,exports.buildFlatText=buildFlatText,exports.resolveInlineComments=function resolveInlineComments(e,n){const o=buildTextRuns(e),s=buildFlatText(e),r=[],i=[];for(const a of n){if(a.deleted||!a.anchor)continue;if(a.anchor.prefix?.startsWith("mind:")){let t=!1;const walk=e=>{if("mindMap"!==e.type||e.attrs?.id!==a.anchor.prefix.slice(5))for(const t of e.content??[])walk(t);else t=!!e.content?.some(t=>"mindMapTopic"===t.type&&t.attrs?.id===a.anchor.suffix)};e&&walk(e),t||i.push(a.id);continue}if(null!==a.parentId)continue;const n=(0,t.resolveAnchor)(s,{quote:a.anchor.quote,prefix:a.anchor.prefix,suffix:a.anchor.suffix,start:a.anchor.start});if(!n){i.push(a.id);continue}const l=o.filter(t=>t.flatEnd>n.from&&t.flatStart<=n.to);if(0===l.length){i.push(a.id);continue}if(n.to<=n.from){const t=l[0];r.push({commentId:a.id,textIndex:t.index,from:Math.max(0,n.from-t.flatStart),to:Math.max(0,n.from-t.flatStart),state:"shifted",hasReplies:a.replies.length>0});continue}const f="exact";let c=0;for(const t of l){const e=Math.max(0,n.from-t.flatStart),o=Math.min(t.text.length,n.to-t.flatStart);o<=e||(r.push({commentId:a.id,textIndex:t.index,from:e,to:o,state:f,hasReplies:a.replies.length>0}),c+=1)}0===c&&i.push(a.id)}const a=new Map;for(const t of r){const e=a.get(t.textIndex)??[];e.push(t),a.set(t.textIndex,e)}return{marks:r,orphanCommentIds:i,byTextIndex:a}},exports.splitTextByMarks=function splitTextByMarks(t,e){if(0===e.length||0===t.length)return[{text:t,marks:[]}];const n=new Set([0,t.length]);for(const o of e)n.add(Math.max(0,Math.min(o.from,t.length))),n.add(Math.max(0,Math.min(o.to,t.length)));const o=[...n].sort((t,e)=>t-e),s=[];for(let n=0;n<o.length-1;n+=1){const r=o[n],i=o[n+1];if(i<=r)continue;const a=e.filter(t=>t.from<=r&&t.to>=i);s.push({text:t.slice(r,i),marks:a})}return s.length>0?s:[{text:t,marks:[]}]};const t=require("./anchor.js"),e=require("./doc-text.js");function buildTextRuns(t){const e=[];let n=0;const o=[],collect=(t,e)=>{if("string"!=typeof t.text)for(const n of t.content??[])collect(n,e);else e.push(t)};for(const s of t?.content??[]){const t=[];collect(s,t);const r=t.map(t=>t.text??"").join("");if(0===r.length)continue;o.push(r);const i=o.length>1?n+1:n;let a=0;for(const n of t){const t=n.text??"";0!==t.length&&(e.push({index:e.length,text:t,flatStart:i+a,flatEnd:i+a+t.length}),a+=t.length)}n=i+a}return e}function buildFlatText(n){const o=(n?.content??[]).map(t=>(0,e.plainTextOf)(t)).filter(t=>t.length>0);return(0,t.flattenDocText)(o).text}
|
|
@@ -1,14 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.normalizeMindFolds = normalizeMindFolds;
|
|
4
|
-
exports.firstLevelMindFolds = firstLevelMindFolds;
|
|
5
|
-
const mind_map_js_1 = require("./mind-map.js");
|
|
6
|
-
/** Root/leaf/stale entries have no local fold affordance and must not hide a whole map. */
|
|
7
|
-
function normalizeMindFolds(model, ids) {
|
|
8
|
-
const tree = (0, mind_map_js_1.mindMapTree)(model), parents = new Set(tree.map(t => t.parentId)), known = new Set(tree.map(t => t.id));
|
|
9
|
-
return new Set([...ids].filter(id => id !== model.rootId && known.has(id) && parents.has(id)));
|
|
10
|
-
}
|
|
11
|
-
/** Keep every first-level branch visible, collapsing only those with descendants. */
|
|
12
|
-
function firstLevelMindFolds(model) {
|
|
13
|
-
return normalizeMindFolds(model, (0, mind_map_js_1.mindMapTree)(model).filter(t => t.parentId === model.rootId).map(t => t.id));
|
|
14
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.normalizeMindFolds=normalizeMindFolds,exports.firstLevelMindFolds=function firstLevelMindFolds(n){return normalizeMindFolds(n,(0,e.mindMapTree)(n).filter(e=>e.parentId===n.rootId).map(e=>e.id))};const e=require("./mind-map.js");function normalizeMindFolds(n,r){const i=(0,e.mindMapTree)(n),t=new Set(i.map(e=>e.parentId)),d=new Set(i.map(e=>e.id));return new Set([...r].filter(e=>e!==n.rootId&&d.has(e)&&t.has(e)))}
|