noteconnection 1.7.0 → 1.8.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 +674 -21
- package/README.md +242 -62
- package/dist/src/agent_workspace.contract.parity.test.js +475 -0
- package/dist/src/agent_workspace.frontend.test.js +9989 -0
- package/dist/src/agent_workspace.locale.contract.test.js +95 -0
- package/dist/src/agent_workspace.runtime.behavior.test.js +5072 -0
- package/dist/src/copy.assets.contract.test.js +130 -0
- package/dist/src/core/PathBridge.js +28 -3
- package/dist/src/export/WorkspaceExportBundle.js +1130 -0
- package/dist/src/export/WorkspaceExportBundle.test.js +1480 -0
- package/dist/src/export/index.js +18 -0
- package/dist/src/export/types.js +2 -0
- package/dist/src/fixrisk.issue.verifier.contract.test.js +3 -1
- package/dist/src/foundation.ann.runtime.contract.test.js +81 -0
- package/dist/src/foundation.release.evidence.contract.test.js +406 -0
- package/dist/src/foundation.sqlite.runtime.contract.test.js +82 -0
- package/dist/src/frontend/README.md +242 -62
- package/dist/src/frontend/agent_workspace.js +5353 -0
- package/dist/src/frontend/agent_workspace_runtime.js +4434 -0
- package/dist/src/frontend/analysis.js +31 -4
- package/dist/src/frontend/app.js +2178 -62
- package/dist/src/frontend/focus_mode_interactions.js +33 -0
- package/dist/src/frontend/godot_future_path_renderer.js +540 -0
- package/dist/src/frontend/godot_tree_interactions.js +178 -0
- package/dist/src/frontend/graph_state.mjs +105 -0
- package/dist/src/frontend/hosted_future_path_runtime.js +157 -0
- package/dist/src/frontend/i18n.mjs +186 -0
- package/dist/src/frontend/index.html +641 -266
- package/dist/src/frontend/layout_gpu.js +12 -4
- package/dist/src/frontend/locales/en.json +721 -5
- package/dist/src/frontend/locales/zh.json +721 -5
- package/dist/src/frontend/main.mjs +60 -0
- package/dist/src/frontend/markdown_runtime.js +827 -0
- package/dist/src/frontend/notemd.css +49 -0
- package/dist/src/frontend/notemd.html +7 -1
- package/dist/src/frontend/notemd.js +64 -0
- package/dist/src/frontend/path.html +107 -0
- package/dist/src/frontend/path_app.js +2108 -130
- package/dist/src/frontend/path_layout.mjs +143 -0
- package/dist/src/frontend/path_mermaid_utils.mjs +108 -0
- package/dist/src/frontend/path_modules_bridge.js +486 -0
- package/dist/src/frontend/path_state.mjs +118 -0
- package/dist/src/frontend/path_styles.css +146 -0
- package/dist/src/frontend/path_worker_bridge.mjs +85 -0
- package/dist/src/frontend/reader.js +393 -33
- package/dist/src/frontend/runtime_bridge.js +67 -54
- package/dist/src/frontend/runtime_bridge.mjs +279 -0
- package/dist/src/frontend/settings.js +130 -12
- package/dist/src/frontend/source_manager.js +190 -21
- package/dist/src/frontend/styles.css +2720 -72
- package/dist/src/frontend/workbench_state.mjs +101 -0
- package/dist/src/frontend/workspace_panes.js +10168 -0
- package/dist/src/frontend.locale.contract.test.js +62 -0
- package/dist/src/godot.sidecar.bootstrap.contract.test.js +244 -0
- package/dist/src/indexing/IndexLifecycle.js +195 -0
- package/dist/src/indexing/IndexLifecycle.test.js +49 -0
- package/dist/src/indexing/SegmentBuilder.js +64 -0
- package/dist/src/indexing/UnitBuilder.js +48 -0
- package/dist/src/indexing/types.js +2 -0
- package/dist/src/knowledge.api.contract.test.js +170 -0
- package/dist/src/learning/KnowledgeLearningPlatform.js +10386 -0
- package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +327 -0
- package/dist/src/learning/KnowledgeLearningPlatform.program-f.test.js +99 -0
- package/dist/src/learning/KnowledgeLearningPlatform.test.js +2971 -0
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +2974 -0
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +3928 -0
- package/dist/src/learning/answerReleaseReview.js +4319 -0
- package/dist/src/learning/answerReleaseReview.test.js +2888 -0
- package/dist/src/learning/api.js +2 -0
- package/dist/src/learning/conversationComposer.js +1480 -0
- package/dist/src/learning/conversationComposer.test.js +1817 -0
- package/dist/src/learning/domains/ConversationManager.js +53 -0
- package/dist/src/learning/domains/KnowledgeIngestor.js +238 -0
- package/dist/src/learning/domains/KnowledgeQuerier.js +187 -0
- package/dist/src/learning/domains/MasteryEngine.js +387 -0
- package/dist/src/learning/domains/MemoryPolicyManager.js +408 -0
- package/dist/src/learning/domains/QualityEvaluator.js +307 -0
- package/dist/src/learning/domains/TutorRouter.js +313 -0
- package/dist/src/learning/domains/index.js +33 -0
- package/dist/src/learning/domains/types.js +7 -0
- package/dist/src/learning/errors.js +29 -0
- package/dist/src/learning/evidenceContextAssembler.js +1176 -0
- package/dist/src/learning/evidenceContextAssembler.test.js +6332 -0
- package/dist/src/learning/graphContextAssembler.js +870 -0
- package/dist/src/learning/graphContextAssembler.test.js +1033 -0
- package/dist/src/learning/index.js +28 -0
- package/dist/src/learning/queryBackend.js +1898 -0
- package/dist/src/learning/queryBackend.test.js +955 -0
- package/dist/src/learning/ragContextPack.js +257 -0
- package/dist/src/learning/ragContextPack.test.js +160 -0
- package/dist/src/learning/ragPublicText.js +38 -0
- package/dist/src/learning/ragSufficiencyJudge.js +161 -0
- package/dist/src/learning/ragSufficiencyJudge.test.js +177 -0
- package/dist/src/learning/ragSufficiencyProviderJudge.js +227 -0
- package/dist/src/learning/ragSufficiencyProviderJudge.test.js +156 -0
- package/dist/src/learning/requestNormalization.js +198 -0
- package/dist/src/learning/runtimeCapability.js +4677 -0
- package/dist/src/learning/runtimeCapability.test.js +3635 -0
- package/dist/src/learning/store.js +1240 -0
- package/dist/src/learning/store.test.js +1126 -0
- package/dist/src/learning/tutorAdapter.js +2 -0
- package/dist/src/learning/types.js +2 -0
- package/dist/src/learning/vectorAccelerationAdapter.js +942 -0
- package/dist/src/learning/vectorAccelerationAdapter.test.js +382 -0
- package/dist/src/lfs.asset.policy.contract.test.js +153 -0
- package/dist/src/license.policy.contract.test.js +66 -0
- package/dist/src/memory/MemoryGovernance.js +74 -0
- package/dist/src/memory/MemoryGovernance.test.js +46 -0
- package/dist/src/memory/types.js +2 -0
- package/dist/src/mermaid.frontend.guard.contract.test.js +77 -0
- package/dist/src/middleware/auth.js +17 -0
- package/dist/src/middleware/body-parser.js +45 -0
- package/dist/src/middleware/cors.js +44 -0
- package/dist/src/middleware/index.js +21 -0
- package/dist/src/middleware/request-trace.js +96 -0
- package/dist/src/notemd/AppConfigToml.js +6 -4
- package/dist/src/notemd/MermaidProcessor.js +400 -50
- package/dist/src/notemd/NotemdService.js +498 -13
- package/dist/src/notemd/PromptManager.js +15 -0
- package/dist/src/notemd/cli/commands.js +357 -0
- package/dist/src/notemd/cli/dispatcher.js +225 -0
- package/dist/src/notemd/cli/index.js +169 -0
- package/dist/src/notemd/cli/parser.js +68 -0
- package/dist/src/notemd/cli/types.js +2 -0
- package/dist/src/notemd/constants.js +43 -0
- package/dist/src/notemd/diagram/diagramGenerationService.js +78 -0
- package/dist/src/notemd/diagram/diagramSpec.js +79 -0
- package/dist/src/notemd/diagram/diagramSpecResponseParser.js +131 -0
- package/dist/src/notemd/diagram/intent.js +95 -0
- package/dist/src/notemd/diagram/planner.js +71 -0
- package/dist/src/notemd/diagram/prompts/diagramSpecPrompt.js +42 -0
- package/dist/src/notemd/diagram/types.js +18 -0
- package/dist/src/notemd/index.js +26 -0
- package/dist/src/notemd/operations/capabilityManifest.js +23 -0
- package/dist/src/notemd/operations/cliContracts.js +17 -0
- package/dist/src/notemd/operations/configProfileCommands.js +85 -0
- package/dist/src/notemd/operations/registry.contract.test.js +95 -0
- package/dist/src/notemd/operations/registry.js +991 -0
- package/dist/src/notemd/operations/types.js +2 -0
- package/dist/src/notemd/providerDiagnostics.js +220 -0
- package/dist/src/notemd/providerProfiles.js +42 -0
- package/dist/src/notemd/providerTemplates.js +231 -0
- package/dist/src/notemd/search/DuckDuckGoProvider.js +39 -0
- package/dist/src/notemd/search/SearchManager.js +13 -0
- package/dist/src/notemd/search/SearchProvider.js +2 -0
- package/dist/src/notemd/search/TavilyProvider.js +44 -0
- package/dist/src/notemd.agent.manifest.test.js +85 -0
- package/dist/src/notemd.api.contract.test.js +14 -1
- package/dist/src/notemd.app_config_toml.test.js +2 -1
- package/dist/src/notemd.batch.workflow.test.js +117 -0
- package/dist/src/notemd.cli.e2e.test.js +136 -0
- package/dist/src/notemd.core.test.js +51 -0
- package/dist/src/notemd.diagram.pipeline.test.js +233 -0
- package/dist/src/notemd.providerTemplates.test.js +34 -0
- package/dist/src/notemd.server.integration.test.js +143 -35
- package/dist/src/notemd.workflow.pipeline.test.js +162 -0
- package/dist/src/pathbridge.handshake.contract.test.js +16 -2
- package/dist/src/pathmode.background.contract.test.js +69 -0
- package/dist/src/pathmode.settings.api.contract.test.js +9 -0
- package/dist/src/pkg.sidecar.contract.test.js +9 -3
- package/dist/src/platform/ExportProfile.js +58 -0
- package/dist/src/platform/PlatformCapabilities.js +45 -0
- package/dist/src/platform/PlatformCapabilities.test.js +30 -0
- package/dist/src/platform/RenderMaterializer.js +33 -0
- package/dist/src/platform/RenderMaterializer.test.js +32 -0
- package/dist/src/query_backend.external_http.integration.test.js +410 -0
- package/dist/src/reader_renderer.js +404 -3
- package/dist/src/reader_renderer.test.js +87 -0
- package/dist/src/release.godot.mirror.contract.test.js +73 -0
- package/dist/src/resources/ResourceRegistry.js +223 -0
- package/dist/src/resources/ResourceRegistry.test.js +61 -0
- package/dist/src/resources/types.js +2 -0
- package/dist/src/routes/agentWorkspaceDiagnostics.js +173 -0
- package/dist/src/routes/data.js +267 -0
- package/dist/src/routes/diagnostics.js +51 -0
- package/dist/src/routes/index.js +23 -0
- package/dist/src/routes/knowledge.js +968 -0
- package/dist/src/routes/markdown.js +287 -0
- package/dist/src/routes/notemd.js +565 -0
- package/dist/src/routes/registry.contract.test.js +130 -0
- package/dist/src/routes/render.js +285 -0
- package/dist/src/routes/runtimeRunbookRouteOps.js +149 -0
- package/dist/src/routes/runtimeRunbookRouteOps.test.js +194 -0
- package/dist/src/routes/settings.js +6 -0
- package/dist/src/routes/staticFiles.js +94 -0
- package/dist/src/routes/types.js +2 -0
- package/dist/src/runtime.transport.adapter.contract.test.js +81 -0
- package/dist/src/server.js +11090 -1549
- package/dist/src/server.migration.test.js +193 -21
- package/dist/src/server.port.fallback.contract.test.js +63 -0
- package/dist/src/session/SessionStateStore.js +81 -0
- package/dist/src/session/SessionStateStore.test.js +58 -0
- package/dist/src/session/types.js +2 -0
- package/dist/src/settings.runtime.contract.test.js +50 -0
- package/dist/src/shared/types.contract.test.js +107 -0
- package/dist/src/shared/types.js +22 -0
- package/dist/src/sidecar.replacement.boundary.contract.test.js +128 -0
- package/dist/src/sidecar.supply.readiness.contract.test.js +144 -0
- package/dist/src/source_manager.loadflow.test.js +46 -0
- package/dist/src/startup.layout.snapshot.contract.test.js +57 -0
- package/dist/src/tauri.frontend.build.contract.test.js +60 -0
- package/dist/src/tauri.sidecar.cleanup.contract.test.js +21 -0
- package/dist/src/utils/RuntimePaths.js +4 -13
- package/dist/src/utils/platform.js +153 -0
- package/dist/src/workflows/WorkflowArtifactStore.js +96 -0
- package/dist/src/workflows/WorkflowArtifactStore.test.js +80 -0
- package/dist/src/workflows/types.js +2 -0
- package/dist/src/workspace/WorkspaceRegistry.js +122 -0
- package/dist/src/workspace/WorkspaceRegistry.test.js +29 -0
- package/dist/src/workspace/types.js +2 -0
- package/package.json +53 -10
|
@@ -3,36 +3,135 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.MermaidProcessor = void 0;
|
|
4
4
|
exports.fixMermaidSyntax = fixMermaidSyntax;
|
|
5
5
|
const MERMAID_BLOCK_PATTERN = /```mermaid\s*([\s\S]*?)```/gi;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
.replace(/\
|
|
10
|
-
.replace(
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
const TABLE_PLACEHOLDER_PREFIX = '___MERMAID_TABLE_LINE_';
|
|
7
|
+
function normalizeMermaidLineBreaks(source) {
|
|
8
|
+
return String(source || '')
|
|
9
|
+
.replace(/\r\n?/g, '\n')
|
|
10
|
+
.replace(/<br\s*>/gi, '<br/>');
|
|
11
|
+
}
|
|
12
|
+
function stripWrappingDoubleQuotes(text) {
|
|
13
|
+
const trimmed = String(text || '').trim();
|
|
14
|
+
if (trimmed.length >= 2 && trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
15
|
+
return trimmed.slice(1, -1);
|
|
16
|
+
}
|
|
17
|
+
return trimmed;
|
|
18
|
+
}
|
|
19
|
+
function escapeMermaidLabel(rawValue) {
|
|
20
|
+
return String(rawValue || '')
|
|
21
|
+
.replace(/\\/g, '\\\\')
|
|
22
|
+
.replace(/"/g, '\\"')
|
|
13
23
|
.trim();
|
|
14
24
|
}
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
function escapeMermaidQuotedNodeLabel(rawValue) {
|
|
26
|
+
return String(rawValue || '')
|
|
27
|
+
.replace(/\\/g, '\\\\')
|
|
28
|
+
.replace(/"/g, '#quot;')
|
|
29
|
+
.trim();
|
|
30
|
+
}
|
|
31
|
+
function normalizeMermaidQuotedNodeLabels(source) {
|
|
32
|
+
return String(source || '')
|
|
33
|
+
.split('\n')
|
|
34
|
+
.map((line) => {
|
|
35
|
+
const text = String(line || '');
|
|
36
|
+
const startPattern = /([A-Za-z_][A-Za-z0-9_]*)\["/g;
|
|
37
|
+
let result = '';
|
|
38
|
+
let cursor = 0;
|
|
39
|
+
let match;
|
|
40
|
+
while ((match = startPattern.exec(text)) !== null) {
|
|
41
|
+
const labelStart = match.index + match[0].length;
|
|
42
|
+
let labelEnd = -1;
|
|
43
|
+
for (let index = labelStart; index < text.length - 1; index += 1) {
|
|
44
|
+
if (text.charAt(index) === '"' && text.charAt(index - 1) !== '\\' && text.charAt(index + 1) === ']') {
|
|
45
|
+
labelEnd = index;
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (labelEnd < 0) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
result += text.slice(cursor, labelStart);
|
|
53
|
+
result += escapeMermaidQuotedNodeLabel(text.slice(labelStart, labelEnd));
|
|
54
|
+
result += '"]';
|
|
55
|
+
cursor = labelEnd + 2;
|
|
56
|
+
startPattern.lastIndex = cursor;
|
|
23
57
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
58
|
+
return result + text.slice(cursor);
|
|
59
|
+
})
|
|
60
|
+
.join('\n');
|
|
61
|
+
}
|
|
62
|
+
function protectTableLines(content) {
|
|
63
|
+
const protectedLines = [];
|
|
64
|
+
const tableSeparatorRegex = /^\s*\|(?:[\s\t]*:?[\s\t]*-+[\s\t]*:?[\s\t]*\|)+[\s\t]*$/;
|
|
65
|
+
const next = String(content || '')
|
|
66
|
+
.split('\n')
|
|
67
|
+
.map((line) => {
|
|
68
|
+
if (line.includes(':-- :') || tableSeparatorRegex.test(line)) {
|
|
69
|
+
const placeholder = `${TABLE_PLACEHOLDER_PREFIX}${protectedLines.length}___`;
|
|
70
|
+
protectedLines.push(line);
|
|
71
|
+
return placeholder;
|
|
72
|
+
}
|
|
73
|
+
return line;
|
|
74
|
+
})
|
|
75
|
+
.join('\n');
|
|
76
|
+
return { next, protectedLines };
|
|
77
|
+
}
|
|
78
|
+
function restoreTableLines(content, protectedLines) {
|
|
79
|
+
return protectedLines.reduce((restored, line, index) => {
|
|
80
|
+
const placeholder = `${TABLE_PLACEHOLDER_PREFIX}${index}___`;
|
|
81
|
+
return restored.split(placeholder).join(line);
|
|
82
|
+
}, content);
|
|
83
|
+
}
|
|
84
|
+
function splitTopLevelStatements(source) {
|
|
85
|
+
const text = normalizeMermaidLineBreaks(source)
|
|
86
|
+
.split('\n')
|
|
87
|
+
.map((line) => rewriteQuotedLabelAfterSemicolonLine(line) || line)
|
|
88
|
+
.join('\n');
|
|
89
|
+
let result = '';
|
|
90
|
+
let quote = false;
|
|
91
|
+
let squareDepth = 0;
|
|
92
|
+
let roundDepth = 0;
|
|
93
|
+
let curlyDepth = 0;
|
|
94
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
95
|
+
const char = text.charAt(index);
|
|
96
|
+
if (char === '"' && text.charAt(index - 1) !== '\\') {
|
|
97
|
+
quote = !quote;
|
|
98
|
+
result += char;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (!quote) {
|
|
102
|
+
if (char === '[')
|
|
103
|
+
squareDepth += 1;
|
|
104
|
+
else if (char === ']')
|
|
105
|
+
squareDepth = Math.max(0, squareDepth - 1);
|
|
106
|
+
else if (char === '(')
|
|
107
|
+
roundDepth += 1;
|
|
108
|
+
else if (char === ')')
|
|
109
|
+
roundDepth = Math.max(0, roundDepth - 1);
|
|
110
|
+
else if (char === '{')
|
|
111
|
+
curlyDepth += 1;
|
|
112
|
+
else if (char === '}')
|
|
113
|
+
curlyDepth = Math.max(0, curlyDepth - 1);
|
|
114
|
+
if (char === ';' && squareDepth === 0 && roundDepth === 0 && curlyDepth === 0) {
|
|
115
|
+
result += '\n';
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
result += char;
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
function rewriteSingleDoubleDashLabelLine(line) {
|
|
124
|
+
const match = line.match(/^(.*?)\s*(?<!-)--(?!>|-)\s*"([^"\n]+)"\s*(?<!-)--(?!>|-)\s*(.+?)\s*;?\s*$/);
|
|
125
|
+
if (!match) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
const start = String(match[1] || '').trim();
|
|
129
|
+
const label = String(match[2] || '').trim();
|
|
130
|
+
const end = String(match[3] || '').trim();
|
|
131
|
+
if (!start || !label || !end || /^"/.test(end)) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
return `${start} -- "${label}" --> ${end};`;
|
|
36
135
|
}
|
|
37
136
|
function normalizeSubgraphLine(line) {
|
|
38
137
|
const match = /^(\s*subgraph\s+)(.+)$/i.exec(line);
|
|
@@ -44,7 +143,6 @@ function normalizeSubgraphLine(line) {
|
|
|
44
143
|
if (!rawTitle || rawTitle.startsWith('"') || rawTitle.startsWith("'")) {
|
|
45
144
|
return { next: line, changed: false };
|
|
46
145
|
}
|
|
47
|
-
// Quote titles that contain spaces or punctuation to avoid Mermaid parse failures.
|
|
48
146
|
if (/[\s()[\]{}:;,-]/.test(rawTitle)) {
|
|
49
147
|
return {
|
|
50
148
|
next: `${prefix}"${rawTitle.replace(/"/g, '\\"')}"`,
|
|
@@ -53,40 +151,292 @@ function normalizeSubgraphLine(line) {
|
|
|
53
151
|
}
|
|
54
152
|
return { next: line, changed: false };
|
|
55
153
|
}
|
|
56
|
-
function
|
|
154
|
+
function rewriteQuotedLabelAfterSemicolonLine(line) {
|
|
155
|
+
if (!line.includes('-->')) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
const match = line.match(/^(.*?)\s*(-->)\s*(.*?);\s*"([^"\n]+)"\s*$/);
|
|
159
|
+
if (!match) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
const source = String(match[1] || '').trim();
|
|
163
|
+
const arrow = String(match[2] || '').trim();
|
|
164
|
+
const target = String(match[3] || '').trim();
|
|
165
|
+
const label = String(match[4] || '').trim();
|
|
166
|
+
if (!source || !target || !label) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
return `${source} -- "${label}" ${arrow} ${target};`;
|
|
170
|
+
}
|
|
171
|
+
function mergeDoubleArrowLabelLine(line) {
|
|
172
|
+
const match = line.match(/^(.*?)\s*--\s*"([^"\n]+)"\s*--\s*"([^"\n]+)"\s*(-->|---)\s*(.*)$/);
|
|
173
|
+
if (!match) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
const start = String(match[1] || '').trim();
|
|
177
|
+
const labelLeft = String(match[2] || '').trim();
|
|
178
|
+
const labelRight = String(match[3] || '').trim();
|
|
179
|
+
const arrow = String(match[4] || '').trim();
|
|
180
|
+
const end = String(match[5] || '').trim();
|
|
181
|
+
if (!start || !labelLeft || !labelRight || !end) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
return `${start} -- "${labelLeft}<br/>${labelRight}" ${arrow} ${end}`;
|
|
185
|
+
}
|
|
186
|
+
function quoteUnquotedEdgeLabelLine(line) {
|
|
187
|
+
const match = line.match(/^(.*?)\s*--\s*([^"\n][^>\n]*?)\s*-->\s*(.*)$/);
|
|
188
|
+
if (!match) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
const start = String(match[1] || '').trim();
|
|
192
|
+
const label = String(match[2] || '').trim();
|
|
193
|
+
const end = String(match[3] || '').trim();
|
|
194
|
+
if (!start || !label || !end) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(label) ||
|
|
198
|
+
/^[A-Za-z_][A-Za-z0-9_]*\s*[\[\(\{].*$/.test(label) ||
|
|
199
|
+
/^["[{(]/.test(label)) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
return `${start} -- "${label}" --> ${end}`;
|
|
203
|
+
}
|
|
204
|
+
function fixMalformedArrows(content) {
|
|
205
|
+
return String(content || '')
|
|
206
|
+
.replace(/[→⇒⟶⟹]/g, '-->')
|
|
207
|
+
.replace(/--\|>/g, '-->')
|
|
208
|
+
.replace(/<--/g, '-->')
|
|
209
|
+
.replace(/-- >/g, '-->');
|
|
210
|
+
}
|
|
211
|
+
function normalizeMermaidComments(content) {
|
|
212
|
+
return String(content || '')
|
|
213
|
+
.split('\n')
|
|
214
|
+
.map((line) => {
|
|
215
|
+
const hashCommentMatch = line.match(/^(\s*[A-Za-z0-9_()[\]{}"'\s.-]+?)\s*-->\s*([A-Za-z0-9_()[\]{}"'\s.-]+?)\s*;\s*#(.*)$/);
|
|
216
|
+
if (hashCommentMatch) {
|
|
217
|
+
return `${hashCommentMatch[1].trim()} -- "${hashCommentMatch[3].trim()}" --> ${hashCommentMatch[2].trim()};`;
|
|
218
|
+
}
|
|
219
|
+
const percentCommentMatch = line.match(/^(\s*[A-Za-z0-9_()[\]{}"'\s.-]+?)\s*-->\s*([A-Za-z0-9_()[\]{}"'\s.-]+?)\s*;\s*%(.*)$/);
|
|
220
|
+
if (percentCommentMatch) {
|
|
221
|
+
return `${percentCommentMatch[1].trim()} -- "${percentCommentMatch[3].trim()}" --> ${percentCommentMatch[2].trim()};`;
|
|
222
|
+
}
|
|
223
|
+
const slashCommentMatch = line.match(/^(\s*[A-Za-z0-9_()[\]{}"'\s.-]+?)\s*-->\s*([A-Za-z0-9_()[\]{}"'\s.-]+?)\s*;\s*\/\/(.*)$/);
|
|
224
|
+
if (slashCommentMatch) {
|
|
225
|
+
return `${slashCommentMatch[1].trim()} -- "${slashCommentMatch[3].trim()}" --> ${slashCommentMatch[2].trim()};`;
|
|
226
|
+
}
|
|
227
|
+
return line;
|
|
228
|
+
})
|
|
229
|
+
.join('\n');
|
|
230
|
+
}
|
|
231
|
+
function normalizeHtmlBreakBareNodeLabels(line) {
|
|
232
|
+
const text = String(line || '');
|
|
233
|
+
const arrowMatch = text.match(/^(.*?(?:-->|---|-\.->|\-.-))\s*([A-Za-z_][A-Za-z0-9_]*)\s+(.+?)\s*;?\s*$/);
|
|
234
|
+
if (!arrowMatch) {
|
|
235
|
+
return text;
|
|
236
|
+
}
|
|
237
|
+
const prefix = String(arrowMatch[1] || '');
|
|
238
|
+
const nodeId = String(arrowMatch[2] || '').trim();
|
|
239
|
+
const label = String(arrowMatch[3] || '').trim();
|
|
240
|
+
if (!nodeId || !label || !label.includes('<br/>')) {
|
|
241
|
+
return text;
|
|
242
|
+
}
|
|
243
|
+
if (/^[\[\(\{"]/.test(label)) {
|
|
244
|
+
return text;
|
|
245
|
+
}
|
|
246
|
+
if (/(?:-->|---|-\.->|\-.-)/.test(label)) {
|
|
247
|
+
return text;
|
|
248
|
+
}
|
|
249
|
+
return `${prefix} ${nodeId}["${escapeMermaidLabel(stripWrappingDoubleQuotes(label))}"]`;
|
|
250
|
+
}
|
|
251
|
+
function convertNoteLine(line, counters) {
|
|
252
|
+
const directionalMatch = line.match(/^\s*note\s+(?:right|left|top|bottom)\s+of\s+([A-Za-z0-9_]+)\s*:\s*(.+)$/i);
|
|
253
|
+
if (directionalMatch) {
|
|
254
|
+
const targetId = directionalMatch[1];
|
|
255
|
+
const noteId = `Note${targetId}`;
|
|
256
|
+
const noteText = escapeMermaidLabel(stripWrappingDoubleQuotes(directionalMatch[2]));
|
|
257
|
+
return [
|
|
258
|
+
`${noteId}["${noteText}"]`,
|
|
259
|
+
`${targetId} -.- ${noteId}`,
|
|
260
|
+
];
|
|
261
|
+
}
|
|
262
|
+
const targetedMatch = line.match(/^\s*note\s+([A-Za-z0-9_]+)\s+"(.+)"\s*;?\s*$/i);
|
|
263
|
+
if (targetedMatch) {
|
|
264
|
+
const targetId = targetedMatch[1];
|
|
265
|
+
const noteId = `Note${targetId}`;
|
|
266
|
+
const noteText = escapeMermaidLabel(stripWrappingDoubleQuotes(targetedMatch[2]));
|
|
267
|
+
return [
|
|
268
|
+
`${noteId}["${noteText}"]`,
|
|
269
|
+
`${targetId} -.- ${noteId}`,
|
|
270
|
+
];
|
|
271
|
+
}
|
|
272
|
+
const forOfMatch = line.match(/^\s*note\s+(?:for|of)\s+([A-Za-z0-9_]+)\s+(.+)$/i);
|
|
273
|
+
if (forOfMatch) {
|
|
274
|
+
const targetId = forOfMatch[1];
|
|
275
|
+
const noteId = `Note${targetId}`;
|
|
276
|
+
const noteText = escapeMermaidLabel(stripWrappingDoubleQuotes(forOfMatch[2].replace(/\]$/, '').trim()));
|
|
277
|
+
return [
|
|
278
|
+
`${noteId}["${noteText}"]`,
|
|
279
|
+
`${targetId} -.- ${noteId}`,
|
|
280
|
+
];
|
|
281
|
+
}
|
|
282
|
+
const standaloneMatch = line.match(/^\s*note\s*:\s*(.+)$/i);
|
|
283
|
+
if (standaloneMatch) {
|
|
284
|
+
counters.note += 1;
|
|
285
|
+
const noteId = `NoteStandalone${counters.note}`;
|
|
286
|
+
const noteText = escapeMermaidLabel(stripWrappingDoubleQuotes(standaloneMatch[1]));
|
|
287
|
+
return [`${noteId}["${noteText}"]`];
|
|
288
|
+
}
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
function splitIntermediateNodeLine(line) {
|
|
292
|
+
const match = line.match(/^(.*?)\s*(-->|---)\s*([A-Za-z_][A-Za-z0-9_]*)\s*(\[[^\]]+\]|\([^)]+\)|\{[^}]+\})\s*(-->|---)\s*(.*)$/);
|
|
293
|
+
if (!match) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
const start = String(match[1] || '').trim();
|
|
297
|
+
const leftArrow = String(match[2] || '').trim();
|
|
298
|
+
const nodeId = String(match[3] || '').trim();
|
|
299
|
+
const nodeShape = String(match[4] || '').trim();
|
|
300
|
+
const rightArrow = String(match[5] || '').trim();
|
|
301
|
+
const end = String(match[6] || '').trim();
|
|
302
|
+
if (!start || !nodeId || !nodeShape || !end) {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
return [
|
|
306
|
+
`${start} ${leftArrow} ${nodeId}${nodeShape}`,
|
|
307
|
+
`${nodeId} ${rightArrow} ${end}`,
|
|
308
|
+
];
|
|
309
|
+
}
|
|
310
|
+
function normalizeMermaidPipes(content) {
|
|
311
|
+
return String(content || '')
|
|
312
|
+
.replace(/\|""\|"/g, '')
|
|
313
|
+
.replace(/"\[\]"/g, '');
|
|
314
|
+
}
|
|
315
|
+
function fixExcessiveBrackets(content) {
|
|
316
|
+
return String(content || '')
|
|
317
|
+
.replace(/\]{3,}/g, ']')
|
|
318
|
+
.replace(/\[""\]/g, '')
|
|
319
|
+
.replace(/\["\]/g, ']')
|
|
320
|
+
.replace(/\[\/\["/g, '["')
|
|
321
|
+
.replace(/\["\/\]/g, '"]');
|
|
322
|
+
}
|
|
323
|
+
function fixDanglingBracketedNodeLabelLine(line) {
|
|
324
|
+
const match = line.match(/^(\s*[A-Za-z_][A-Za-z0-9_]*)\["([^"\n]*)\["\s*;?\s*$/);
|
|
325
|
+
if (!match) {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
const nodeId = String(match[1] || '').trim();
|
|
329
|
+
const label = String(match[2] || '').trim();
|
|
330
|
+
if (!nodeId || !label) {
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
return `${nodeId}["${escapeMermaidLabel(label)}"]`;
|
|
334
|
+
}
|
|
335
|
+
function applyDeepDebugMermaid(content) {
|
|
336
|
+
let next = normalizeMermaidPipes(content);
|
|
57
337
|
const fixes = [];
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
[
|
|
61
|
-
[
|
|
62
|
-
[
|
|
63
|
-
[/graph\s+([A-Z]{2})\s*;/g, 'graph $1', 'Removed semicolon after graph declaration.'],
|
|
64
|
-
[/;\s*$/gm, ';', 'Normalized trailing semicolon spacing.'],
|
|
338
|
+
const passes = [
|
|
339
|
+
['Normalized Mermaid line breaks.', normalizeMermaidLineBreaks],
|
|
340
|
+
['Normalized malformed arrows and Unicode arrows.', fixMalformedArrows],
|
|
341
|
+
['Converted Mermaid comments into explicit edge labels.', normalizeMermaidComments],
|
|
342
|
+
['Cleaned excessive Mermaid brackets and placeholder artifacts.', fixExcessiveBrackets],
|
|
65
343
|
];
|
|
66
|
-
|
|
67
|
-
const updated = next
|
|
344
|
+
passes.forEach(([description, apply]) => {
|
|
345
|
+
const updated = apply(next);
|
|
68
346
|
if (updated !== next) {
|
|
69
347
|
fixes.push(description);
|
|
70
348
|
next = updated;
|
|
71
349
|
}
|
|
72
350
|
});
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
351
|
+
const noteCounters = { note: 0 };
|
|
352
|
+
const nextLines = [];
|
|
353
|
+
next.split('\n').forEach((rawLine) => {
|
|
354
|
+
const subgraphNormalized = normalizeSubgraphLine(rawLine);
|
|
355
|
+
let line = subgraphNormalized.next;
|
|
356
|
+
if (subgraphNormalized.changed) {
|
|
78
357
|
fixes.push('Quoted subgraph title with special characters.');
|
|
79
358
|
}
|
|
359
|
+
const convertedNotes = convertNoteLine(line, noteCounters);
|
|
360
|
+
if (convertedNotes) {
|
|
361
|
+
nextLines.push(...convertedNotes);
|
|
362
|
+
fixes.push('Converted Mermaid note directives into linked note nodes.');
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
const rewrittenQuotedLabel = rewriteQuotedLabelAfterSemicolonLine(line);
|
|
366
|
+
if (rewrittenQuotedLabel && rewrittenQuotedLabel !== line) {
|
|
367
|
+
line = rewrittenQuotedLabel;
|
|
368
|
+
fixes.push('Re-attached quoted edge labels that were displaced after semicolons.');
|
|
369
|
+
}
|
|
370
|
+
const mergedDoubleLabel = mergeDoubleArrowLabelLine(line);
|
|
371
|
+
if (mergedDoubleLabel && mergedDoubleLabel !== line) {
|
|
372
|
+
line = mergedDoubleLabel;
|
|
373
|
+
fixes.push('Merged legacy double-label Mermaid edges.');
|
|
374
|
+
}
|
|
375
|
+
const rewrittenSingleDoubleDash = rewriteSingleDoubleDashLabelLine(line);
|
|
376
|
+
if (rewrittenSingleDoubleDash && rewrittenSingleDoubleDash !== line) {
|
|
377
|
+
line = rewrittenSingleDoubleDash;
|
|
378
|
+
fixes.push('Converted legacy double-dash Mermaid edges into standard arrows.');
|
|
379
|
+
}
|
|
380
|
+
const quotedUnquotedLabel = quoteUnquotedEdgeLabelLine(line);
|
|
381
|
+
if (quotedUnquotedLabel && quotedUnquotedLabel !== line) {
|
|
382
|
+
line = quotedUnquotedLabel;
|
|
383
|
+
fixes.push('Quoted unquoted Mermaid edge labels.');
|
|
384
|
+
}
|
|
385
|
+
const htmlBreakLabel = normalizeHtmlBreakBareNodeLabels(line);
|
|
386
|
+
if (htmlBreakLabel !== line) {
|
|
387
|
+
line = htmlBreakLabel;
|
|
388
|
+
fixes.push('Wrapped bare Mermaid node labels containing HTML line breaks.');
|
|
389
|
+
}
|
|
390
|
+
const danglingLabelFix = fixDanglingBracketedNodeLabelLine(line);
|
|
391
|
+
if (danglingLabelFix && danglingLabelFix !== line) {
|
|
392
|
+
line = danglingLabelFix;
|
|
393
|
+
fixes.push('Closed Mermaid node labels that had a dangling opening bracket inside quotes.');
|
|
394
|
+
}
|
|
395
|
+
const splitIntermediate = splitIntermediateNodeLine(line);
|
|
396
|
+
if (splitIntermediate) {
|
|
397
|
+
nextLines.push(...splitIntermediate);
|
|
398
|
+
fixes.push('Split Mermaid intermediate node edges into valid statements.');
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
nextLines.push(line);
|
|
402
|
+
});
|
|
403
|
+
next = nextLines
|
|
404
|
+
.join('\n')
|
|
405
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
406
|
+
.trimEnd();
|
|
407
|
+
return {
|
|
408
|
+
next,
|
|
409
|
+
fixes: Array.from(new Set(fixes)),
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
function fixMermaidBlock(blockSource) {
|
|
413
|
+
const fixes = [];
|
|
414
|
+
const protectedTables = protectTableLines(blockSource);
|
|
415
|
+
let next = normalizeMermaidQuotedNodeLabels(protectedTables.next);
|
|
416
|
+
if (next !== protectedTables.next) {
|
|
417
|
+
fixes.push('Escaped stray double quotes inside Mermaid node labels.');
|
|
80
418
|
}
|
|
81
|
-
next =
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
419
|
+
next = splitTopLevelStatements(next);
|
|
420
|
+
const deepDebug = applyDeepDebugMermaid(next);
|
|
421
|
+
next = deepDebug.next;
|
|
422
|
+
fixes.push(...deepDebug.fixes);
|
|
423
|
+
next = restoreTableLines(next, protectedTables.protectedLines);
|
|
424
|
+
// Cleanup final syntax trivia after all structural passes.
|
|
425
|
+
const cleanupPasses = [
|
|
426
|
+
[/\b(end);+\s*$/gim, 'end', 'Removed invalid trailing semicolons after end.'],
|
|
427
|
+
[/graph\s+([A-Z]{2})\s*;/g, 'graph $1', 'Removed semicolon after graph declaration.'],
|
|
428
|
+
[/\n{3,}/g, '\n\n', 'Collapsed excessive blank lines inside Mermaid blocks.'],
|
|
429
|
+
];
|
|
430
|
+
cleanupPasses.forEach(([pattern, replacement, description]) => {
|
|
431
|
+
const updated = next.replace(pattern, replacement);
|
|
432
|
+
if (updated !== next) {
|
|
433
|
+
next = updated;
|
|
434
|
+
fixes.push(description);
|
|
435
|
+
}
|
|
436
|
+
});
|
|
87
437
|
return {
|
|
88
438
|
block: next.trimEnd(),
|
|
89
|
-
fixes,
|
|
439
|
+
fixes: Array.from(new Set(fixes)),
|
|
90
440
|
};
|
|
91
441
|
}
|
|
92
442
|
class MermaidProcessor {
|