@probelabs/probe 0.6.0-rc115 → 0.6.0-rc117
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/build/agent/ProbeAgent.js +100 -10
- package/build/agent/index.js +3853 -306
- package/build/agent/probeTool.js +93 -18
- package/build/agent/schemaUtils.js +1 -1
- package/build/index.js +4 -0
- package/cjs/agent/ProbeAgent.cjs +3856 -309
- package/cjs/index.cjs +3601 -50
- package/package.json +2 -2
- package/src/agent/ProbeAgent.js +100 -10
- package/src/agent/probeTool.js +93 -18
- package/src/agent/schemaUtils.js +1 -1
- package/src/index.js +4 -0
package/cjs/agent/ProbeAgent.cjs
CHANGED
|
@@ -29807,6 +29807,268 @@ var init_simpleTelemetry = __esm({
|
|
|
29807
29807
|
}
|
|
29808
29808
|
});
|
|
29809
29809
|
|
|
29810
|
+
// src/agent/probeTool.js
|
|
29811
|
+
function isSessionCancelled(sessionId) {
|
|
29812
|
+
return activeToolExecutions.get(sessionId)?.cancelled || false;
|
|
29813
|
+
}
|
|
29814
|
+
function registerToolExecution(sessionId) {
|
|
29815
|
+
if (!sessionId) return;
|
|
29816
|
+
if (!activeToolExecutions.has(sessionId)) {
|
|
29817
|
+
activeToolExecutions.set(sessionId, { cancelled: false });
|
|
29818
|
+
} else {
|
|
29819
|
+
activeToolExecutions.get(sessionId).cancelled = false;
|
|
29820
|
+
}
|
|
29821
|
+
}
|
|
29822
|
+
function clearToolExecutionData(sessionId) {
|
|
29823
|
+
if (!sessionId) return;
|
|
29824
|
+
if (activeToolExecutions.has(sessionId)) {
|
|
29825
|
+
activeToolExecutions.delete(sessionId);
|
|
29826
|
+
if (process.env.DEBUG === "1") {
|
|
29827
|
+
console.log(`Cleared tool execution data for session: ${sessionId}`);
|
|
29828
|
+
}
|
|
29829
|
+
}
|
|
29830
|
+
}
|
|
29831
|
+
function createWrappedTools(baseTools) {
|
|
29832
|
+
const wrappedTools = {};
|
|
29833
|
+
if (baseTools.searchTool) {
|
|
29834
|
+
wrappedTools.searchToolInstance = wrapToolWithEmitter(
|
|
29835
|
+
baseTools.searchTool,
|
|
29836
|
+
"search",
|
|
29837
|
+
baseTools.searchTool.execute
|
|
29838
|
+
);
|
|
29839
|
+
}
|
|
29840
|
+
if (baseTools.queryTool) {
|
|
29841
|
+
wrappedTools.queryToolInstance = wrapToolWithEmitter(
|
|
29842
|
+
baseTools.queryTool,
|
|
29843
|
+
"query",
|
|
29844
|
+
baseTools.queryTool.execute
|
|
29845
|
+
);
|
|
29846
|
+
}
|
|
29847
|
+
if (baseTools.extractTool) {
|
|
29848
|
+
wrappedTools.extractToolInstance = wrapToolWithEmitter(
|
|
29849
|
+
baseTools.extractTool,
|
|
29850
|
+
"extract",
|
|
29851
|
+
baseTools.extractTool.execute
|
|
29852
|
+
);
|
|
29853
|
+
}
|
|
29854
|
+
if (baseTools.delegateTool) {
|
|
29855
|
+
wrappedTools.delegateToolInstance = wrapToolWithEmitter(
|
|
29856
|
+
baseTools.delegateTool,
|
|
29857
|
+
"delegate",
|
|
29858
|
+
baseTools.delegateTool.execute
|
|
29859
|
+
);
|
|
29860
|
+
}
|
|
29861
|
+
if (baseTools.bashTool) {
|
|
29862
|
+
wrappedTools.bashToolInstance = wrapToolWithEmitter(
|
|
29863
|
+
baseTools.bashTool,
|
|
29864
|
+
"bash",
|
|
29865
|
+
baseTools.bashTool.execute
|
|
29866
|
+
);
|
|
29867
|
+
}
|
|
29868
|
+
return wrappedTools;
|
|
29869
|
+
}
|
|
29870
|
+
var import_child_process8, import_util6, import_crypto3, import_events, import_fs4, import_fs5, import_path8, import_glob, toolCallEmitter, activeToolExecutions, wrapToolWithEmitter, listFilesTool, searchFilesTool, listFilesToolInstance, searchFilesToolInstance;
|
|
29871
|
+
var init_probeTool = __esm({
|
|
29872
|
+
"src/agent/probeTool.js"() {
|
|
29873
|
+
"use strict";
|
|
29874
|
+
init_index();
|
|
29875
|
+
import_child_process8 = require("child_process");
|
|
29876
|
+
import_util6 = require("util");
|
|
29877
|
+
import_crypto3 = require("crypto");
|
|
29878
|
+
import_events = require("events");
|
|
29879
|
+
import_fs4 = __toESM(require("fs"), 1);
|
|
29880
|
+
import_fs5 = require("fs");
|
|
29881
|
+
import_path8 = __toESM(require("path"), 1);
|
|
29882
|
+
import_glob = require("glob");
|
|
29883
|
+
toolCallEmitter = new import_events.EventEmitter();
|
|
29884
|
+
activeToolExecutions = /* @__PURE__ */ new Map();
|
|
29885
|
+
wrapToolWithEmitter = (tool3, toolName, baseExecute) => {
|
|
29886
|
+
return {
|
|
29887
|
+
...tool3,
|
|
29888
|
+
// Spread schema, description etc.
|
|
29889
|
+
execute: async (params) => {
|
|
29890
|
+
const debug = process.env.DEBUG === "1";
|
|
29891
|
+
const toolSessionId = params.sessionId || (0, import_crypto3.randomUUID)();
|
|
29892
|
+
if (debug) {
|
|
29893
|
+
console.log(`[DEBUG] probeTool: Executing ${toolName} for session ${toolSessionId}`);
|
|
29894
|
+
}
|
|
29895
|
+
registerToolExecution(toolSessionId);
|
|
29896
|
+
let executionError = null;
|
|
29897
|
+
let result = null;
|
|
29898
|
+
try {
|
|
29899
|
+
const toolCallStartData = {
|
|
29900
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29901
|
+
name: toolName,
|
|
29902
|
+
args: params,
|
|
29903
|
+
status: "started"
|
|
29904
|
+
};
|
|
29905
|
+
if (debug) {
|
|
29906
|
+
console.log(`[DEBUG] probeTool: Emitting toolCallStart:${toolSessionId}`);
|
|
29907
|
+
}
|
|
29908
|
+
toolCallEmitter.emit(`toolCall:${toolSessionId}`, toolCallStartData);
|
|
29909
|
+
if (isSessionCancelled(toolSessionId)) {
|
|
29910
|
+
if (debug) {
|
|
29911
|
+
console.log(`Tool execution cancelled before start for ${toolSessionId}`);
|
|
29912
|
+
}
|
|
29913
|
+
throw new Error(`Tool execution cancelled for session ${toolSessionId}`);
|
|
29914
|
+
}
|
|
29915
|
+
result = await baseExecute(params);
|
|
29916
|
+
if (isSessionCancelled(toolSessionId)) {
|
|
29917
|
+
if (debug) {
|
|
29918
|
+
console.log(`Tool execution cancelled after completion for ${toolSessionId}`);
|
|
29919
|
+
}
|
|
29920
|
+
throw new Error(`Tool execution cancelled for session ${toolSessionId}`);
|
|
29921
|
+
}
|
|
29922
|
+
} catch (error2) {
|
|
29923
|
+
executionError = error2;
|
|
29924
|
+
if (debug) {
|
|
29925
|
+
console.error(`[DEBUG] probeTool: Error in ${toolName}:`, error2);
|
|
29926
|
+
}
|
|
29927
|
+
}
|
|
29928
|
+
if (executionError) {
|
|
29929
|
+
const toolCallErrorData = {
|
|
29930
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29931
|
+
name: toolName,
|
|
29932
|
+
args: params,
|
|
29933
|
+
error: executionError.message || "Unknown error",
|
|
29934
|
+
status: "error"
|
|
29935
|
+
};
|
|
29936
|
+
if (debug) {
|
|
29937
|
+
console.log(`[DEBUG] probeTool: Emitting toolCall:${toolSessionId} (error)`);
|
|
29938
|
+
}
|
|
29939
|
+
toolCallEmitter.emit(`toolCall:${toolSessionId}`, toolCallErrorData);
|
|
29940
|
+
throw executionError;
|
|
29941
|
+
} else {
|
|
29942
|
+
if (isSessionCancelled(toolSessionId)) {
|
|
29943
|
+
if (process.env.DEBUG === "1") {
|
|
29944
|
+
console.log(`Tool execution finished but session was cancelled for ${toolSessionId}`);
|
|
29945
|
+
}
|
|
29946
|
+
throw new Error(`Tool execution cancelled for session ${toolSessionId}`);
|
|
29947
|
+
}
|
|
29948
|
+
const toolCallData = {
|
|
29949
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29950
|
+
name: toolName,
|
|
29951
|
+
args: params,
|
|
29952
|
+
// Safely preview result
|
|
29953
|
+
resultPreview: typeof result === "string" ? result.length > 200 ? result.substring(0, 200) + "..." : result : result ? JSON.stringify(result).substring(0, 200) + "..." : "No Result",
|
|
29954
|
+
status: "completed"
|
|
29955
|
+
};
|
|
29956
|
+
if (debug) {
|
|
29957
|
+
console.log(`[DEBUG] probeTool: Emitting toolCall:${toolSessionId} (completed)`);
|
|
29958
|
+
}
|
|
29959
|
+
toolCallEmitter.emit(`toolCall:${toolSessionId}`, toolCallData);
|
|
29960
|
+
return result;
|
|
29961
|
+
}
|
|
29962
|
+
}
|
|
29963
|
+
};
|
|
29964
|
+
};
|
|
29965
|
+
listFilesTool = {
|
|
29966
|
+
execute: async (params) => {
|
|
29967
|
+
const { directory = ".", workingDirectory } = params;
|
|
29968
|
+
const baseCwd = workingDirectory || process.cwd();
|
|
29969
|
+
const secureBaseDir = import_path8.default.resolve(baseCwd);
|
|
29970
|
+
const targetDir = import_path8.default.resolve(secureBaseDir, directory);
|
|
29971
|
+
if (!targetDir.startsWith(secureBaseDir + import_path8.default.sep) && targetDir !== secureBaseDir) {
|
|
29972
|
+
throw new Error("Path traversal attempt detected. Access denied.");
|
|
29973
|
+
}
|
|
29974
|
+
const debug = process.env.DEBUG === "1";
|
|
29975
|
+
if (debug) {
|
|
29976
|
+
console.log(`[DEBUG] Listing files in directory: ${targetDir}`);
|
|
29977
|
+
}
|
|
29978
|
+
try {
|
|
29979
|
+
const files = await import_fs5.promises.readdir(targetDir, { withFileTypes: true });
|
|
29980
|
+
const formatSize = (size) => {
|
|
29981
|
+
if (size < 1024) return `${size}B`;
|
|
29982
|
+
if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)}K`;
|
|
29983
|
+
if (size < 1024 * 1024 * 1024) return `${(size / (1024 * 1024)).toFixed(1)}M`;
|
|
29984
|
+
return `${(size / (1024 * 1024 * 1024)).toFixed(1)}G`;
|
|
29985
|
+
};
|
|
29986
|
+
const entries = await Promise.all(files.map(async (file) => {
|
|
29987
|
+
const isDirectory = file.isDirectory();
|
|
29988
|
+
const fullPath = import_path8.default.join(targetDir, file.name);
|
|
29989
|
+
let size = 0;
|
|
29990
|
+
try {
|
|
29991
|
+
const stats = await import_fs5.promises.stat(fullPath);
|
|
29992
|
+
size = stats.size;
|
|
29993
|
+
} catch (statError) {
|
|
29994
|
+
if (debug) {
|
|
29995
|
+
console.log(`[DEBUG] Could not stat file ${file.name}:`, statError.message);
|
|
29996
|
+
}
|
|
29997
|
+
}
|
|
29998
|
+
return {
|
|
29999
|
+
name: file.name,
|
|
30000
|
+
isDirectory,
|
|
30001
|
+
size
|
|
30002
|
+
};
|
|
30003
|
+
}));
|
|
30004
|
+
entries.sort((a3, b3) => {
|
|
30005
|
+
if (a3.isDirectory && !b3.isDirectory) return -1;
|
|
30006
|
+
if (!a3.isDirectory && b3.isDirectory) return 1;
|
|
30007
|
+
return a3.name.localeCompare(b3.name);
|
|
30008
|
+
});
|
|
30009
|
+
const formatted = entries.map((entry) => {
|
|
30010
|
+
const type = entry.isDirectory ? "dir " : "file";
|
|
30011
|
+
const sizeStr = formatSize(entry.size).padStart(8);
|
|
30012
|
+
return `${type} ${sizeStr} ${entry.name}`;
|
|
30013
|
+
});
|
|
30014
|
+
if (debug) {
|
|
30015
|
+
console.log(`[DEBUG] Found ${entries.length} files/directories in ${targetDir}`);
|
|
30016
|
+
}
|
|
30017
|
+
const header = `${targetDir}:
|
|
30018
|
+
`;
|
|
30019
|
+
const output = header + formatted.join("\n");
|
|
30020
|
+
return output;
|
|
30021
|
+
} catch (error2) {
|
|
30022
|
+
throw new Error(`Failed to list files: ${error2.message}`);
|
|
30023
|
+
}
|
|
30024
|
+
}
|
|
30025
|
+
};
|
|
30026
|
+
searchFilesTool = {
|
|
30027
|
+
execute: async (params) => {
|
|
30028
|
+
const { pattern, directory = ".", recursive = true, workingDirectory } = params;
|
|
30029
|
+
if (!pattern) {
|
|
30030
|
+
throw new Error("Pattern is required for file search");
|
|
30031
|
+
}
|
|
30032
|
+
const baseCwd = workingDirectory || process.cwd();
|
|
30033
|
+
const secureBaseDir = import_path8.default.resolve(baseCwd);
|
|
30034
|
+
const targetDir = import_path8.default.resolve(secureBaseDir, directory);
|
|
30035
|
+
if (!targetDir.startsWith(secureBaseDir + import_path8.default.sep) && targetDir !== secureBaseDir) {
|
|
30036
|
+
throw new Error("Path traversal attempt detected. Access denied.");
|
|
30037
|
+
}
|
|
30038
|
+
if (pattern.includes("**/**") || pattern.split("*").length > 10) {
|
|
30039
|
+
throw new Error("Pattern too complex. Please use a simpler glob pattern.");
|
|
30040
|
+
}
|
|
30041
|
+
try {
|
|
30042
|
+
const options = {
|
|
30043
|
+
cwd: targetDir,
|
|
30044
|
+
ignore: ["node_modules/**", ".git/**"],
|
|
30045
|
+
absolute: false
|
|
30046
|
+
};
|
|
30047
|
+
if (!recursive) {
|
|
30048
|
+
options.deep = 1;
|
|
30049
|
+
}
|
|
30050
|
+
const timeoutPromise = new Promise((_2, reject2) => {
|
|
30051
|
+
setTimeout(() => reject2(new Error("Search operation timed out after 10 seconds")), 1e4);
|
|
30052
|
+
});
|
|
30053
|
+
const files = await Promise.race([
|
|
30054
|
+
(0, import_glob.glob)(pattern, options),
|
|
30055
|
+
timeoutPromise
|
|
30056
|
+
]);
|
|
30057
|
+
const maxResults = 1e3;
|
|
30058
|
+
if (files.length > maxResults) {
|
|
30059
|
+
return files.slice(0, maxResults);
|
|
30060
|
+
}
|
|
30061
|
+
return files;
|
|
30062
|
+
} catch (error2) {
|
|
30063
|
+
throw new Error(`Failed to search files: ${error2.message}`);
|
|
30064
|
+
}
|
|
30065
|
+
}
|
|
30066
|
+
};
|
|
30067
|
+
listFilesToolInstance = wrapToolWithEmitter(listFilesTool, "listFiles", listFilesTool.execute);
|
|
30068
|
+
searchFilesToolInstance = wrapToolWithEmitter(searchFilesTool, "searchFiles", searchFilesTool.execute);
|
|
30069
|
+
}
|
|
30070
|
+
});
|
|
30071
|
+
|
|
29810
30072
|
// src/index.js
|
|
29811
30073
|
var init_index = __esm({
|
|
29812
30074
|
"src/index.js"() {
|
|
@@ -29824,6 +30086,7 @@ var init_index = __esm({
|
|
|
29824
30086
|
init_bash();
|
|
29825
30087
|
init_ProbeAgent();
|
|
29826
30088
|
init_simpleTelemetry();
|
|
30089
|
+
init_probeTool();
|
|
29827
30090
|
}
|
|
29828
30091
|
});
|
|
29829
30092
|
|
|
@@ -29946,12 +30209,12 @@ function parseXmlToolCallWithThinking(xmlString, validTools) {
|
|
|
29946
30209
|
}
|
|
29947
30210
|
return parseXmlToolCall(cleanedXmlString, validTools);
|
|
29948
30211
|
}
|
|
29949
|
-
var
|
|
30212
|
+
var import_crypto4, implementToolDefinition, listFilesToolDefinition, searchFilesToolDefinition;
|
|
29950
30213
|
var init_tools2 = __esm({
|
|
29951
30214
|
"src/agent/tools.js"() {
|
|
29952
30215
|
"use strict";
|
|
29953
30216
|
init_index();
|
|
29954
|
-
|
|
30217
|
+
import_crypto4 = require("crypto");
|
|
29955
30218
|
init_xmlParsingUtils();
|
|
29956
30219
|
implementToolDefinition = `
|
|
29957
30220
|
## implement
|
|
@@ -30030,216 +30293,6 @@ User: Find all markdown files in the docs directory, but only at the top level.
|
|
|
30030
30293
|
}
|
|
30031
30294
|
});
|
|
30032
30295
|
|
|
30033
|
-
// src/agent/probeTool.js
|
|
30034
|
-
function isSessionCancelled(sessionId) {
|
|
30035
|
-
return activeToolExecutions.get(sessionId)?.cancelled || false;
|
|
30036
|
-
}
|
|
30037
|
-
function registerToolExecution(sessionId) {
|
|
30038
|
-
if (!sessionId) return;
|
|
30039
|
-
if (!activeToolExecutions.has(sessionId)) {
|
|
30040
|
-
activeToolExecutions.set(sessionId, { cancelled: false });
|
|
30041
|
-
} else {
|
|
30042
|
-
activeToolExecutions.get(sessionId).cancelled = false;
|
|
30043
|
-
}
|
|
30044
|
-
}
|
|
30045
|
-
function clearToolExecutionData(sessionId) {
|
|
30046
|
-
if (!sessionId) return;
|
|
30047
|
-
if (activeToolExecutions.has(sessionId)) {
|
|
30048
|
-
activeToolExecutions.delete(sessionId);
|
|
30049
|
-
if (process.env.DEBUG === "1") {
|
|
30050
|
-
console.log(`Cleared tool execution data for session: ${sessionId}`);
|
|
30051
|
-
}
|
|
30052
|
-
}
|
|
30053
|
-
}
|
|
30054
|
-
function createWrappedTools(baseTools) {
|
|
30055
|
-
const wrappedTools = {};
|
|
30056
|
-
if (baseTools.searchTool) {
|
|
30057
|
-
wrappedTools.searchToolInstance = wrapToolWithEmitter(
|
|
30058
|
-
baseTools.searchTool,
|
|
30059
|
-
"search",
|
|
30060
|
-
baseTools.searchTool.execute
|
|
30061
|
-
);
|
|
30062
|
-
}
|
|
30063
|
-
if (baseTools.queryTool) {
|
|
30064
|
-
wrappedTools.queryToolInstance = wrapToolWithEmitter(
|
|
30065
|
-
baseTools.queryTool,
|
|
30066
|
-
"query",
|
|
30067
|
-
baseTools.queryTool.execute
|
|
30068
|
-
);
|
|
30069
|
-
}
|
|
30070
|
-
if (baseTools.extractTool) {
|
|
30071
|
-
wrappedTools.extractToolInstance = wrapToolWithEmitter(
|
|
30072
|
-
baseTools.extractTool,
|
|
30073
|
-
"extract",
|
|
30074
|
-
baseTools.extractTool.execute
|
|
30075
|
-
);
|
|
30076
|
-
}
|
|
30077
|
-
if (baseTools.delegateTool) {
|
|
30078
|
-
wrappedTools.delegateToolInstance = wrapToolWithEmitter(
|
|
30079
|
-
baseTools.delegateTool,
|
|
30080
|
-
"delegate",
|
|
30081
|
-
baseTools.delegateTool.execute
|
|
30082
|
-
);
|
|
30083
|
-
}
|
|
30084
|
-
if (baseTools.bashTool) {
|
|
30085
|
-
wrappedTools.bashToolInstance = wrapToolWithEmitter(
|
|
30086
|
-
baseTools.bashTool,
|
|
30087
|
-
"bash",
|
|
30088
|
-
baseTools.bashTool.execute
|
|
30089
|
-
);
|
|
30090
|
-
}
|
|
30091
|
-
return wrappedTools;
|
|
30092
|
-
}
|
|
30093
|
-
var import_child_process8, import_util6, import_crypto4, import_events, import_fs4, import_fs5, import_path8, import_glob, toolCallEmitter, activeToolExecutions, wrapToolWithEmitter, listFilesTool, searchFilesTool, listFilesToolInstance, searchFilesToolInstance;
|
|
30094
|
-
var init_probeTool = __esm({
|
|
30095
|
-
"src/agent/probeTool.js"() {
|
|
30096
|
-
"use strict";
|
|
30097
|
-
init_index();
|
|
30098
|
-
import_child_process8 = require("child_process");
|
|
30099
|
-
import_util6 = require("util");
|
|
30100
|
-
import_crypto4 = require("crypto");
|
|
30101
|
-
import_events = require("events");
|
|
30102
|
-
import_fs4 = __toESM(require("fs"), 1);
|
|
30103
|
-
import_fs5 = require("fs");
|
|
30104
|
-
import_path8 = __toESM(require("path"), 1);
|
|
30105
|
-
import_glob = require("glob");
|
|
30106
|
-
toolCallEmitter = new import_events.EventEmitter();
|
|
30107
|
-
activeToolExecutions = /* @__PURE__ */ new Map();
|
|
30108
|
-
wrapToolWithEmitter = (tool3, toolName, baseExecute) => {
|
|
30109
|
-
return {
|
|
30110
|
-
...tool3,
|
|
30111
|
-
// Spread schema, description etc.
|
|
30112
|
-
execute: async (params) => {
|
|
30113
|
-
const debug = process.env.DEBUG === "1";
|
|
30114
|
-
const toolSessionId = params.sessionId || (0, import_crypto4.randomUUID)();
|
|
30115
|
-
if (debug) {
|
|
30116
|
-
console.log(`[DEBUG] probeTool: Executing ${toolName} for session ${toolSessionId}`);
|
|
30117
|
-
}
|
|
30118
|
-
registerToolExecution(toolSessionId);
|
|
30119
|
-
let executionError = null;
|
|
30120
|
-
let result = null;
|
|
30121
|
-
try {
|
|
30122
|
-
const toolCallStartData = {
|
|
30123
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30124
|
-
name: toolName,
|
|
30125
|
-
args: params,
|
|
30126
|
-
status: "started"
|
|
30127
|
-
};
|
|
30128
|
-
if (debug) {
|
|
30129
|
-
console.log(`[DEBUG] probeTool: Emitting toolCallStart:${toolSessionId}`);
|
|
30130
|
-
}
|
|
30131
|
-
toolCallEmitter.emit(`toolCall:${toolSessionId}`, toolCallStartData);
|
|
30132
|
-
if (isSessionCancelled(toolSessionId)) {
|
|
30133
|
-
if (debug) {
|
|
30134
|
-
console.log(`Tool execution cancelled before start for ${toolSessionId}`);
|
|
30135
|
-
}
|
|
30136
|
-
throw new Error(`Tool execution cancelled for session ${toolSessionId}`);
|
|
30137
|
-
}
|
|
30138
|
-
result = await baseExecute(params);
|
|
30139
|
-
if (isSessionCancelled(toolSessionId)) {
|
|
30140
|
-
if (debug) {
|
|
30141
|
-
console.log(`Tool execution cancelled after completion for ${toolSessionId}`);
|
|
30142
|
-
}
|
|
30143
|
-
throw new Error(`Tool execution cancelled for session ${toolSessionId}`);
|
|
30144
|
-
}
|
|
30145
|
-
} catch (error2) {
|
|
30146
|
-
executionError = error2;
|
|
30147
|
-
if (debug) {
|
|
30148
|
-
console.error(`[DEBUG] probeTool: Error in ${toolName}:`, error2);
|
|
30149
|
-
}
|
|
30150
|
-
}
|
|
30151
|
-
if (executionError) {
|
|
30152
|
-
const toolCallErrorData = {
|
|
30153
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30154
|
-
name: toolName,
|
|
30155
|
-
args: params,
|
|
30156
|
-
error: executionError.message || "Unknown error",
|
|
30157
|
-
status: "error"
|
|
30158
|
-
};
|
|
30159
|
-
if (debug) {
|
|
30160
|
-
console.log(`[DEBUG] probeTool: Emitting toolCall:${toolSessionId} (error)`);
|
|
30161
|
-
}
|
|
30162
|
-
toolCallEmitter.emit(`toolCall:${toolSessionId}`, toolCallErrorData);
|
|
30163
|
-
throw executionError;
|
|
30164
|
-
} else {
|
|
30165
|
-
if (isSessionCancelled(toolSessionId)) {
|
|
30166
|
-
if (process.env.DEBUG === "1") {
|
|
30167
|
-
console.log(`Tool execution finished but session was cancelled for ${toolSessionId}`);
|
|
30168
|
-
}
|
|
30169
|
-
throw new Error(`Tool execution cancelled for session ${toolSessionId}`);
|
|
30170
|
-
}
|
|
30171
|
-
const toolCallData = {
|
|
30172
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30173
|
-
name: toolName,
|
|
30174
|
-
args: params,
|
|
30175
|
-
// Safely preview result
|
|
30176
|
-
resultPreview: typeof result === "string" ? result.length > 200 ? result.substring(0, 200) + "..." : result : result ? JSON.stringify(result).substring(0, 200) + "..." : "No Result",
|
|
30177
|
-
status: "completed"
|
|
30178
|
-
};
|
|
30179
|
-
if (debug) {
|
|
30180
|
-
console.log(`[DEBUG] probeTool: Emitting toolCall:${toolSessionId} (completed)`);
|
|
30181
|
-
}
|
|
30182
|
-
toolCallEmitter.emit(`toolCall:${toolSessionId}`, toolCallData);
|
|
30183
|
-
return result;
|
|
30184
|
-
}
|
|
30185
|
-
}
|
|
30186
|
-
};
|
|
30187
|
-
};
|
|
30188
|
-
listFilesTool = {
|
|
30189
|
-
execute: async (params) => {
|
|
30190
|
-
const { directory = ".", workingDirectory } = params;
|
|
30191
|
-
const baseCwd = workingDirectory || process.cwd();
|
|
30192
|
-
const secureBaseDir = import_path8.default.resolve(baseCwd);
|
|
30193
|
-
const targetDir = import_path8.default.resolve(secureBaseDir, directory);
|
|
30194
|
-
if (!targetDir.startsWith(secureBaseDir + import_path8.default.sep) && targetDir !== secureBaseDir) {
|
|
30195
|
-
throw new Error("Path traversal attempt detected. Access denied.");
|
|
30196
|
-
}
|
|
30197
|
-
try {
|
|
30198
|
-
const files = await listFilesByLevel({
|
|
30199
|
-
directory: targetDir,
|
|
30200
|
-
maxFiles: 100,
|
|
30201
|
-
respectGitignore: !process.env.PROBE_NO_GITIGNORE || process.env.PROBE_NO_GITIGNORE === "",
|
|
30202
|
-
cwd: secureBaseDir
|
|
30203
|
-
});
|
|
30204
|
-
return files;
|
|
30205
|
-
} catch (error2) {
|
|
30206
|
-
throw new Error(`Failed to list files: ${error2.message}`);
|
|
30207
|
-
}
|
|
30208
|
-
}
|
|
30209
|
-
};
|
|
30210
|
-
searchFilesTool = {
|
|
30211
|
-
execute: async (params) => {
|
|
30212
|
-
const { pattern, directory = ".", recursive = true, workingDirectory } = params;
|
|
30213
|
-
if (!pattern) {
|
|
30214
|
-
throw new Error("Pattern is required for file search");
|
|
30215
|
-
}
|
|
30216
|
-
const baseCwd = workingDirectory || process.cwd();
|
|
30217
|
-
const secureBaseDir = import_path8.default.resolve(baseCwd);
|
|
30218
|
-
const targetDir = import_path8.default.resolve(secureBaseDir, directory);
|
|
30219
|
-
if (!targetDir.startsWith(secureBaseDir + import_path8.default.sep) && targetDir !== secureBaseDir) {
|
|
30220
|
-
throw new Error("Path traversal attempt detected. Access denied.");
|
|
30221
|
-
}
|
|
30222
|
-
try {
|
|
30223
|
-
const options = {
|
|
30224
|
-
cwd: targetDir,
|
|
30225
|
-
ignore: ["node_modules/**", ".git/**"],
|
|
30226
|
-
absolute: false
|
|
30227
|
-
};
|
|
30228
|
-
if (!recursive) {
|
|
30229
|
-
options.deep = 1;
|
|
30230
|
-
}
|
|
30231
|
-
const files = await (0, import_glob.glob)(pattern, options);
|
|
30232
|
-
return files;
|
|
30233
|
-
} catch (error2) {
|
|
30234
|
-
throw new Error(`Failed to search files: ${error2.message}`);
|
|
30235
|
-
}
|
|
30236
|
-
}
|
|
30237
|
-
};
|
|
30238
|
-
listFilesToolInstance = wrapToolWithEmitter(listFilesTool, "listFiles", listFilesTool.execute);
|
|
30239
|
-
searchFilesToolInstance = wrapToolWithEmitter(searchFilesTool, "searchFiles", searchFilesTool.execute);
|
|
30240
|
-
}
|
|
30241
|
-
});
|
|
30242
|
-
|
|
30243
30296
|
// src/agent/mockProvider.js
|
|
30244
30297
|
function createMockProvider() {
|
|
30245
30298
|
return {
|
|
@@ -41546,13 +41599,14 @@ function tokenize(text) {
|
|
|
41546
41599
|
const lexResult = MermaidLexer.tokenize(text);
|
|
41547
41600
|
return lexResult;
|
|
41548
41601
|
}
|
|
41549
|
-
var Identifier, NumberLiteral, FlowchartKeyword, GraphKeyword, Direction, SubgraphKeyword, EndKeyword, ClassKeyword, StyleKeyword, ClassDefKeyword, Ampersand, Comma, Semicolon, Colon, TripleColon, BiDirectionalArrow, CircleEndLine, CrossEndLine, DottedArrowRight, DottedArrowLeft, ThickArrowRight, ThickArrowLeft, ArrowRight, ArrowLeft, DottedLine, ThickLine, Line, TwoDashes, InvalidArrow, DoubleSquareOpen, DoubleSquareClose, DoubleRoundOpen, DoubleRoundClose, HexagonOpen, HexagonClose, StadiumOpen, StadiumClose, CylinderOpen, CylinderClose, SquareOpen, SquareClose, RoundOpen, RoundClose, DiamondOpen, DiamondClose, AngleOpen, AngleLess, Pipe, QuotedString, MultilineText, Comment, ColorValue, Text, WhiteSpace, Newline, allTokens, MermaidLexer;
|
|
41602
|
+
var Identifier, NumberLiteral, FlowchartKeyword, GraphKeyword, Direction, SubgraphKeyword, EndKeyword, ClassKeyword, StyleKeyword, ClassDefKeyword, Ampersand, Comma, Semicolon, Colon, TripleColon, BiDirectionalArrow, CircleEndLine, CrossEndLine, DottedArrowRight, DottedArrowLeft, ThickArrowRight, ThickArrowLeft, ArrowRight, ArrowLeft, DottedLine, ThickLine, Line, TwoDashes, InvalidArrow, DoubleSquareOpen, DoubleSquareClose, DoubleRoundOpen, DoubleRoundClose, HexagonOpen, HexagonClose, StadiumOpen, StadiumClose, CylinderOpen, CylinderClose, SquareOpen, SquareClose, RoundOpen, RoundClose, DiamondOpen, DiamondClose, AngleOpen, AngleLess, Pipe, ForwardSlash, Backslash, QuotedString, MultilineText, Comment, ColorValue, Text, WhiteSpace, Newline, allTokens, MermaidLexer;
|
|
41550
41603
|
var init_lexer2 = __esm({
|
|
41551
41604
|
"node_modules/@probelabs/maid/out/diagrams/flowchart/lexer.js"() {
|
|
41552
41605
|
init_api5();
|
|
41553
41606
|
Identifier = createToken({
|
|
41554
41607
|
name: "Identifier",
|
|
41555
|
-
|
|
41608
|
+
// e.g., id-2, _id, A1, but not A-- (that belongs to an arrow token)
|
|
41609
|
+
pattern: /[a-zA-Z_][a-zA-Z0-9_]*(?:-[a-zA-Z0-9_]+)*/
|
|
41556
41610
|
});
|
|
41557
41611
|
NumberLiteral = createToken({
|
|
41558
41612
|
name: "NumberLiteral",
|
|
@@ -41693,6 +41747,8 @@ var init_lexer2 = __esm({
|
|
|
41693
41747
|
AngleOpen = createToken({ name: "AngleOpen", pattern: />/ });
|
|
41694
41748
|
AngleLess = createToken({ name: "AngleLess", pattern: /</ });
|
|
41695
41749
|
Pipe = createToken({ name: "Pipe", pattern: /\|/ });
|
|
41750
|
+
ForwardSlash = createToken({ name: "ForwardSlash", pattern: /\// });
|
|
41751
|
+
Backslash = createToken({ name: "Backslash", pattern: /\\/ });
|
|
41696
41752
|
QuotedString = createToken({
|
|
41697
41753
|
name: "QuotedString",
|
|
41698
41754
|
// Allow escaped characters within quotes (Mermaid accepts \" inside "...")
|
|
@@ -41776,6 +41832,8 @@ var init_lexer2 = __esm({
|
|
|
41776
41832
|
DiamondClose,
|
|
41777
41833
|
AngleOpen,
|
|
41778
41834
|
AngleLess,
|
|
41835
|
+
ForwardSlash,
|
|
41836
|
+
Backslash,
|
|
41779
41837
|
Pipe,
|
|
41780
41838
|
TripleColon,
|
|
41781
41839
|
Ampersand,
|
|
@@ -41968,6 +42026,8 @@ var init_parser2 = __esm({
|
|
|
41968
42026
|
// Allow HTML-like tags (e.g., <br/>) inside labels
|
|
41969
42027
|
{ ALT: () => this.CONSUME(AngleLess) },
|
|
41970
42028
|
{ ALT: () => this.CONSUME(AngleOpen) },
|
|
42029
|
+
{ ALT: () => this.CONSUME(ForwardSlash) },
|
|
42030
|
+
{ ALT: () => this.CONSUME(Backslash) },
|
|
41971
42031
|
{ ALT: () => this.CONSUME(Comma) },
|
|
41972
42032
|
{ ALT: () => this.CONSUME(Colon) },
|
|
41973
42033
|
// HTML entities and ampersands inside labels
|
|
@@ -43016,6 +43076,66 @@ ${br.example}`,
|
|
|
43016
43076
|
length: len
|
|
43017
43077
|
};
|
|
43018
43078
|
}
|
|
43079
|
+
if (inRule("boxBlock") && (err.name === "NoViableAltException" || err.name === "MismatchedTokenException")) {
|
|
43080
|
+
const isMessage = /->|-->>|-->/.test(ltxt);
|
|
43081
|
+
const isNote = /note\s+(left|right|over)/i.test(ltxt);
|
|
43082
|
+
const isActivate = /activate\s+/i.test(ltxt);
|
|
43083
|
+
const isDeactivate = /deactivate\s+/i.test(ltxt);
|
|
43084
|
+
if (isMessage || isNote || isActivate || isDeactivate || tokType === "NoteKeyword" || tokType === "ActivateKeyword" || tokType === "DeactivateKeyword") {
|
|
43085
|
+
const lines2 = text.split(/\r?\n/);
|
|
43086
|
+
const boxLine = Math.max(0, line - 1);
|
|
43087
|
+
let hasEnd = false;
|
|
43088
|
+
let openIdx = -1;
|
|
43089
|
+
for (let i3 = boxLine; i3 >= 0; i3--) {
|
|
43090
|
+
if (/^\s*box\b/.test(lines2[i3] || "")) {
|
|
43091
|
+
openIdx = i3;
|
|
43092
|
+
break;
|
|
43093
|
+
}
|
|
43094
|
+
}
|
|
43095
|
+
if (openIdx !== -1) {
|
|
43096
|
+
for (let i3 = boxLine; i3 < lines2.length; i3++) {
|
|
43097
|
+
if (/^\s*end\s*$/.test(lines2[i3] || "")) {
|
|
43098
|
+
hasEnd = true;
|
|
43099
|
+
break;
|
|
43100
|
+
}
|
|
43101
|
+
if (i3 > boxLine && /^\s*(sequenceDiagram|box|alt|opt|loop|par|rect|critical|break)\b/.test(lines2[i3] || ""))
|
|
43102
|
+
break;
|
|
43103
|
+
}
|
|
43104
|
+
}
|
|
43105
|
+
if (hasEnd) {
|
|
43106
|
+
let hasParticipants = false;
|
|
43107
|
+
for (let i3 = openIdx + 1; i3 < lines2.length; i3++) {
|
|
43108
|
+
const raw = lines2[i3] || "";
|
|
43109
|
+
if (/^\s*end\s*$/.test(raw))
|
|
43110
|
+
break;
|
|
43111
|
+
if (/^\s*(participant|actor)\b/i.test(raw)) {
|
|
43112
|
+
hasParticipants = true;
|
|
43113
|
+
break;
|
|
43114
|
+
}
|
|
43115
|
+
}
|
|
43116
|
+
if (!hasParticipants) {
|
|
43117
|
+
return {
|
|
43118
|
+
line: openIdx + 1,
|
|
43119
|
+
column: 1,
|
|
43120
|
+
severity: "error",
|
|
43121
|
+
code: "SE-BOX-EMPTY",
|
|
43122
|
+
message: "Box block has no participant/actor declarations. Use 'rect' to group messages visually.",
|
|
43123
|
+
hint: "Replace 'box' with 'rect' if you want to group messages:\nrect rgb(240, 240, 255)\n A->>B: Message\n Note over A: Info\nend",
|
|
43124
|
+
length: 3
|
|
43125
|
+
};
|
|
43126
|
+
}
|
|
43127
|
+
return {
|
|
43128
|
+
line,
|
|
43129
|
+
column,
|
|
43130
|
+
severity: "error",
|
|
43131
|
+
code: "SE-BOX-INVALID-CONTENT",
|
|
43132
|
+
message: "Box blocks can only contain participant/actor declarations.",
|
|
43133
|
+
hint: 'Move messages, notes, and other statements outside the box block.\nExample:\nbox "Group"\n participant A\n participant B\nend\nA->>B: Message',
|
|
43134
|
+
length: len
|
|
43135
|
+
};
|
|
43136
|
+
}
|
|
43137
|
+
}
|
|
43138
|
+
}
|
|
43019
43139
|
const blockRules = [
|
|
43020
43140
|
{ rule: "altBlock", label: "alt" },
|
|
43021
43141
|
{ rule: "optBlock", label: "opt" },
|
|
@@ -43915,9 +44035,15 @@ var init_parser4 = __esm({
|
|
|
43915
44035
|
this.CONSUME(BoxKeyword);
|
|
43916
44036
|
this.OPTION(() => this.SUBRULE(this.lineRemainder));
|
|
43917
44037
|
this.AT_LEAST_ONE(() => this.CONSUME(Newline3));
|
|
43918
|
-
this.MANY(() => this.
|
|
44038
|
+
this.MANY(() => this.OR([
|
|
44039
|
+
{ ALT: () => this.SUBRULE(this.participantDecl) },
|
|
44040
|
+
{ ALT: () => this.SUBRULE(this.blankLine) }
|
|
44041
|
+
]));
|
|
43919
44042
|
this.CONSUME(EndKeyword2);
|
|
43920
|
-
this.
|
|
44043
|
+
this.OR2([
|
|
44044
|
+
{ ALT: () => this.AT_LEAST_ONE2(() => this.CONSUME2(Newline3)) },
|
|
44045
|
+
{ ALT: () => this.CONSUME2(EOF) }
|
|
44046
|
+
]);
|
|
43921
44047
|
});
|
|
43922
44048
|
this.lineRemainder = this.RULE("lineRemainder", () => {
|
|
43923
44049
|
this.AT_LEAST_ONE(() => this.OR([
|
|
@@ -45468,6 +45594,69 @@ function computeFixes(text, errors, level = "safe") {
|
|
|
45468
45594
|
edits.push(replaceRange(text, at(e3), e3.length ?? 4, "option"));
|
|
45469
45595
|
continue;
|
|
45470
45596
|
}
|
|
45597
|
+
if (is("SE-BOX-EMPTY", e3)) {
|
|
45598
|
+
const lines = text.split(/\r?\n/);
|
|
45599
|
+
const boxIdx = Math.max(0, e3.line - 1);
|
|
45600
|
+
const boxLine = lines[boxIdx] || "";
|
|
45601
|
+
const labelMatch = /^\s*box\s+(.+)$/.exec(boxLine);
|
|
45602
|
+
if (labelMatch) {
|
|
45603
|
+
const indent = boxLine.match(/^\s*/)?.[0] || "";
|
|
45604
|
+
const newLine = `${indent}rect rgb(240, 240, 255)`;
|
|
45605
|
+
edits.push({ start: { line: e3.line, column: 1 }, end: { line: e3.line, column: boxLine.length + 1 }, newText: newLine });
|
|
45606
|
+
}
|
|
45607
|
+
continue;
|
|
45608
|
+
}
|
|
45609
|
+
if (is("SE-BOX-INVALID-CONTENT", e3)) {
|
|
45610
|
+
const lines = text.split(/\r?\n/);
|
|
45611
|
+
const curIdx = Math.max(0, e3.line - 1);
|
|
45612
|
+
const boxRe = /^(\s*)box\b/;
|
|
45613
|
+
let openIdx = -1;
|
|
45614
|
+
let openIndent = "";
|
|
45615
|
+
for (let i3 = curIdx; i3 >= 0; i3--) {
|
|
45616
|
+
const m3 = boxRe.exec(lines[i3] || "");
|
|
45617
|
+
if (m3) {
|
|
45618
|
+
openIdx = i3;
|
|
45619
|
+
openIndent = m3[1] || "";
|
|
45620
|
+
break;
|
|
45621
|
+
}
|
|
45622
|
+
}
|
|
45623
|
+
if (openIdx !== -1) {
|
|
45624
|
+
let endIdx = -1;
|
|
45625
|
+
for (let i3 = openIdx + 1; i3 < lines.length; i3++) {
|
|
45626
|
+
const trimmed = (lines[i3] || "").trim();
|
|
45627
|
+
if (trimmed === "end") {
|
|
45628
|
+
endIdx = i3;
|
|
45629
|
+
break;
|
|
45630
|
+
}
|
|
45631
|
+
}
|
|
45632
|
+
if (endIdx !== -1) {
|
|
45633
|
+
const invalidLines = [];
|
|
45634
|
+
for (let i3 = openIdx + 1; i3 < endIdx; i3++) {
|
|
45635
|
+
const raw = lines[i3] || "";
|
|
45636
|
+
const trimmed = raw.trim();
|
|
45637
|
+
if (trimmed === "")
|
|
45638
|
+
continue;
|
|
45639
|
+
if (!/^\s*(participant|actor)\b/i.test(raw)) {
|
|
45640
|
+
invalidLines.push(i3);
|
|
45641
|
+
}
|
|
45642
|
+
}
|
|
45643
|
+
if (invalidLines.length > 0) {
|
|
45644
|
+
const endIndent = openIndent;
|
|
45645
|
+
const movedContent = invalidLines.map((i3) => {
|
|
45646
|
+
const line = lines[i3] || "";
|
|
45647
|
+
const trimmed = line.trimStart();
|
|
45648
|
+
return endIndent + trimmed;
|
|
45649
|
+
}).join("\n") + "\n";
|
|
45650
|
+
for (let i3 = invalidLines.length - 1; i3 >= 0; i3--) {
|
|
45651
|
+
const idx = invalidLines[i3];
|
|
45652
|
+
edits.push({ start: { line: idx + 1, column: 1 }, end: { line: idx + 2, column: 1 }, newText: "" });
|
|
45653
|
+
}
|
|
45654
|
+
edits.push(insertAt(text, { line: endIdx + 2, column: 1 }, movedContent));
|
|
45655
|
+
}
|
|
45656
|
+
}
|
|
45657
|
+
}
|
|
45658
|
+
continue;
|
|
45659
|
+
}
|
|
45471
45660
|
if (is("SE-BLOCK-MISSING-END", e3)) {
|
|
45472
45661
|
const lines = text.split(/\r?\n/);
|
|
45473
45662
|
const curIdx = Math.max(0, e3.line - 1);
|
|
@@ -45748,26 +45937,561 @@ var init_fixes = __esm({
|
|
|
45748
45937
|
});
|
|
45749
45938
|
|
|
45750
45939
|
// node_modules/@probelabs/maid/out/renderer/graph-builder.js
|
|
45940
|
+
var GraphBuilder;
|
|
45751
45941
|
var init_graph_builder = __esm({
|
|
45752
45942
|
"node_modules/@probelabs/maid/out/renderer/graph-builder.js"() {
|
|
45753
|
-
|
|
45754
|
-
|
|
45755
|
-
|
|
45756
|
-
|
|
45757
|
-
|
|
45758
|
-
|
|
45759
|
-
|
|
45760
|
-
|
|
45761
|
-
|
|
45762
|
-
|
|
45763
|
-
|
|
45764
|
-
|
|
45765
|
-
|
|
45766
|
-
|
|
45767
|
-
|
|
45768
|
-
|
|
45769
|
-
|
|
45770
|
-
|
|
45943
|
+
GraphBuilder = class {
|
|
45944
|
+
constructor() {
|
|
45945
|
+
this.nodes = /* @__PURE__ */ new Map();
|
|
45946
|
+
this.edges = [];
|
|
45947
|
+
this.nodeCounter = 0;
|
|
45948
|
+
this.edgeCounter = 0;
|
|
45949
|
+
this.subgraphs = [];
|
|
45950
|
+
this.currentSubgraphStack = [];
|
|
45951
|
+
this.classStyles = /* @__PURE__ */ new Map();
|
|
45952
|
+
this.nodeStyles = /* @__PURE__ */ new Map();
|
|
45953
|
+
this.nodeClasses = /* @__PURE__ */ new Map();
|
|
45954
|
+
}
|
|
45955
|
+
build(cst) {
|
|
45956
|
+
this.reset();
|
|
45957
|
+
if (!cst || !cst.children) {
|
|
45958
|
+
return {
|
|
45959
|
+
nodes: [],
|
|
45960
|
+
edges: [],
|
|
45961
|
+
direction: "TD",
|
|
45962
|
+
subgraphs: []
|
|
45963
|
+
};
|
|
45964
|
+
}
|
|
45965
|
+
const direction = this.extractDirection(cst);
|
|
45966
|
+
this.processStatements(cst);
|
|
45967
|
+
return {
|
|
45968
|
+
nodes: Array.from(this.nodes.values()),
|
|
45969
|
+
edges: this.edges,
|
|
45970
|
+
direction,
|
|
45971
|
+
subgraphs: this.subgraphs
|
|
45972
|
+
};
|
|
45973
|
+
}
|
|
45974
|
+
reset() {
|
|
45975
|
+
this.nodes.clear();
|
|
45976
|
+
this.edges = [];
|
|
45977
|
+
this.nodeCounter = 0;
|
|
45978
|
+
this.edgeCounter = 0;
|
|
45979
|
+
this.subgraphs = [];
|
|
45980
|
+
this.currentSubgraphStack = [];
|
|
45981
|
+
this.classStyles.clear();
|
|
45982
|
+
this.nodeStyles.clear();
|
|
45983
|
+
this.nodeClasses.clear();
|
|
45984
|
+
}
|
|
45985
|
+
extractDirection(cst) {
|
|
45986
|
+
const dirToken = cst.children?.Direction?.[0];
|
|
45987
|
+
const dir = dirToken?.image?.toUpperCase();
|
|
45988
|
+
switch (dir) {
|
|
45989
|
+
case "TB":
|
|
45990
|
+
case "TD":
|
|
45991
|
+
return "TD";
|
|
45992
|
+
case "BT":
|
|
45993
|
+
return "BT";
|
|
45994
|
+
case "LR":
|
|
45995
|
+
return "LR";
|
|
45996
|
+
case "RL":
|
|
45997
|
+
return "RL";
|
|
45998
|
+
default:
|
|
45999
|
+
return "TD";
|
|
46000
|
+
}
|
|
46001
|
+
}
|
|
46002
|
+
processStatements(cst) {
|
|
46003
|
+
const statements = cst.children?.statement;
|
|
46004
|
+
if (!statements)
|
|
46005
|
+
return;
|
|
46006
|
+
for (const stmt of statements) {
|
|
46007
|
+
if (stmt.children?.nodeStatement) {
|
|
46008
|
+
this.processNodeStatement(stmt.children.nodeStatement[0]);
|
|
46009
|
+
} else if (stmt.children?.subgraph) {
|
|
46010
|
+
this.processSubgraph(stmt.children.subgraph[0]);
|
|
46011
|
+
} else if (stmt.children?.classDefStatement) {
|
|
46012
|
+
this.processClassDef(stmt.children.classDefStatement[0]);
|
|
46013
|
+
} else if (stmt.children?.classStatement) {
|
|
46014
|
+
this.processClassAssign(stmt.children.classStatement[0]);
|
|
46015
|
+
} else if (stmt.children?.styleStatement) {
|
|
46016
|
+
this.processStyle(stmt.children.styleStatement[0]);
|
|
46017
|
+
}
|
|
46018
|
+
}
|
|
46019
|
+
}
|
|
46020
|
+
processNodeStatement(stmt) {
|
|
46021
|
+
const groups = stmt.children?.nodeOrParallelGroup;
|
|
46022
|
+
const links = stmt.children?.link;
|
|
46023
|
+
if (!groups || groups.length === 0)
|
|
46024
|
+
return;
|
|
46025
|
+
const sourceNodes = this.processNodeGroup(groups[0]);
|
|
46026
|
+
if (groups.length > 1 && links && links.length > 0) {
|
|
46027
|
+
const targetNodes = this.processNodeGroup(groups[1]);
|
|
46028
|
+
const linkInfo = this.extractLinkInfo(links[0]);
|
|
46029
|
+
for (const source of sourceNodes) {
|
|
46030
|
+
for (const target of targetNodes) {
|
|
46031
|
+
this.edges.push({
|
|
46032
|
+
id: `e${this.edgeCounter++}`,
|
|
46033
|
+
source,
|
|
46034
|
+
target,
|
|
46035
|
+
label: linkInfo.label,
|
|
46036
|
+
type: linkInfo.type,
|
|
46037
|
+
markerStart: linkInfo.markerStart,
|
|
46038
|
+
markerEnd: linkInfo.markerEnd
|
|
46039
|
+
});
|
|
46040
|
+
}
|
|
46041
|
+
}
|
|
46042
|
+
for (let i3 = 2; i3 < groups.length; i3++) {
|
|
46043
|
+
const nextNodes = this.processNodeGroup(groups[i3]);
|
|
46044
|
+
const nextLink = links[i3 - 1] ? this.extractLinkInfo(links[i3 - 1]) : linkInfo;
|
|
46045
|
+
for (const source of targetNodes) {
|
|
46046
|
+
for (const target of nextNodes) {
|
|
46047
|
+
this.edges.push({
|
|
46048
|
+
id: `e${this.edgeCounter++}`,
|
|
46049
|
+
source,
|
|
46050
|
+
target,
|
|
46051
|
+
label: nextLink.label,
|
|
46052
|
+
type: nextLink.type,
|
|
46053
|
+
markerStart: nextLink.markerStart,
|
|
46054
|
+
markerEnd: nextLink.markerEnd
|
|
46055
|
+
});
|
|
46056
|
+
}
|
|
46057
|
+
}
|
|
46058
|
+
targetNodes.length = 0;
|
|
46059
|
+
targetNodes.push(...nextNodes);
|
|
46060
|
+
}
|
|
46061
|
+
}
|
|
46062
|
+
}
|
|
46063
|
+
processNodeGroup(group) {
|
|
46064
|
+
const nodes = group.children?.node;
|
|
46065
|
+
if (!nodes)
|
|
46066
|
+
return [];
|
|
46067
|
+
const nodeIds = [];
|
|
46068
|
+
for (const node of nodes) {
|
|
46069
|
+
const nodeInfo = this.extractNodeInfo(node);
|
|
46070
|
+
if (nodeInfo) {
|
|
46071
|
+
const isSubgraph = this.subgraphs.some((sg) => sg.id === nodeInfo.id);
|
|
46072
|
+
if (!isSubgraph) {
|
|
46073
|
+
if (!this.nodes.has(nodeInfo.id)) {
|
|
46074
|
+
nodeInfo.style = this.computeNodeStyle(nodeInfo.id);
|
|
46075
|
+
this.nodes.set(nodeInfo.id, nodeInfo);
|
|
46076
|
+
} else {
|
|
46077
|
+
const existing = this.nodes.get(nodeInfo.id);
|
|
46078
|
+
if (nodeInfo.shape !== "rectangle" || nodeInfo.label !== nodeInfo.id) {
|
|
46079
|
+
if (nodeInfo.label !== nodeInfo.id) {
|
|
46080
|
+
existing.label = nodeInfo.label;
|
|
46081
|
+
}
|
|
46082
|
+
if (nodeInfo.shape !== "rectangle") {
|
|
46083
|
+
existing.shape = nodeInfo.shape;
|
|
46084
|
+
}
|
|
46085
|
+
}
|
|
46086
|
+
const merged = this.computeNodeStyle(nodeInfo.id);
|
|
46087
|
+
if (Object.keys(merged).length) {
|
|
46088
|
+
existing.style = { ...existing.style || {}, ...merged };
|
|
46089
|
+
}
|
|
46090
|
+
}
|
|
46091
|
+
if (this.currentSubgraphStack.length) {
|
|
46092
|
+
for (const sgId of this.currentSubgraphStack) {
|
|
46093
|
+
const subgraph = this.subgraphs.find((s3) => s3.id === sgId);
|
|
46094
|
+
if (subgraph && !subgraph.nodes.includes(nodeInfo.id)) {
|
|
46095
|
+
subgraph.nodes.push(nodeInfo.id);
|
|
46096
|
+
}
|
|
46097
|
+
}
|
|
46098
|
+
}
|
|
46099
|
+
}
|
|
46100
|
+
nodeIds.push(nodeInfo.id);
|
|
46101
|
+
}
|
|
46102
|
+
}
|
|
46103
|
+
return nodeIds;
|
|
46104
|
+
}
|
|
46105
|
+
extractNodeInfo(node) {
|
|
46106
|
+
const children = node.children;
|
|
46107
|
+
if (!children)
|
|
46108
|
+
return null;
|
|
46109
|
+
let id;
|
|
46110
|
+
if (children.nodeId) {
|
|
46111
|
+
id = children.nodeId[0].image;
|
|
46112
|
+
if (children.nodeIdSuffix) {
|
|
46113
|
+
id += children.nodeIdSuffix[0].image;
|
|
46114
|
+
}
|
|
46115
|
+
} else if (children.nodeIdNum) {
|
|
46116
|
+
id = children.nodeIdNum[0].image;
|
|
46117
|
+
} else if (children.Identifier) {
|
|
46118
|
+
id = children.Identifier[0].image;
|
|
46119
|
+
} else {
|
|
46120
|
+
return null;
|
|
46121
|
+
}
|
|
46122
|
+
let shape = "rectangle";
|
|
46123
|
+
let label = id;
|
|
46124
|
+
const shapeNode = children.nodeShape?.[0];
|
|
46125
|
+
if (shapeNode?.children) {
|
|
46126
|
+
const result = this.extractShapeAndLabel(shapeNode);
|
|
46127
|
+
shape = result.shape;
|
|
46128
|
+
if (result.label)
|
|
46129
|
+
label = result.label;
|
|
46130
|
+
}
|
|
46131
|
+
const clsTok = children.nodeClass?.[0];
|
|
46132
|
+
if (clsTok) {
|
|
46133
|
+
const set = this.nodeClasses.get(id) || /* @__PURE__ */ new Set();
|
|
46134
|
+
set.add(clsTok.image);
|
|
46135
|
+
this.nodeClasses.set(id, set);
|
|
46136
|
+
}
|
|
46137
|
+
return { id, label, shape };
|
|
46138
|
+
}
|
|
46139
|
+
extractShapeAndLabel(shapeNode) {
|
|
46140
|
+
const children = shapeNode.children;
|
|
46141
|
+
let shape = "rectangle";
|
|
46142
|
+
let label = "";
|
|
46143
|
+
const contentNodes = children?.nodeContent;
|
|
46144
|
+
if (contentNodes && contentNodes.length > 0) {
|
|
46145
|
+
label = this.extractTextContent(contentNodes[0]);
|
|
46146
|
+
}
|
|
46147
|
+
if (children?.SquareOpen) {
|
|
46148
|
+
shape = "rectangle";
|
|
46149
|
+
const contentNode = children.nodeContent?.[0];
|
|
46150
|
+
if (contentNode) {
|
|
46151
|
+
const c3 = contentNode.children;
|
|
46152
|
+
const tokTypes = ["ForwardSlash", "Backslash", "Identifier", "Text", "NumberLiteral", "RoundOpen", "RoundClose", "AngleLess", "AngleOpen", "Comma", "Colon", "Ampersand", "Semicolon", "TwoDashes", "Line", "ThickLine", "DottedLine"];
|
|
46153
|
+
const toks = [];
|
|
46154
|
+
for (const tt of tokTypes) {
|
|
46155
|
+
const arr = c3[tt];
|
|
46156
|
+
arr?.forEach((t3) => toks.push({ type: tt, t: t3, start: t3.startOffset ?? 0 }));
|
|
46157
|
+
}
|
|
46158
|
+
if (toks.length >= 2) {
|
|
46159
|
+
toks.sort((a3, b3) => a3.start - b3.start);
|
|
46160
|
+
const first2 = toks[0].type;
|
|
46161
|
+
const last2 = toks[toks.length - 1].type;
|
|
46162
|
+
if (first2 === "ForwardSlash" && last2 === "ForwardSlash" || first2 === "Backslash" && last2 === "Backslash") {
|
|
46163
|
+
shape = "parallelogram";
|
|
46164
|
+
} else if (first2 === "ForwardSlash" && last2 === "Backslash") {
|
|
46165
|
+
shape = "trapezoid";
|
|
46166
|
+
} else if (first2 === "Backslash" && last2 === "ForwardSlash") {
|
|
46167
|
+
shape = "trapezoidAlt";
|
|
46168
|
+
}
|
|
46169
|
+
}
|
|
46170
|
+
}
|
|
46171
|
+
} else if (children?.RoundOpen) {
|
|
46172
|
+
shape = "round";
|
|
46173
|
+
} else if (children?.DiamondOpen) {
|
|
46174
|
+
shape = "diamond";
|
|
46175
|
+
} else if (children?.DoubleRoundOpen) {
|
|
46176
|
+
shape = "circle";
|
|
46177
|
+
} else if (children?.StadiumOpen) {
|
|
46178
|
+
shape = "stadium";
|
|
46179
|
+
} else if (children?.HexagonOpen) {
|
|
46180
|
+
shape = "hexagon";
|
|
46181
|
+
} else if (children?.DoubleSquareOpen) {
|
|
46182
|
+
shape = "subroutine";
|
|
46183
|
+
} else if (children?.CylinderOpen) {
|
|
46184
|
+
shape = "cylinder";
|
|
46185
|
+
} else if (children?.TrapezoidOpen) {
|
|
46186
|
+
shape = "trapezoid";
|
|
46187
|
+
} else if (children?.ParallelogramOpen) {
|
|
46188
|
+
shape = "parallelogram";
|
|
46189
|
+
}
|
|
46190
|
+
return { shape, label };
|
|
46191
|
+
}
|
|
46192
|
+
extractTextContent(contentNode) {
|
|
46193
|
+
const children = contentNode.children;
|
|
46194
|
+
if (!children)
|
|
46195
|
+
return "";
|
|
46196
|
+
const tokenTypes = [
|
|
46197
|
+
"Text",
|
|
46198
|
+
"Identifier",
|
|
46199
|
+
"QuotedString",
|
|
46200
|
+
"NumberLiteral",
|
|
46201
|
+
"Ampersand",
|
|
46202
|
+
"Comma",
|
|
46203
|
+
"Colon",
|
|
46204
|
+
"Semicolon",
|
|
46205
|
+
"Dot",
|
|
46206
|
+
"Underscore",
|
|
46207
|
+
"Dash",
|
|
46208
|
+
"ForwardSlash",
|
|
46209
|
+
"Backslash",
|
|
46210
|
+
"AngleLess",
|
|
46211
|
+
"AngleOpen"
|
|
46212
|
+
];
|
|
46213
|
+
const tokenWithPositions = [];
|
|
46214
|
+
for (const type of tokenTypes) {
|
|
46215
|
+
const tokens = children[type];
|
|
46216
|
+
if (tokens) {
|
|
46217
|
+
for (const token of tokens) {
|
|
46218
|
+
let text = token.image;
|
|
46219
|
+
if (type === "QuotedString" && text.startsWith('"') && text.endsWith('"')) {
|
|
46220
|
+
text = text.slice(1, -1);
|
|
46221
|
+
}
|
|
46222
|
+
if ((type === "ForwardSlash" || type === "Backslash") && tokenWithPositions.length === 0) {
|
|
46223
|
+
continue;
|
|
46224
|
+
}
|
|
46225
|
+
tokenWithPositions.push({
|
|
46226
|
+
text,
|
|
46227
|
+
startOffset: token.startOffset ?? 0,
|
|
46228
|
+
type
|
|
46229
|
+
});
|
|
46230
|
+
}
|
|
46231
|
+
}
|
|
46232
|
+
}
|
|
46233
|
+
tokenWithPositions.sort((a3, b3) => a3.startOffset - b3.startOffset);
|
|
46234
|
+
if (tokenWithPositions.length) {
|
|
46235
|
+
const first2 = tokenWithPositions[0];
|
|
46236
|
+
if (first2.type === "ForwardSlash" || first2.type === "Backslash") {
|
|
46237
|
+
tokenWithPositions.shift();
|
|
46238
|
+
}
|
|
46239
|
+
const last2 = tokenWithPositions[tokenWithPositions.length - 1];
|
|
46240
|
+
if (last2.type === "ForwardSlash" || last2.type === "Backslash") {
|
|
46241
|
+
tokenWithPositions.pop();
|
|
46242
|
+
}
|
|
46243
|
+
}
|
|
46244
|
+
const parts = tokenWithPositions.map((t3) => t3.text);
|
|
46245
|
+
if (children.Space) {
|
|
46246
|
+
return parts.join("");
|
|
46247
|
+
}
|
|
46248
|
+
return parts.join(" ").trim();
|
|
46249
|
+
}
|
|
46250
|
+
extractLinkInfo(link) {
|
|
46251
|
+
const children = link.children;
|
|
46252
|
+
let type = "arrow";
|
|
46253
|
+
let label;
|
|
46254
|
+
let markerStart = "none";
|
|
46255
|
+
let markerEnd = "none";
|
|
46256
|
+
if (children.BiDirectionalArrow) {
|
|
46257
|
+
type = "arrow";
|
|
46258
|
+
markerStart = "arrow";
|
|
46259
|
+
markerEnd = "arrow";
|
|
46260
|
+
} else if (children.CircleEndLine) {
|
|
46261
|
+
type = "open";
|
|
46262
|
+
markerStart = "circle";
|
|
46263
|
+
markerEnd = "circle";
|
|
46264
|
+
} else if (children.CrossEndLine) {
|
|
46265
|
+
type = "open";
|
|
46266
|
+
markerStart = "cross";
|
|
46267
|
+
markerEnd = "cross";
|
|
46268
|
+
} else if (children?.ArrowRight) {
|
|
46269
|
+
type = "arrow";
|
|
46270
|
+
markerEnd = "arrow";
|
|
46271
|
+
} else if (children?.ArrowLeft) {
|
|
46272
|
+
type = "arrow";
|
|
46273
|
+
markerStart = "arrow";
|
|
46274
|
+
} else if (children?.DottedArrowRight) {
|
|
46275
|
+
type = "dotted";
|
|
46276
|
+
markerEnd = "arrow";
|
|
46277
|
+
} else if (children?.DottedArrowLeft) {
|
|
46278
|
+
type = "dotted";
|
|
46279
|
+
markerStart = "arrow";
|
|
46280
|
+
} else if (children?.ThickArrowRight) {
|
|
46281
|
+
type = "thick";
|
|
46282
|
+
markerEnd = "arrow";
|
|
46283
|
+
} else if (children?.ThickArrowLeft) {
|
|
46284
|
+
type = "thick";
|
|
46285
|
+
markerStart = "arrow";
|
|
46286
|
+
} else if (children?.LinkRight || children?.LinkLeft || children?.Line || children?.TwoDashes || children?.DottedLine || children?.ThickLine) {
|
|
46287
|
+
if (children?.DottedLine)
|
|
46288
|
+
type = "dotted";
|
|
46289
|
+
else if (children?.ThickLine)
|
|
46290
|
+
type = "thick";
|
|
46291
|
+
else
|
|
46292
|
+
type = "open";
|
|
46293
|
+
} else if (children?.InvisibleLink) {
|
|
46294
|
+
type = "invisible";
|
|
46295
|
+
}
|
|
46296
|
+
if (markerEnd === "none" && (children?.ArrowRight || children.ThickArrowRight || children.DottedArrowRight)) {
|
|
46297
|
+
markerEnd = "arrow";
|
|
46298
|
+
}
|
|
46299
|
+
if (markerStart === "none" && (children?.ArrowLeft || children.ThickArrowLeft || children.DottedArrowLeft)) {
|
|
46300
|
+
markerStart = "arrow";
|
|
46301
|
+
}
|
|
46302
|
+
const textNode = children?.linkText?.[0];
|
|
46303
|
+
if (textNode) {
|
|
46304
|
+
label = this.extractTextContent(textNode);
|
|
46305
|
+
} else if (children.linkTextInline?.[0]) {
|
|
46306
|
+
label = this.extractTextContent(children.linkTextInline[0]);
|
|
46307
|
+
} else if (children.inlineCarrier?.[0]) {
|
|
46308
|
+
const token = children.inlineCarrier[0];
|
|
46309
|
+
const raw = token.image.trim();
|
|
46310
|
+
if (raw.startsWith("-.") && raw.endsWith(".-")) {
|
|
46311
|
+
type = "dotted";
|
|
46312
|
+
} else if (raw.startsWith("==") && raw.endsWith("==")) {
|
|
46313
|
+
type = "thick";
|
|
46314
|
+
} else if (raw.startsWith("--") && raw.endsWith("--")) {
|
|
46315
|
+
}
|
|
46316
|
+
if (children.ArrowRight || children.DottedArrowRight || children.ThickArrowRight) {
|
|
46317
|
+
markerEnd = "arrow";
|
|
46318
|
+
}
|
|
46319
|
+
if (children.ArrowLeft || children.DottedArrowLeft || children.ThickArrowLeft) {
|
|
46320
|
+
markerStart = "arrow";
|
|
46321
|
+
}
|
|
46322
|
+
const strip = (str) => {
|
|
46323
|
+
if (str.startsWith("-.") && str.endsWith(".-") || str.startsWith("==") && str.endsWith("==") || str.startsWith("--") && str.endsWith("--")) {
|
|
46324
|
+
return str.slice(2, -2).trim();
|
|
46325
|
+
}
|
|
46326
|
+
return str;
|
|
46327
|
+
};
|
|
46328
|
+
label = strip(raw);
|
|
46329
|
+
}
|
|
46330
|
+
return { type, label, markerStart, markerEnd };
|
|
46331
|
+
}
|
|
46332
|
+
processSubgraph(subgraph) {
|
|
46333
|
+
const children = subgraph.children;
|
|
46334
|
+
let id = `subgraph_${this.subgraphs.length}`;
|
|
46335
|
+
let label;
|
|
46336
|
+
const idToken = children?.subgraphId?.[0] || children?.Identifier?.[0];
|
|
46337
|
+
if (idToken) {
|
|
46338
|
+
id = idToken.image;
|
|
46339
|
+
}
|
|
46340
|
+
if (children?.SquareOpen && children?.nodeContent) {
|
|
46341
|
+
label = this.extractTextContent(children.nodeContent[0]);
|
|
46342
|
+
} else if (children.subgraphTitleQ?.[0]) {
|
|
46343
|
+
const qt = children.subgraphTitleQ[0];
|
|
46344
|
+
const img = qt.image;
|
|
46345
|
+
label = img && img.length >= 2 && (img.startsWith('"') || img.startsWith("'")) ? img.slice(1, -1) : img;
|
|
46346
|
+
} else if (children?.subgraphLabel) {
|
|
46347
|
+
label = this.extractTextContent(children.subgraphLabel[0]);
|
|
46348
|
+
}
|
|
46349
|
+
if (!label && id !== `subgraph_${this.subgraphs.length}`) {
|
|
46350
|
+
label = id;
|
|
46351
|
+
}
|
|
46352
|
+
const parent = this.currentSubgraphStack.length ? this.currentSubgraphStack[this.currentSubgraphStack.length - 1] : void 0;
|
|
46353
|
+
const sg = { id, label, nodes: [], parent };
|
|
46354
|
+
this.subgraphs.push(sg);
|
|
46355
|
+
this.currentSubgraphStack.push(id);
|
|
46356
|
+
const statements = children?.subgraphStatement;
|
|
46357
|
+
if (statements) {
|
|
46358
|
+
for (const stmt of statements) {
|
|
46359
|
+
if (stmt.children?.nodeStatement) {
|
|
46360
|
+
this.processNodeStatement(stmt.children.nodeStatement[0]);
|
|
46361
|
+
} else if (stmt.children?.subgraph) {
|
|
46362
|
+
this.processSubgraph(stmt.children.subgraph[0]);
|
|
46363
|
+
}
|
|
46364
|
+
}
|
|
46365
|
+
}
|
|
46366
|
+
this.currentSubgraphStack.pop();
|
|
46367
|
+
}
|
|
46368
|
+
// ---- Styling helpers ----
|
|
46369
|
+
processClassDef(cst) {
|
|
46370
|
+
const idTok = cst.children?.Identifier?.[0];
|
|
46371
|
+
if (!idTok)
|
|
46372
|
+
return;
|
|
46373
|
+
const className = idTok.image;
|
|
46374
|
+
const props = this.collectStyleProps(cst, { skipFirstIdentifier: true });
|
|
46375
|
+
if (Object.keys(props).length) {
|
|
46376
|
+
this.classStyles.set(className, props);
|
|
46377
|
+
for (const [nodeId, classes] of this.nodeClasses.entries()) {
|
|
46378
|
+
if (classes.has(className)) {
|
|
46379
|
+
const node = this.nodes.get(nodeId);
|
|
46380
|
+
if (node) {
|
|
46381
|
+
node.style = { ...node.style || {}, ...this.computeNodeStyle(nodeId) };
|
|
46382
|
+
}
|
|
46383
|
+
}
|
|
46384
|
+
}
|
|
46385
|
+
}
|
|
46386
|
+
}
|
|
46387
|
+
processClassAssign(cst) {
|
|
46388
|
+
const ids = cst.children?.Identifier || [];
|
|
46389
|
+
if (!ids.length)
|
|
46390
|
+
return;
|
|
46391
|
+
const classNameTok = cst.children.className?.[0];
|
|
46392
|
+
const className = classNameTok?.image || ids[ids.length - 1].image;
|
|
46393
|
+
const nodeIds = classNameTok ? ids.slice(0, -1) : ids.slice(0, -1);
|
|
46394
|
+
for (const tok of nodeIds) {
|
|
46395
|
+
const id = tok.image;
|
|
46396
|
+
const set = this.nodeClasses.get(id) || /* @__PURE__ */ new Set();
|
|
46397
|
+
set.add(className);
|
|
46398
|
+
this.nodeClasses.set(id, set);
|
|
46399
|
+
const node = this.nodes.get(id);
|
|
46400
|
+
if (node) {
|
|
46401
|
+
node.style = { ...node.style || {}, ...this.computeNodeStyle(id) };
|
|
46402
|
+
}
|
|
46403
|
+
}
|
|
46404
|
+
}
|
|
46405
|
+
processStyle(cst) {
|
|
46406
|
+
const idTok = cst.children?.Identifier?.[0];
|
|
46407
|
+
if (!idTok)
|
|
46408
|
+
return;
|
|
46409
|
+
const nodeId = idTok.image;
|
|
46410
|
+
const props = this.collectStyleProps(cst, { skipFirstIdentifier: true });
|
|
46411
|
+
if (Object.keys(props).length) {
|
|
46412
|
+
this.nodeStyles.set(nodeId, props);
|
|
46413
|
+
const node = this.nodes.get(nodeId);
|
|
46414
|
+
if (node) {
|
|
46415
|
+
node.style = { ...node.style || {}, ...this.computeNodeStyle(nodeId) };
|
|
46416
|
+
}
|
|
46417
|
+
}
|
|
46418
|
+
}
|
|
46419
|
+
collectStyleProps(cst, opts = {}) {
|
|
46420
|
+
const tokens = [];
|
|
46421
|
+
const ch = cst.children || {};
|
|
46422
|
+
const push = (arr, type = "t") => arr?.forEach((t3) => tokens.push({ text: t3.image, startOffset: t3.startOffset ?? 0, type }));
|
|
46423
|
+
push(ch.Text, "Text");
|
|
46424
|
+
push(ch.Identifier, "Identifier");
|
|
46425
|
+
push(ch.ColorValue, "Color");
|
|
46426
|
+
push(ch.Colon, "Colon");
|
|
46427
|
+
push(ch.Comma, "Comma");
|
|
46428
|
+
push(ch.NumberLiteral, "Number");
|
|
46429
|
+
tokens.sort((a3, b3) => a3.startOffset - b3.startOffset);
|
|
46430
|
+
if (opts.skipFirstIdentifier) {
|
|
46431
|
+
const idx = tokens.findIndex((t3) => t3.type === "Identifier");
|
|
46432
|
+
if (idx >= 0)
|
|
46433
|
+
tokens.splice(idx, 1);
|
|
46434
|
+
}
|
|
46435
|
+
const joined = tokens.map((t3) => t3.text).join("");
|
|
46436
|
+
const props = {};
|
|
46437
|
+
for (const seg of joined.split(",").map((s3) => s3.trim()).filter(Boolean)) {
|
|
46438
|
+
const [k3, v3] = seg.split(":");
|
|
46439
|
+
if (k3 && v3)
|
|
46440
|
+
props[k3.trim()] = v3.trim();
|
|
46441
|
+
}
|
|
46442
|
+
return props;
|
|
46443
|
+
}
|
|
46444
|
+
computeNodeStyle(nodeId) {
|
|
46445
|
+
const out = {};
|
|
46446
|
+
const classes = this.nodeClasses.get(nodeId);
|
|
46447
|
+
if (classes) {
|
|
46448
|
+
for (const c3 of classes) {
|
|
46449
|
+
const s3 = this.classStyles.get(c3);
|
|
46450
|
+
if (s3)
|
|
46451
|
+
Object.assign(out, this.normalizeStyle(s3));
|
|
46452
|
+
}
|
|
46453
|
+
}
|
|
46454
|
+
const direct = this.nodeStyles.get(nodeId);
|
|
46455
|
+
if (direct)
|
|
46456
|
+
Object.assign(out, this.normalizeStyle(direct));
|
|
46457
|
+
return out;
|
|
46458
|
+
}
|
|
46459
|
+
normalizeStyle(s3) {
|
|
46460
|
+
const out = {};
|
|
46461
|
+
for (const [kRaw, vRaw] of Object.entries(s3)) {
|
|
46462
|
+
const k3 = kRaw.trim().toLowerCase();
|
|
46463
|
+
const v3 = vRaw.trim();
|
|
46464
|
+
if (k3 === "stroke-width") {
|
|
46465
|
+
const num = parseFloat(v3);
|
|
46466
|
+
if (!Number.isNaN(num))
|
|
46467
|
+
out.strokeWidth = num;
|
|
46468
|
+
} else if (k3 === "stroke") {
|
|
46469
|
+
out.stroke = v3;
|
|
46470
|
+
} else if (k3 === "fill") {
|
|
46471
|
+
out.fill = v3;
|
|
46472
|
+
}
|
|
46473
|
+
}
|
|
46474
|
+
return out;
|
|
46475
|
+
}
|
|
46476
|
+
};
|
|
46477
|
+
}
|
|
46478
|
+
});
|
|
46479
|
+
|
|
46480
|
+
// node_modules/lodash/_listCacheClear.js
|
|
46481
|
+
var require_listCacheClear = __commonJS({
|
|
46482
|
+
"node_modules/lodash/_listCacheClear.js"(exports2, module2) {
|
|
46483
|
+
function listCacheClear2() {
|
|
46484
|
+
this.__data__ = [];
|
|
46485
|
+
this.size = 0;
|
|
46486
|
+
}
|
|
46487
|
+
module2.exports = listCacheClear2;
|
|
46488
|
+
}
|
|
46489
|
+
});
|
|
46490
|
+
|
|
46491
|
+
// node_modules/lodash/eq.js
|
|
46492
|
+
var require_eq = __commonJS({
|
|
46493
|
+
"node_modules/lodash/eq.js"(exports2, module2) {
|
|
46494
|
+
function eq2(value, other) {
|
|
45771
46495
|
return value === other || value !== value && other !== other;
|
|
45772
46496
|
}
|
|
45773
46497
|
module2.exports = eq2;
|
|
@@ -53363,85 +54087,2504 @@ var require_layout = __commonJS({
|
|
|
53363
54087
|
}
|
|
53364
54088
|
});
|
|
53365
54089
|
}
|
|
53366
|
-
function selectNumberAttrs(obj, attrs) {
|
|
53367
|
-
return _2.mapValues(_2.pick(obj, attrs), Number);
|
|
54090
|
+
function selectNumberAttrs(obj, attrs) {
|
|
54091
|
+
return _2.mapValues(_2.pick(obj, attrs), Number);
|
|
54092
|
+
}
|
|
54093
|
+
function canonicalize(attrs) {
|
|
54094
|
+
var newAttrs = {};
|
|
54095
|
+
_2.forEach(attrs, function(v3, k3) {
|
|
54096
|
+
newAttrs[k3.toLowerCase()] = v3;
|
|
54097
|
+
});
|
|
54098
|
+
return newAttrs;
|
|
54099
|
+
}
|
|
54100
|
+
}
|
|
54101
|
+
});
|
|
54102
|
+
|
|
54103
|
+
// node_modules/dagre/lib/debug.js
|
|
54104
|
+
var require_debug = __commonJS({
|
|
54105
|
+
"node_modules/dagre/lib/debug.js"(exports2, module2) {
|
|
54106
|
+
var _2 = require_lodash2();
|
|
54107
|
+
var util = require_util();
|
|
54108
|
+
var Graph = require_graphlib2().Graph;
|
|
54109
|
+
module2.exports = {
|
|
54110
|
+
debugOrdering
|
|
54111
|
+
};
|
|
54112
|
+
function debugOrdering(g3) {
|
|
54113
|
+
var layerMatrix = util.buildLayerMatrix(g3);
|
|
54114
|
+
var h3 = new Graph({ compound: true, multigraph: true }).setGraph({});
|
|
54115
|
+
_2.forEach(g3.nodes(), function(v3) {
|
|
54116
|
+
h3.setNode(v3, { label: v3 });
|
|
54117
|
+
h3.setParent(v3, "layer" + g3.node(v3).rank);
|
|
54118
|
+
});
|
|
54119
|
+
_2.forEach(g3.edges(), function(e3) {
|
|
54120
|
+
h3.setEdge(e3.v, e3.w, {}, e3.name);
|
|
54121
|
+
});
|
|
54122
|
+
_2.forEach(layerMatrix, function(layer, i3) {
|
|
54123
|
+
var layerV = "layer" + i3;
|
|
54124
|
+
h3.setNode(layerV, { rank: "same" });
|
|
54125
|
+
_2.reduce(layer, function(u3, v3) {
|
|
54126
|
+
h3.setEdge(u3, v3, { style: "invis" });
|
|
54127
|
+
return v3;
|
|
54128
|
+
});
|
|
54129
|
+
});
|
|
54130
|
+
return h3;
|
|
54131
|
+
}
|
|
54132
|
+
}
|
|
54133
|
+
});
|
|
54134
|
+
|
|
54135
|
+
// node_modules/dagre/lib/version.js
|
|
54136
|
+
var require_version2 = __commonJS({
|
|
54137
|
+
"node_modules/dagre/lib/version.js"(exports2, module2) {
|
|
54138
|
+
module2.exports = "0.8.5";
|
|
54139
|
+
}
|
|
54140
|
+
});
|
|
54141
|
+
|
|
54142
|
+
// node_modules/dagre/index.js
|
|
54143
|
+
var require_dagre = __commonJS({
|
|
54144
|
+
"node_modules/dagre/index.js"(exports2, module2) {
|
|
54145
|
+
module2.exports = {
|
|
54146
|
+
graphlib: require_graphlib2(),
|
|
54147
|
+
layout: require_layout(),
|
|
54148
|
+
debug: require_debug(),
|
|
54149
|
+
util: {
|
|
54150
|
+
time: require_util().time,
|
|
54151
|
+
notime: require_util().notime
|
|
54152
|
+
},
|
|
54153
|
+
version: require_version2()
|
|
54154
|
+
};
|
|
54155
|
+
}
|
|
54156
|
+
});
|
|
54157
|
+
|
|
54158
|
+
// node_modules/@probelabs/maid/out/renderer/layout.js
|
|
54159
|
+
var import_dagre, DagreLayoutEngine;
|
|
54160
|
+
var init_layout = __esm({
|
|
54161
|
+
"node_modules/@probelabs/maid/out/renderer/layout.js"() {
|
|
54162
|
+
import_dagre = __toESM(require_dagre(), 1);
|
|
54163
|
+
DagreLayoutEngine = class {
|
|
54164
|
+
constructor() {
|
|
54165
|
+
this.nodeWidth = 120;
|
|
54166
|
+
this.nodeHeight = 50;
|
|
54167
|
+
this.rankSep = 50;
|
|
54168
|
+
this.nodeSep = 50;
|
|
54169
|
+
this.edgeSep = 10;
|
|
54170
|
+
}
|
|
54171
|
+
layout(graph) {
|
|
54172
|
+
const g3 = new import_dagre.default.graphlib.Graph();
|
|
54173
|
+
const hasClusters = !!(graph.subgraphs && graph.subgraphs.length > 0);
|
|
54174
|
+
const dir = this.mapDirection(graph.direction);
|
|
54175
|
+
let ranksep = this.rankSep;
|
|
54176
|
+
let nodesep = this.nodeSep;
|
|
54177
|
+
if (hasClusters) {
|
|
54178
|
+
if (dir === "LR" || dir === "RL") {
|
|
54179
|
+
ranksep += 20;
|
|
54180
|
+
nodesep += 70;
|
|
54181
|
+
} else {
|
|
54182
|
+
ranksep += 70;
|
|
54183
|
+
nodesep += 20;
|
|
54184
|
+
}
|
|
54185
|
+
}
|
|
54186
|
+
const graphConfig = {
|
|
54187
|
+
rankdir: dir,
|
|
54188
|
+
ranksep,
|
|
54189
|
+
nodesep,
|
|
54190
|
+
edgesep: this.edgeSep,
|
|
54191
|
+
marginx: 20,
|
|
54192
|
+
marginy: 20
|
|
54193
|
+
};
|
|
54194
|
+
if (hasClusters && (dir === "LR" || dir === "RL")) {
|
|
54195
|
+
graphConfig.ranker = "longest-path";
|
|
54196
|
+
graphConfig.acyclicer = "greedy";
|
|
54197
|
+
}
|
|
54198
|
+
if (hasClusters) {
|
|
54199
|
+
graphConfig.compound = true;
|
|
54200
|
+
}
|
|
54201
|
+
g3.setGraph(graphConfig);
|
|
54202
|
+
g3.setDefaultEdgeLabel(() => ({}));
|
|
54203
|
+
if (graph.subgraphs && graph.subgraphs.length > 0) {
|
|
54204
|
+
for (const subgraph of graph.subgraphs) {
|
|
54205
|
+
g3.setNode(subgraph.id, { label: subgraph.label || subgraph.id, clusterLabelPos: "top" });
|
|
54206
|
+
}
|
|
54207
|
+
}
|
|
54208
|
+
for (const node of graph.nodes) {
|
|
54209
|
+
const dimensions = this.calculateNodeDimensions(node.label, node.shape);
|
|
54210
|
+
g3.setNode(node.id, {
|
|
54211
|
+
width: dimensions.width,
|
|
54212
|
+
height: dimensions.height,
|
|
54213
|
+
label: node.label,
|
|
54214
|
+
shape: node.shape
|
|
54215
|
+
});
|
|
54216
|
+
}
|
|
54217
|
+
if (graph.subgraphs && graph.subgraphs.length > 0) {
|
|
54218
|
+
for (const subgraph of graph.subgraphs) {
|
|
54219
|
+
for (const nodeId of subgraph.nodes) {
|
|
54220
|
+
if (g3.hasNode(nodeId)) {
|
|
54221
|
+
try {
|
|
54222
|
+
g3.setParent(nodeId, subgraph.id);
|
|
54223
|
+
} catch {
|
|
54224
|
+
}
|
|
54225
|
+
}
|
|
54226
|
+
}
|
|
54227
|
+
if (subgraph.parent && g3.hasNode(subgraph.parent)) {
|
|
54228
|
+
try {
|
|
54229
|
+
g3.setParent(subgraph.id, subgraph.parent);
|
|
54230
|
+
} catch {
|
|
54231
|
+
}
|
|
54232
|
+
}
|
|
54233
|
+
}
|
|
54234
|
+
}
|
|
54235
|
+
for (const edge of graph.edges) {
|
|
54236
|
+
g3.setEdge(edge.source, edge.target, {
|
|
54237
|
+
label: edge.label,
|
|
54238
|
+
width: edge.label ? edge.label.length * 8 : 0,
|
|
54239
|
+
height: edge.label ? 20 : 0
|
|
54240
|
+
});
|
|
54241
|
+
}
|
|
54242
|
+
import_dagre.default.layout(g3);
|
|
54243
|
+
const graphInfo = g3.graph();
|
|
54244
|
+
const layoutNodes = [];
|
|
54245
|
+
const layoutEdges = [];
|
|
54246
|
+
for (const node of graph.nodes) {
|
|
54247
|
+
const nodeLayout = g3.node(node.id);
|
|
54248
|
+
if (nodeLayout) {
|
|
54249
|
+
layoutNodes.push({
|
|
54250
|
+
...node,
|
|
54251
|
+
x: nodeLayout.x - nodeLayout.width / 2,
|
|
54252
|
+
y: nodeLayout.y - nodeLayout.height / 2,
|
|
54253
|
+
width: nodeLayout.width,
|
|
54254
|
+
height: nodeLayout.height
|
|
54255
|
+
});
|
|
54256
|
+
}
|
|
54257
|
+
}
|
|
54258
|
+
const layoutSubgraphs = [];
|
|
54259
|
+
if (graph.subgraphs && graph.subgraphs.length > 0) {
|
|
54260
|
+
for (const sg of graph.subgraphs) {
|
|
54261
|
+
const members = layoutNodes.filter((nd) => sg.nodes.includes(nd.id));
|
|
54262
|
+
if (members.length) {
|
|
54263
|
+
const minX = Math.min(...members.map((m3) => m3.x));
|
|
54264
|
+
const minY = Math.min(...members.map((m3) => m3.y));
|
|
54265
|
+
const maxX = Math.max(...members.map((m3) => m3.x + m3.width));
|
|
54266
|
+
const maxY = Math.max(...members.map((m3) => m3.y + m3.height));
|
|
54267
|
+
const pad = 30;
|
|
54268
|
+
layoutSubgraphs.push({
|
|
54269
|
+
id: sg.id,
|
|
54270
|
+
label: sg.label || sg.id,
|
|
54271
|
+
x: minX - pad,
|
|
54272
|
+
y: minY - pad - 18,
|
|
54273
|
+
// space for title
|
|
54274
|
+
width: maxX - minX + pad * 2,
|
|
54275
|
+
height: maxY - minY + pad * 2 + 18,
|
|
54276
|
+
parent: sg.parent
|
|
54277
|
+
});
|
|
54278
|
+
}
|
|
54279
|
+
}
|
|
54280
|
+
const byId = Object.fromEntries(layoutSubgraphs.map((s3) => [s3.id, s3]));
|
|
54281
|
+
for (const sg of layoutSubgraphs) {
|
|
54282
|
+
if (!sg.parent)
|
|
54283
|
+
continue;
|
|
54284
|
+
const p3 = byId[sg.parent];
|
|
54285
|
+
if (!p3)
|
|
54286
|
+
continue;
|
|
54287
|
+
const minX = Math.min(p3.x, sg.x);
|
|
54288
|
+
const minY = Math.min(p3.y, sg.y);
|
|
54289
|
+
const maxX = Math.max(p3.x + p3.width, sg.x + sg.width);
|
|
54290
|
+
const maxY = Math.max(p3.y + p3.height, sg.y + sg.height);
|
|
54291
|
+
p3.x = minX;
|
|
54292
|
+
p3.y = minY;
|
|
54293
|
+
p3.width = maxX - minX;
|
|
54294
|
+
p3.height = maxY - minY;
|
|
54295
|
+
}
|
|
54296
|
+
}
|
|
54297
|
+
const subgraphById = Object.fromEntries(layoutSubgraphs.map((sg) => [sg.id, sg]));
|
|
54298
|
+
for (const edge of graph.edges) {
|
|
54299
|
+
const edgeLayout = g3.edge(edge.source, edge.target);
|
|
54300
|
+
let pts = edgeLayout && Array.isArray(edgeLayout.points) ? edgeLayout.points.slice() : [];
|
|
54301
|
+
const hasNaN = pts.some((p3) => !Number.isFinite(p3.x) || !Number.isFinite(p3.y));
|
|
54302
|
+
const srcSg = subgraphById[edge.source];
|
|
54303
|
+
const dstSg = subgraphById[edge.target];
|
|
54304
|
+
let synthesized = false;
|
|
54305
|
+
if (!pts.length || hasNaN || srcSg || dstSg) {
|
|
54306
|
+
const rankdir = this.mapDirection(graph.direction);
|
|
54307
|
+
const getNode = (id) => {
|
|
54308
|
+
const n3 = g3.node(id);
|
|
54309
|
+
if (!n3)
|
|
54310
|
+
return void 0;
|
|
54311
|
+
return {
|
|
54312
|
+
id,
|
|
54313
|
+
label: n3.label || id,
|
|
54314
|
+
shape: n3.shape || "rectangle",
|
|
54315
|
+
x: n3.x - n3.width / 2,
|
|
54316
|
+
y: n3.y - n3.height / 2,
|
|
54317
|
+
width: n3.width,
|
|
54318
|
+
height: n3.height,
|
|
54319
|
+
style: {}
|
|
54320
|
+
};
|
|
54321
|
+
};
|
|
54322
|
+
const start = srcSg ? this.clusterAnchor(srcSg, rankdir, "out") : this.nodeAnchor(getNode(edge.source), rankdir, "out");
|
|
54323
|
+
const end = dstSg ? this.clusterAnchor(dstSg, rankdir, "in") : this.nodeAnchor(getNode(edge.target), rankdir, "in");
|
|
54324
|
+
if (start && end) {
|
|
54325
|
+
const PAD = 20;
|
|
54326
|
+
const horizontallyAdjacent = srcSg && dstSg && Math.abs(srcSg.x - dstSg.x) > Math.abs(srcSg.y - dstSg.y);
|
|
54327
|
+
const horizontalSubgraphs = horizontallyAdjacent;
|
|
54328
|
+
if (rankdir === "LR" || rankdir === "RL") {
|
|
54329
|
+
const outX = start.x + (rankdir === "LR" ? PAD : -PAD);
|
|
54330
|
+
const inX = end.x + (rankdir === "LR" ? -PAD : PAD);
|
|
54331
|
+
const startOut = { x: srcSg ? outX : start.x, y: start.y };
|
|
54332
|
+
const endPre = { x: dstSg ? inX : end.x, y: end.y };
|
|
54333
|
+
const alpha = 0.68;
|
|
54334
|
+
const midX = startOut.x + (endPre.x - startOut.x) * alpha;
|
|
54335
|
+
const m1 = { x: midX, y: startOut.y };
|
|
54336
|
+
const m22 = { x: midX, y: endPre.y };
|
|
54337
|
+
pts = dstSg ? [start, startOut, m1, m22, endPre] : [start, startOut, m1, m22, endPre, end];
|
|
54338
|
+
} else {
|
|
54339
|
+
if (horizontalSubgraphs && srcSg && dstSg) {
|
|
54340
|
+
const midY = (srcSg.y + srcSg.height / 2 + dstSg.y + dstSg.height / 2) / 2;
|
|
54341
|
+
if (srcSg.x < dstSg.x) {
|
|
54342
|
+
const startX = srcSg.x + srcSg.width;
|
|
54343
|
+
const endX = dstSg.x;
|
|
54344
|
+
pts = [{ x: startX, y: midY }, { x: endX, y: midY }];
|
|
54345
|
+
} else {
|
|
54346
|
+
const startX = srcSg.x;
|
|
54347
|
+
const endX = dstSg.x + dstSg.width;
|
|
54348
|
+
pts = [{ x: startX, y: midY }, { x: endX, y: midY }];
|
|
54349
|
+
}
|
|
54350
|
+
} else {
|
|
54351
|
+
const outY = start.y + (rankdir === "TD" ? PAD : -PAD);
|
|
54352
|
+
const inY = end.y + (rankdir === "TD" ? -PAD : PAD);
|
|
54353
|
+
const startOut = { x: start.x, y: srcSg ? outY : start.y };
|
|
54354
|
+
const endPre = { x: end.x, y: dstSg ? inY : end.y };
|
|
54355
|
+
const alpha = 0.68;
|
|
54356
|
+
const midY = startOut.y + (endPre.y - startOut.y) * alpha;
|
|
54357
|
+
const m1 = { x: startOut.x, y: midY };
|
|
54358
|
+
const m22 = { x: endPre.x, y: midY };
|
|
54359
|
+
pts = dstSg ? [start, startOut, m1, m22, endPre] : [start, startOut, m1, m22, endPre, end];
|
|
54360
|
+
}
|
|
54361
|
+
}
|
|
54362
|
+
synthesized = true;
|
|
54363
|
+
}
|
|
54364
|
+
}
|
|
54365
|
+
if (pts.length) {
|
|
54366
|
+
layoutEdges.push({ ...edge, points: pts, pathMode: synthesized ? "orthogonal" : "smooth" });
|
|
54367
|
+
}
|
|
54368
|
+
}
|
|
54369
|
+
const rawW = graphInfo.width;
|
|
54370
|
+
const rawH = graphInfo.height;
|
|
54371
|
+
const w3 = Number.isFinite(rawW) && rawW > 0 ? rawW : 800;
|
|
54372
|
+
const h3 = Number.isFinite(rawH) && rawH > 0 ? rawH : 600;
|
|
54373
|
+
return {
|
|
54374
|
+
nodes: layoutNodes,
|
|
54375
|
+
edges: layoutEdges,
|
|
54376
|
+
width: w3,
|
|
54377
|
+
height: h3,
|
|
54378
|
+
subgraphs: layoutSubgraphs
|
|
54379
|
+
};
|
|
54380
|
+
}
|
|
54381
|
+
mapDirection(direction) {
|
|
54382
|
+
switch (direction) {
|
|
54383
|
+
case "TB":
|
|
54384
|
+
case "TD":
|
|
54385
|
+
return "TB";
|
|
54386
|
+
case "BT":
|
|
54387
|
+
return "BT";
|
|
54388
|
+
case "LR":
|
|
54389
|
+
return "LR";
|
|
54390
|
+
case "RL":
|
|
54391
|
+
return "RL";
|
|
54392
|
+
default:
|
|
54393
|
+
return "TB";
|
|
54394
|
+
}
|
|
54395
|
+
}
|
|
54396
|
+
calculateNodeDimensions(label, shape) {
|
|
54397
|
+
const charWidth = 7;
|
|
54398
|
+
const padding = 20;
|
|
54399
|
+
const minWidth = 80;
|
|
54400
|
+
const minHeight = 40;
|
|
54401
|
+
const maxWidth = 240;
|
|
54402
|
+
const lineHeight = 18;
|
|
54403
|
+
const explicitLines = label.split(/<\s*br\s*\/?\s*>/i);
|
|
54404
|
+
const hasExplicitBreaks = explicitLines.length > 1;
|
|
54405
|
+
let width;
|
|
54406
|
+
let lines;
|
|
54407
|
+
if (hasExplicitBreaks) {
|
|
54408
|
+
const maxLineLength = Math.max(...explicitLines.map((line) => line.length));
|
|
54409
|
+
width = Math.min(Math.max(maxLineLength * charWidth + padding * 2, minWidth), maxWidth);
|
|
54410
|
+
lines = explicitLines.length;
|
|
54411
|
+
} else {
|
|
54412
|
+
width = Math.min(Math.max(label.length * charWidth + padding * 2, minWidth), maxWidth);
|
|
54413
|
+
const charsPerLine = Math.max(1, Math.floor((width - padding * 2) / charWidth));
|
|
54414
|
+
lines = Math.ceil(label.length / charsPerLine);
|
|
54415
|
+
}
|
|
54416
|
+
let height = Math.max(lines * lineHeight + padding, minHeight);
|
|
54417
|
+
switch (shape) {
|
|
54418
|
+
case "circle":
|
|
54419
|
+
const size = Math.max(width, height);
|
|
54420
|
+
width = size;
|
|
54421
|
+
height = size;
|
|
54422
|
+
break;
|
|
54423
|
+
case "diamond": {
|
|
54424
|
+
const size2 = Math.max(width, height) * 1.2;
|
|
54425
|
+
width = size2;
|
|
54426
|
+
height = size2;
|
|
54427
|
+
break;
|
|
54428
|
+
}
|
|
54429
|
+
case "hexagon":
|
|
54430
|
+
width *= 1.3;
|
|
54431
|
+
height *= 1.2;
|
|
54432
|
+
break;
|
|
54433
|
+
case "stadium":
|
|
54434
|
+
width *= 1.2;
|
|
54435
|
+
break;
|
|
54436
|
+
case "cylinder":
|
|
54437
|
+
height *= 1.5;
|
|
54438
|
+
break;
|
|
54439
|
+
case "subroutine":
|
|
54440
|
+
case "double":
|
|
54441
|
+
width += 10;
|
|
54442
|
+
height += 10;
|
|
54443
|
+
break;
|
|
54444
|
+
case "parallelogram":
|
|
54445
|
+
case "trapezoid":
|
|
54446
|
+
width *= 1.3;
|
|
54447
|
+
break;
|
|
54448
|
+
}
|
|
54449
|
+
return { width: Math.round(width), height: Math.round(height) };
|
|
54450
|
+
}
|
|
54451
|
+
clusterAnchor(sg, rankdir, mode) {
|
|
54452
|
+
switch (rankdir) {
|
|
54453
|
+
case "LR":
|
|
54454
|
+
return { x: mode === "out" ? sg.x + sg.width : sg.x, y: sg.y + sg.height / 2 };
|
|
54455
|
+
case "RL":
|
|
54456
|
+
return { x: mode === "out" ? sg.x : sg.x + sg.width, y: sg.y + sg.height / 2 };
|
|
54457
|
+
case "BT":
|
|
54458
|
+
return { x: sg.x + sg.width / 2, y: mode === "out" ? sg.y : sg.y + sg.height };
|
|
54459
|
+
case "TB":
|
|
54460
|
+
default:
|
|
54461
|
+
return { x: sg.x + sg.width / 2, y: mode === "out" ? sg.y + sg.height : sg.y };
|
|
54462
|
+
}
|
|
54463
|
+
}
|
|
54464
|
+
nodeAnchor(n3, rankdir, mode) {
|
|
54465
|
+
if (!n3)
|
|
54466
|
+
return { x: 0, y: 0 };
|
|
54467
|
+
switch (rankdir) {
|
|
54468
|
+
case "LR":
|
|
54469
|
+
return { x: mode === "in" ? n3.x : n3.x + n3.width, y: n3.y + n3.height / 2 };
|
|
54470
|
+
case "RL":
|
|
54471
|
+
return { x: mode === "in" ? n3.x + n3.width : n3.x, y: n3.y + n3.height / 2 };
|
|
54472
|
+
case "BT":
|
|
54473
|
+
return { x: n3.x + n3.width / 2, y: mode === "in" ? n3.y + n3.height : n3.y };
|
|
54474
|
+
case "TB":
|
|
54475
|
+
default:
|
|
54476
|
+
return { x: n3.x + n3.width / 2, y: mode === "in" ? n3.y : n3.y + n3.height };
|
|
54477
|
+
}
|
|
54478
|
+
}
|
|
54479
|
+
};
|
|
54480
|
+
}
|
|
54481
|
+
});
|
|
54482
|
+
|
|
54483
|
+
// node_modules/@probelabs/maid/out/renderer/arrow-utils.js
|
|
54484
|
+
function triangleAtEnd(start, end, color = "#333", length = 8, width = 6) {
|
|
54485
|
+
const vx = end.x - start.x;
|
|
54486
|
+
const vy = end.y - start.y;
|
|
54487
|
+
const len = Math.hypot(vx, vy) || 1;
|
|
54488
|
+
const ux = vx / len;
|
|
54489
|
+
const uy = vy / len;
|
|
54490
|
+
const nx = -uy;
|
|
54491
|
+
const ny = ux;
|
|
54492
|
+
const baseX = end.x - ux * length;
|
|
54493
|
+
const baseY = end.y - uy * length;
|
|
54494
|
+
const p2x = baseX + nx * (width / 2), p2y = baseY + ny * (width / 2);
|
|
54495
|
+
const p3x = baseX - nx * (width / 2), p3y = baseY - ny * (width / 2);
|
|
54496
|
+
return `<path d="M${end.x},${end.y} L${p2x},${p2y} L${p3x},${p3y} Z" fill="${color}" />`;
|
|
54497
|
+
}
|
|
54498
|
+
function triangleAtStart(first2, second, color = "#333", length = 8, width = 6) {
|
|
54499
|
+
const vx = second.x - first2.x;
|
|
54500
|
+
const vy = second.y - first2.y;
|
|
54501
|
+
const len = Math.hypot(vx, vy) || 1;
|
|
54502
|
+
const ux = vx / len;
|
|
54503
|
+
const uy = vy / len;
|
|
54504
|
+
const nx = -uy;
|
|
54505
|
+
const ny = ux;
|
|
54506
|
+
const tipX = first2.x - ux * length;
|
|
54507
|
+
const tipY = first2.y - uy * length;
|
|
54508
|
+
const p2x = first2.x + nx * (width / 2), p2y = first2.y + ny * (width / 2);
|
|
54509
|
+
const p3x = first2.x - nx * (width / 2), p3y = first2.y - ny * (width / 2);
|
|
54510
|
+
return `<path d="M${tipX},${tipY} L${p2x},${p2y} L${p3x},${p3y} Z" fill="${color}" />`;
|
|
54511
|
+
}
|
|
54512
|
+
var init_arrow_utils = __esm({
|
|
54513
|
+
"node_modules/@probelabs/maid/out/renderer/arrow-utils.js"() {
|
|
54514
|
+
}
|
|
54515
|
+
});
|
|
54516
|
+
|
|
54517
|
+
// node_modules/@probelabs/maid/out/renderer/styles.js
|
|
54518
|
+
function buildSharedCss(opts = {}) {
|
|
54519
|
+
const fontFamily = opts.fontFamily || "Arial, sans-serif";
|
|
54520
|
+
const fontSize = opts.fontSize ?? 14;
|
|
54521
|
+
const nodeFill = opts.nodeFill || "#eef0ff";
|
|
54522
|
+
const nodeStroke = opts.nodeStroke || "#3f3f3f";
|
|
54523
|
+
const edgeStroke = opts.edgeStroke || "#555555";
|
|
54524
|
+
return `
|
|
54525
|
+
.node-shape { fill: ${nodeFill}; stroke: ${nodeStroke}; stroke-width: 1px; }
|
|
54526
|
+
.node-label { fill: #333; font-family: ${fontFamily}; font-size: ${fontSize}px; }
|
|
54527
|
+
.edge-path { stroke: ${edgeStroke}; stroke-width: 2px; fill: none; }
|
|
54528
|
+
.edge-label-bg { fill: rgba(232,232,232, 0.8); opacity: 0.5; }
|
|
54529
|
+
.edge-label-text { fill: #333; font-family: ${fontFamily}; font-size: ${Math.max(10, fontSize - 2)}px; }
|
|
54530
|
+
|
|
54531
|
+
/* Cluster (flowchart + sequence blocks) */
|
|
54532
|
+
.cluster-bg { fill: #ffffde; }
|
|
54533
|
+
.cluster-border { fill: none; stroke: #aaaa33; stroke-width: 1px; }
|
|
54534
|
+
.cluster-title-bg { fill: rgba(255,255,255,0.8); }
|
|
54535
|
+
.cluster-label-text { fill: #333; font-family: ${fontFamily}; font-size: 12px; }
|
|
54536
|
+
|
|
54537
|
+
/* Notes */
|
|
54538
|
+
.note { fill: #fff5ad; stroke: #aaaa33; stroke-width: 1px; }
|
|
54539
|
+
.note-text { fill: #333; font-family: ${fontFamily}; font-size: 12px; }
|
|
54540
|
+
|
|
54541
|
+
/* Sequence-specific add-ons (safe for flowcharts too) */
|
|
54542
|
+
.actor-rect { fill: #eaeaea; stroke: #666; stroke-width: 1.5px; }
|
|
54543
|
+
.actor-label { fill: #111; font-family: ${fontFamily}; font-size: 16px; }
|
|
54544
|
+
.lifeline { stroke: #999; stroke-width: 0.5px; }
|
|
54545
|
+
.activation { fill: #f4f4f4; stroke: #666; stroke-width: 1px; }
|
|
54546
|
+
.msg-line { stroke: #333; stroke-width: 1.5px; fill: none; }
|
|
54547
|
+
.msg-line.dotted { stroke-dasharray: 2 2; }
|
|
54548
|
+
.msg-line.thick { stroke-width: 3px; }
|
|
54549
|
+
.msg-label { fill: #333; font-family: ${fontFamily}; font-size: 12px; dominant-baseline: middle; }
|
|
54550
|
+
.msg-label-bg { fill: #ffffff; stroke: #cccccc; stroke-width: 1px; rx: 3; }
|
|
54551
|
+
`;
|
|
54552
|
+
}
|
|
54553
|
+
var init_styles = __esm({
|
|
54554
|
+
"node_modules/@probelabs/maid/out/renderer/styles.js"() {
|
|
54555
|
+
}
|
|
54556
|
+
});
|
|
54557
|
+
|
|
54558
|
+
// node_modules/@probelabs/maid/out/renderer/utils.js
|
|
54559
|
+
function escapeXml(text) {
|
|
54560
|
+
return String(text).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
54561
|
+
}
|
|
54562
|
+
function measureText(text, fontSize = 12) {
|
|
54563
|
+
const avg = 0.6 * fontSize;
|
|
54564
|
+
return Math.max(0, Math.round(text.length * avg));
|
|
54565
|
+
}
|
|
54566
|
+
function palette(index) {
|
|
54567
|
+
if (index < DEFAULT_PALETTE.length)
|
|
54568
|
+
return DEFAULT_PALETTE[index];
|
|
54569
|
+
const i3 = index - DEFAULT_PALETTE.length;
|
|
54570
|
+
const hue = i3 * 47 % 360;
|
|
54571
|
+
return `hsl(${hue} 60% 55%)`;
|
|
54572
|
+
}
|
|
54573
|
+
function formatNumber(n3) {
|
|
54574
|
+
if (Number.isInteger(n3))
|
|
54575
|
+
return String(n3);
|
|
54576
|
+
return (Math.round(n3 * 100) / 100).toString();
|
|
54577
|
+
}
|
|
54578
|
+
function formatPercent(value, total) {
|
|
54579
|
+
if (!(total > 0))
|
|
54580
|
+
return "0%";
|
|
54581
|
+
const p3 = value / total * 100;
|
|
54582
|
+
return `${Math.round(p3)}%`;
|
|
54583
|
+
}
|
|
54584
|
+
var DEFAULT_PALETTE;
|
|
54585
|
+
var init_utils4 = __esm({
|
|
54586
|
+
"node_modules/@probelabs/maid/out/renderer/utils.js"() {
|
|
54587
|
+
DEFAULT_PALETTE = [
|
|
54588
|
+
"#ECECFF",
|
|
54589
|
+
"#ffffde",
|
|
54590
|
+
"hsl(80, 100%, 56.2745098039%)",
|
|
54591
|
+
"hsl(240, 100%, 86.2745098039%)",
|
|
54592
|
+
"hsl(60, 100%, 63.5294117647%)",
|
|
54593
|
+
"hsl(80, 100%, 76.2745098039%)",
|
|
54594
|
+
"hsl(300, 100%, 76.2745098039%)",
|
|
54595
|
+
"hsl(180, 100%, 56.2745098039%)",
|
|
54596
|
+
"hsl(0, 100%, 56.2745098039%)",
|
|
54597
|
+
"hsl(300, 100%, 56.2745098039%)",
|
|
54598
|
+
"hsl(150, 100%, 56.2745098039%)",
|
|
54599
|
+
"hsl(0, 100%, 66.2745098039%)"
|
|
54600
|
+
];
|
|
54601
|
+
}
|
|
54602
|
+
});
|
|
54603
|
+
|
|
54604
|
+
// node_modules/@probelabs/maid/out/renderer/block-utils.js
|
|
54605
|
+
function blockBackground(x3, y2, width, height, radius = 0) {
|
|
54606
|
+
return `<g class="cluster-bg-layer" transform="translate(${x3},${y2})">
|
|
54607
|
+
<rect class="cluster-bg" x="0" y="0" width="${width}" height="${height}" rx="${radius}"/>
|
|
54608
|
+
</g>`;
|
|
54609
|
+
}
|
|
54610
|
+
function blockOverlay(x3, y2, width, height, title, branchYs = [], titleYOffset = 0, align = "center", branchAlign = "left", radius = 0) {
|
|
54611
|
+
const parts = [];
|
|
54612
|
+
parts.push(`<g class="cluster-overlay" transform="translate(${x3},${y2})">`);
|
|
54613
|
+
parts.push(`<rect class="cluster-border" x="0" y="0" width="${width}" height="${height}" rx="${radius}"/>`);
|
|
54614
|
+
const titleText = title ? escapeXml(title) : "";
|
|
54615
|
+
if (titleText) {
|
|
54616
|
+
const titleW = Math.max(24, measureText(titleText, 12) + 10);
|
|
54617
|
+
const yBg = -2 + titleYOffset;
|
|
54618
|
+
const yText = 11 + titleYOffset;
|
|
54619
|
+
if (align === "left") {
|
|
54620
|
+
const xBg = 6;
|
|
54621
|
+
parts.push(`<rect class="cluster-title-bg" x="${xBg}" y="${yBg}" width="${titleW}" height="18" rx="3"/>`);
|
|
54622
|
+
parts.push(`<text class="cluster-label-text" x="${xBg + 6}" y="${yText}" text-anchor="start">${titleText}</text>`);
|
|
54623
|
+
} else {
|
|
54624
|
+
const xBg = 6;
|
|
54625
|
+
parts.push(`<rect class="cluster-title-bg" x="${xBg}" y="${yBg}" width="${titleW}" height="18" rx="3"/>`);
|
|
54626
|
+
parts.push(`<text class="cluster-label-text" x="${xBg + titleW / 2}" y="${yText}" text-anchor="middle">${titleText}</text>`);
|
|
54627
|
+
}
|
|
54628
|
+
}
|
|
54629
|
+
for (const br of branchYs) {
|
|
54630
|
+
const yRel = br.y - y2;
|
|
54631
|
+
parts.push(`<line x1="0" y1="${yRel}" x2="${width}" y2="${yRel}" class="cluster-border" />`);
|
|
54632
|
+
if (br.title) {
|
|
54633
|
+
const text = escapeXml(br.title);
|
|
54634
|
+
const bw = Math.max(24, measureText(text, 12) + 10);
|
|
54635
|
+
const xBg = 6;
|
|
54636
|
+
parts.push(`<rect class="cluster-title-bg" x="${xBg}" y="${yRel - 10}" width="${bw}" height="18" rx="3"/>`);
|
|
54637
|
+
if (branchAlign === "left") {
|
|
54638
|
+
parts.push(`<text class="cluster-label-text" x="${xBg + 6}" y="${yRel + 1}" text-anchor="start">${text}</text>`);
|
|
54639
|
+
} else {
|
|
54640
|
+
parts.push(`<text class="cluster-label-text" x="${xBg + bw / 2}" y="${yRel + 1}" text-anchor="middle">${text}</text>`);
|
|
54641
|
+
}
|
|
54642
|
+
}
|
|
54643
|
+
}
|
|
54644
|
+
parts.push("</g>");
|
|
54645
|
+
return parts.join("\n");
|
|
54646
|
+
}
|
|
54647
|
+
var init_block_utils = __esm({
|
|
54648
|
+
"node_modules/@probelabs/maid/out/renderer/block-utils.js"() {
|
|
54649
|
+
init_utils4();
|
|
54650
|
+
}
|
|
54651
|
+
});
|
|
54652
|
+
|
|
54653
|
+
// node_modules/@probelabs/maid/out/renderer/svg-generator.js
|
|
54654
|
+
var SVGRenderer;
|
|
54655
|
+
var init_svg_generator = __esm({
|
|
54656
|
+
"node_modules/@probelabs/maid/out/renderer/svg-generator.js"() {
|
|
54657
|
+
init_arrow_utils();
|
|
54658
|
+
init_styles();
|
|
54659
|
+
init_block_utils();
|
|
54660
|
+
SVGRenderer = class {
|
|
54661
|
+
constructor() {
|
|
54662
|
+
this.padding = 20;
|
|
54663
|
+
this.fontSize = 14;
|
|
54664
|
+
this.fontFamily = "Arial, sans-serif";
|
|
54665
|
+
this.defaultStroke = "#3f3f3f";
|
|
54666
|
+
this.defaultFill = "#eef0ff";
|
|
54667
|
+
this.arrowStroke = "#555555";
|
|
54668
|
+
this.arrowMarkerSize = 9;
|
|
54669
|
+
}
|
|
54670
|
+
render(layout) {
|
|
54671
|
+
let minX = Infinity;
|
|
54672
|
+
let minY = Infinity;
|
|
54673
|
+
let maxX = -Infinity;
|
|
54674
|
+
let maxY = -Infinity;
|
|
54675
|
+
for (const n3 of layout.nodes) {
|
|
54676
|
+
minX = Math.min(minX, n3.x);
|
|
54677
|
+
minY = Math.min(minY, n3.y);
|
|
54678
|
+
maxX = Math.max(maxX, n3.x + n3.width);
|
|
54679
|
+
maxY = Math.max(maxY, n3.y + n3.height);
|
|
54680
|
+
}
|
|
54681
|
+
if (layout.subgraphs) {
|
|
54682
|
+
for (const sg of layout.subgraphs) {
|
|
54683
|
+
minX = Math.min(minX, sg.x);
|
|
54684
|
+
minY = Math.min(minY, sg.y);
|
|
54685
|
+
maxX = Math.max(maxX, sg.x + sg.width);
|
|
54686
|
+
maxY = Math.max(maxY, sg.y + sg.height);
|
|
54687
|
+
}
|
|
54688
|
+
}
|
|
54689
|
+
for (const e3 of layout.edges) {
|
|
54690
|
+
if (e3.points)
|
|
54691
|
+
for (const p3 of e3.points) {
|
|
54692
|
+
minX = Math.min(minX, p3.x);
|
|
54693
|
+
minY = Math.min(minY, p3.y);
|
|
54694
|
+
maxX = Math.max(maxX, p3.x);
|
|
54695
|
+
maxY = Math.max(maxY, p3.y);
|
|
54696
|
+
}
|
|
54697
|
+
}
|
|
54698
|
+
if (!isFinite(minX)) {
|
|
54699
|
+
minX = 0;
|
|
54700
|
+
}
|
|
54701
|
+
if (!isFinite(minY)) {
|
|
54702
|
+
minY = 0;
|
|
54703
|
+
}
|
|
54704
|
+
if (!isFinite(maxX)) {
|
|
54705
|
+
maxX = layout.width;
|
|
54706
|
+
}
|
|
54707
|
+
if (!isFinite(maxY)) {
|
|
54708
|
+
maxY = layout.height;
|
|
54709
|
+
}
|
|
54710
|
+
const extraPadX = Math.max(0, -Math.floor(minX) + 1);
|
|
54711
|
+
const extraPadY = Math.max(0, -Math.floor(minY) + 1);
|
|
54712
|
+
const padX = this.padding + extraPadX;
|
|
54713
|
+
const padY = this.padding + extraPadY;
|
|
54714
|
+
const bboxWidth = Math.ceil(maxX) - Math.min(0, Math.floor(minX));
|
|
54715
|
+
const bboxHeight = Math.ceil(maxY) - Math.min(0, Math.floor(minY));
|
|
54716
|
+
const width = bboxWidth + this.padding * 2 + extraPadX;
|
|
54717
|
+
const height = bboxHeight + this.padding * 2 + extraPadY;
|
|
54718
|
+
const elements = [];
|
|
54719
|
+
const overlays = [];
|
|
54720
|
+
elements.push(this.generateDefs());
|
|
54721
|
+
if (layout.subgraphs && layout.subgraphs.length) {
|
|
54722
|
+
const sgs = layout.subgraphs;
|
|
54723
|
+
const order = sgs.slice().sort((a3, b3) => (a3.parent ? 1 : 0) - (b3.parent ? 1 : 0));
|
|
54724
|
+
const map4 = new Map(order.map((o3) => [o3.id, o3]));
|
|
54725
|
+
const depthOf = (sg) => {
|
|
54726
|
+
let d3 = 0;
|
|
54727
|
+
let p3 = sg.parent;
|
|
54728
|
+
while (p3) {
|
|
54729
|
+
d3++;
|
|
54730
|
+
p3 = map4.get(p3)?.parent;
|
|
54731
|
+
}
|
|
54732
|
+
return d3;
|
|
54733
|
+
};
|
|
54734
|
+
const bgs = [];
|
|
54735
|
+
for (const sg of order) {
|
|
54736
|
+
const x3 = sg.x + padX;
|
|
54737
|
+
const y2 = sg.y + padY;
|
|
54738
|
+
bgs.push(blockBackground(x3, y2, sg.width, sg.height, 0));
|
|
54739
|
+
const depth = depthOf(sg);
|
|
54740
|
+
const title = sg.label ? this.escapeXml(sg.label) : void 0;
|
|
54741
|
+
const titleYOffset = 7 + depth * 12;
|
|
54742
|
+
overlays.push(blockOverlay(x3, y2, sg.width, sg.height, title, [], titleYOffset, "center", "left", 0));
|
|
54743
|
+
}
|
|
54744
|
+
elements.push(`<g class="subgraph-bg">${bgs.join("")}</g>`);
|
|
54745
|
+
}
|
|
54746
|
+
const nodeMap = {};
|
|
54747
|
+
for (const n3 of layout.nodes) {
|
|
54748
|
+
nodeMap[n3.id] = { x: n3.x + padX, y: n3.y + padY, width: n3.width, height: n3.height, shape: n3.shape };
|
|
54749
|
+
}
|
|
54750
|
+
if (layout.subgraphs && layout.subgraphs.length) {
|
|
54751
|
+
for (const sg of layout.subgraphs) {
|
|
54752
|
+
nodeMap[sg.id] = { x: sg.x + padX, y: sg.y + padY, width: sg.width, height: sg.height, shape: "rectangle" };
|
|
54753
|
+
}
|
|
54754
|
+
}
|
|
54755
|
+
for (const node of layout.nodes) {
|
|
54756
|
+
elements.push(this.generateNodeWithPad(node, padX, padY));
|
|
54757
|
+
}
|
|
54758
|
+
for (const edge of layout.edges) {
|
|
54759
|
+
const { path: path6, overlay } = this.generateEdge(edge, padX, padY, nodeMap);
|
|
54760
|
+
elements.push(path6);
|
|
54761
|
+
if (overlay)
|
|
54762
|
+
overlays.push(overlay);
|
|
54763
|
+
}
|
|
54764
|
+
const bg = `<rect x="0" y="0" width="${width}" height="${height}" fill="#ffffff" />`;
|
|
54765
|
+
const sharedCss = buildSharedCss({
|
|
54766
|
+
fontFamily: this.fontFamily,
|
|
54767
|
+
fontSize: this.fontSize,
|
|
54768
|
+
nodeFill: this.defaultFill,
|
|
54769
|
+
nodeStroke: this.defaultStroke,
|
|
54770
|
+
edgeStroke: this.arrowStroke
|
|
54771
|
+
});
|
|
54772
|
+
const css = `<style>${sharedCss}</style>`;
|
|
54773
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
|
54774
|
+
${bg}
|
|
54775
|
+
${css}
|
|
54776
|
+
${elements.join("\n ")}
|
|
54777
|
+
${overlays.join("\n ")}
|
|
54778
|
+
</svg>`;
|
|
54779
|
+
}
|
|
54780
|
+
buildNodeStyleAttrs(style) {
|
|
54781
|
+
const decs = [];
|
|
54782
|
+
if (style.fill)
|
|
54783
|
+
decs.push(`fill:${style.fill}`);
|
|
54784
|
+
if (style.stroke)
|
|
54785
|
+
decs.push(`stroke:${style.stroke}`);
|
|
54786
|
+
if (style.strokeWidth != null)
|
|
54787
|
+
decs.push(`stroke-width:${style.strokeWidth}`);
|
|
54788
|
+
return decs.length ? `style="${decs.join(";")}"` : "";
|
|
54789
|
+
}
|
|
54790
|
+
buildNodeStrokeStyle(style) {
|
|
54791
|
+
const decs = [];
|
|
54792
|
+
if (style.stroke)
|
|
54793
|
+
decs.push(`stroke:${style.stroke}`);
|
|
54794
|
+
if (style.strokeWidth != null)
|
|
54795
|
+
decs.push(`stroke-width:${style.strokeWidth}`);
|
|
54796
|
+
return decs.length ? `style="${decs.join(";")}"` : "";
|
|
54797
|
+
}
|
|
54798
|
+
generateDefs() {
|
|
54799
|
+
const aw = Math.max(8, this.arrowMarkerSize + 2);
|
|
54800
|
+
const ah = Math.max(8, this.arrowMarkerSize + 2);
|
|
54801
|
+
const arefX = Math.max(6, aw);
|
|
54802
|
+
const arefY = Math.max(4, Math.round(ah / 2));
|
|
54803
|
+
return `<defs>
|
|
54804
|
+
<marker id="arrow" viewBox="0 0 ${aw} ${ah}" markerWidth="${aw}" markerHeight="${ah}" refX="${arefX}" refY="${arefY}" orient="auto" markerUnits="userSpaceOnUse">
|
|
54805
|
+
<path d="M0,0 L0,${ah} L${aw},${arefY} z" fill="${this.arrowStroke}" />
|
|
54806
|
+
</marker>
|
|
54807
|
+
<marker id="circle-marker" viewBox="0 0 9 9" markerWidth="9" markerHeight="9" refX="4.5" refY="4.5" orient="auto" markerUnits="userSpaceOnUse">
|
|
54808
|
+
<circle cx="4.5" cy="4.5" r="4.5" fill="${this.arrowStroke}" />
|
|
54809
|
+
</marker>
|
|
54810
|
+
<marker id="cross-marker" viewBox="0 0 12 12" markerWidth="12" markerHeight="12" refX="6" refY="6" orient="auto" markerUnits="userSpaceOnUse">
|
|
54811
|
+
<path d="M1.5,1.5 L10.5,10.5 M10.5,1.5 L1.5,10.5" stroke="${this.arrowStroke}" stroke-width="2.25" />
|
|
54812
|
+
</marker>
|
|
54813
|
+
</defs>`;
|
|
54814
|
+
}
|
|
54815
|
+
generateNodeWithPad(node, padX, padY) {
|
|
54816
|
+
const x3 = node.x + padX;
|
|
54817
|
+
const y2 = node.y + padY;
|
|
54818
|
+
const cx = x3 + node.width / 2;
|
|
54819
|
+
const cy = y2 + node.height / 2;
|
|
54820
|
+
let shape = "";
|
|
54821
|
+
let labelCenterY = cy;
|
|
54822
|
+
const strokeWidth = node.style?.strokeWidth ?? void 0;
|
|
54823
|
+
const stroke = node.style?.stroke ?? void 0;
|
|
54824
|
+
const fill = node.style?.fill ?? void 0;
|
|
54825
|
+
const styleAttr = this.buildNodeStyleAttrs({ stroke, strokeWidth, fill });
|
|
54826
|
+
switch (node.shape) {
|
|
54827
|
+
case "rectangle":
|
|
54828
|
+
shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="0" ry="0" />`;
|
|
54829
|
+
break;
|
|
54830
|
+
case "round":
|
|
54831
|
+
shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="5" ry="5" />`;
|
|
54832
|
+
break;
|
|
54833
|
+
case "stadium":
|
|
54834
|
+
const radius = node.height / 2;
|
|
54835
|
+
shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="${radius}" ry="${radius}" />`;
|
|
54836
|
+
break;
|
|
54837
|
+
case "circle":
|
|
54838
|
+
const r3 = Math.min(node.width, node.height) / 2;
|
|
54839
|
+
shape = `<circle class="node-shape" ${styleAttr} cx="${cx}" cy="${cy}" r="${r3}" />`;
|
|
54840
|
+
break;
|
|
54841
|
+
case "diamond": {
|
|
54842
|
+
const points = [
|
|
54843
|
+
`${cx},${y2}`,
|
|
54844
|
+
// top
|
|
54845
|
+
`${x3 + node.width},${cy}`,
|
|
54846
|
+
// right
|
|
54847
|
+
`${cx},${y2 + node.height}`,
|
|
54848
|
+
// bottom
|
|
54849
|
+
`${x3},${cy}`
|
|
54850
|
+
// left
|
|
54851
|
+
].join(" ");
|
|
54852
|
+
shape = `<polygon class="node-shape" ${styleAttr} points="${points}" />`;
|
|
54853
|
+
break;
|
|
54854
|
+
}
|
|
54855
|
+
case "hexagon": {
|
|
54856
|
+
const dx = node.width * 0.25;
|
|
54857
|
+
const points = [
|
|
54858
|
+
`${x3 + dx},${y2}`,
|
|
54859
|
+
// top-left
|
|
54860
|
+
`${x3 + node.width - dx},${y2}`,
|
|
54861
|
+
// top-right
|
|
54862
|
+
`${x3 + node.width},${cy}`,
|
|
54863
|
+
// right
|
|
54864
|
+
`${x3 + node.width - dx},${y2 + node.height}`,
|
|
54865
|
+
// bottom-right
|
|
54866
|
+
`${x3 + dx},${y2 + node.height}`,
|
|
54867
|
+
// bottom-left
|
|
54868
|
+
`${x3},${cy}`
|
|
54869
|
+
// left
|
|
54870
|
+
].join(" ");
|
|
54871
|
+
shape = `<polygon class="node-shape" ${styleAttr} points="${points}" />`;
|
|
54872
|
+
break;
|
|
54873
|
+
}
|
|
54874
|
+
case "parallelogram": {
|
|
54875
|
+
const skew = node.width * 0.15;
|
|
54876
|
+
const points = [
|
|
54877
|
+
`${x3 + skew},${y2}`,
|
|
54878
|
+
// top-left
|
|
54879
|
+
`${x3 + node.width},${y2}`,
|
|
54880
|
+
// top-right
|
|
54881
|
+
`${x3 + node.width - skew},${y2 + node.height}`,
|
|
54882
|
+
// bottom-right
|
|
54883
|
+
`${x3},${y2 + node.height}`
|
|
54884
|
+
// bottom-left
|
|
54885
|
+
].join(" ");
|
|
54886
|
+
shape = `<polygon class="node-shape" ${styleAttr} points="${points}" />`;
|
|
54887
|
+
break;
|
|
54888
|
+
}
|
|
54889
|
+
case "trapezoid": {
|
|
54890
|
+
const inset = node.width * 0.15;
|
|
54891
|
+
const points = [
|
|
54892
|
+
`${x3 + inset},${y2}`,
|
|
54893
|
+
// top-left
|
|
54894
|
+
`${x3 + node.width - inset},${y2}`,
|
|
54895
|
+
// top-right
|
|
54896
|
+
`${x3 + node.width},${y2 + node.height}`,
|
|
54897
|
+
// bottom-right
|
|
54898
|
+
`${x3},${y2 + node.height}`
|
|
54899
|
+
// bottom-left
|
|
54900
|
+
].join(" ");
|
|
54901
|
+
shape = `<polygon class="node-shape" ${styleAttr} points="${points}" />`;
|
|
54902
|
+
break;
|
|
54903
|
+
}
|
|
54904
|
+
case "trapezoidAlt": {
|
|
54905
|
+
const inset = node.width * 0.15;
|
|
54906
|
+
const points = [
|
|
54907
|
+
`${x3},${y2}`,
|
|
54908
|
+
// top-left (full width)
|
|
54909
|
+
`${x3 + node.width},${y2}`,
|
|
54910
|
+
// top-right
|
|
54911
|
+
`${x3 + node.width - inset},${y2 + node.height}`,
|
|
54912
|
+
// bottom-right (narrow)
|
|
54913
|
+
`${x3 + inset},${y2 + node.height}`
|
|
54914
|
+
// bottom-left (narrow)
|
|
54915
|
+
].join(" ");
|
|
54916
|
+
shape = `<polygon class="node-shape" ${styleAttr} points="${points}" />`;
|
|
54917
|
+
break;
|
|
54918
|
+
}
|
|
54919
|
+
case "cylinder": {
|
|
54920
|
+
const rx = Math.max(8, node.width / 2);
|
|
54921
|
+
const ry = Math.max(6, Math.min(node.height * 0.22, node.width * 0.25));
|
|
54922
|
+
const topCY = y2 + ry;
|
|
54923
|
+
const botCY = y2 + node.height - ry;
|
|
54924
|
+
const bodyH = Math.max(0, node.height - ry * 2);
|
|
54925
|
+
const strokeOnly = this.buildNodeStrokeStyle({ stroke, strokeWidth });
|
|
54926
|
+
shape = `<g>
|
|
54927
|
+
<rect class="node-shape" ${styleAttr} x="${x3}" y="${topCY}" width="${node.width}" height="${bodyH}" />
|
|
54928
|
+
<ellipse class="node-shape" ${styleAttr} cx="${cx}" cy="${topCY}" rx="${node.width / 2}" ry="${ry}" />
|
|
54929
|
+
<path class="node-shape" ${strokeOnly} d="M${x3},${topCY} L${x3},${botCY} A${node.width / 2},${ry} 0 0,0 ${x3 + node.width},${botCY} L${x3 + node.width},${topCY}" fill="none" />
|
|
54930
|
+
</g>`;
|
|
54931
|
+
labelCenterY = topCY + bodyH / 2;
|
|
54932
|
+
break;
|
|
54933
|
+
}
|
|
54934
|
+
case "subroutine":
|
|
54935
|
+
const insetX = 5;
|
|
54936
|
+
const strokeOnly2 = this.buildNodeStrokeStyle({ stroke, strokeWidth });
|
|
54937
|
+
shape = `<g>
|
|
54938
|
+
<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="0" ry="0" />
|
|
54939
|
+
<line class="node-shape" ${strokeOnly2} x1="${x3 + insetX}" y1="${y2}" x2="${x3 + insetX}" y2="${y2 + node.height}" />
|
|
54940
|
+
<line class="node-shape" ${strokeOnly2} x1="${x3 + node.width - insetX}" y1="${y2}" x2="${x3 + node.width - insetX}" y2="${y2 + node.height}" />
|
|
54941
|
+
</g>`;
|
|
54942
|
+
break;
|
|
54943
|
+
case "double":
|
|
54944
|
+
const gap = 4;
|
|
54945
|
+
const strokeOnly3 = this.buildNodeStrokeStyle({ stroke, strokeWidth });
|
|
54946
|
+
shape = `<g>
|
|
54947
|
+
<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="0" ry="0" />
|
|
54948
|
+
<rect class="node-shape" ${strokeOnly3} x="${x3 + gap}" y="${y2 + gap}" width="${node.width - gap * 2}" height="${node.height - gap * 2}" rx="0" ry="0" fill="none" />
|
|
54949
|
+
</g>`;
|
|
54950
|
+
break;
|
|
54951
|
+
default:
|
|
54952
|
+
const s3 = this.buildNodeStyleAttrs({ stroke, strokeWidth, fill });
|
|
54953
|
+
shape = `<rect ${s3} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="0" ry="0" />`;
|
|
54954
|
+
}
|
|
54955
|
+
const text = this.generateWrappedText(node.label, cx, labelCenterY, node.width - 20);
|
|
54956
|
+
return `<g id="${node.id}">
|
|
54957
|
+
${shape}
|
|
54958
|
+
${text}
|
|
54959
|
+
</g>`;
|
|
54960
|
+
}
|
|
54961
|
+
generateWrappedText(text, x3, y2, maxWidth) {
|
|
54962
|
+
if (text.includes("<")) {
|
|
54963
|
+
return this.generateRichText(text, x3, y2, maxWidth);
|
|
54964
|
+
}
|
|
54965
|
+
const charWidth = 7;
|
|
54966
|
+
const maxCharsPerLine = Math.floor(maxWidth / charWidth);
|
|
54967
|
+
if (maxCharsPerLine <= 0 || text.length <= maxCharsPerLine) {
|
|
54968
|
+
const dyOffset = this.fontSize * 0.35;
|
|
54969
|
+
return `<text class="node-label" x="${x3}" y="${y2 + dyOffset}" text-anchor="middle">${this.escapeXml(text)}</text>`;
|
|
54970
|
+
}
|
|
54971
|
+
const words = text.split(" ");
|
|
54972
|
+
const lines = [];
|
|
54973
|
+
let currentLine = "";
|
|
54974
|
+
for (const word of words) {
|
|
54975
|
+
const testLine = currentLine ? `${currentLine} ${word}` : word;
|
|
54976
|
+
if (testLine.length > maxCharsPerLine && currentLine) {
|
|
54977
|
+
lines.push(currentLine);
|
|
54978
|
+
currentLine = word;
|
|
54979
|
+
} else {
|
|
54980
|
+
currentLine = testLine;
|
|
54981
|
+
}
|
|
54982
|
+
}
|
|
54983
|
+
if (currentLine) {
|
|
54984
|
+
lines.push(currentLine);
|
|
54985
|
+
}
|
|
54986
|
+
const lineHeight = 18;
|
|
54987
|
+
const totalHeight = (lines.length - 1) * lineHeight;
|
|
54988
|
+
const startY = y2 - totalHeight / 2 + this.fontSize * 0.35;
|
|
54989
|
+
const tspans = lines.map((line, i3) => {
|
|
54990
|
+
const lineY = startY + i3 * lineHeight;
|
|
54991
|
+
return `<tspan x="${x3}" y="${lineY}" text-anchor="middle">${this.escapeXml(line)}</tspan>`;
|
|
54992
|
+
}).join("\n ");
|
|
54993
|
+
return `<text class="node-label">
|
|
54994
|
+
${tspans}
|
|
54995
|
+
</text>`;
|
|
54996
|
+
}
|
|
54997
|
+
// Basic HTML-aware text renderer supporting <br>, <b>/<strong>, <i>/<em>, <u>
|
|
54998
|
+
generateRichText(html, x3, y2, maxWidth) {
|
|
54999
|
+
html = this.normalizeHtml(html);
|
|
55000
|
+
const segments = [];
|
|
55001
|
+
const re = /<\/?(br|b|strong|i|em|u)\s*\/?\s*>/gi;
|
|
55002
|
+
let lastIndex = 0;
|
|
55003
|
+
const state2 = { bold: false, italic: false, underline: false };
|
|
55004
|
+
const pushText = (t3) => {
|
|
55005
|
+
if (!t3)
|
|
55006
|
+
return;
|
|
55007
|
+
segments.push({ text: this.htmlDecode(t3), bold: state2.bold, italic: state2.italic, underline: state2.underline });
|
|
55008
|
+
};
|
|
55009
|
+
let m3;
|
|
55010
|
+
while (m3 = re.exec(html)) {
|
|
55011
|
+
pushText(html.slice(lastIndex, m3.index));
|
|
55012
|
+
const tag2 = m3[0].toLowerCase();
|
|
55013
|
+
const name14 = m3[1].toLowerCase();
|
|
55014
|
+
const isClose = tag2.startsWith("</");
|
|
55015
|
+
if (name14 === "br") {
|
|
55016
|
+
segments.push({ text: "", br: true });
|
|
55017
|
+
} else if (name14 === "b" || name14 === "strong") {
|
|
55018
|
+
state2.bold = !isClose ? true : false;
|
|
55019
|
+
} else if (name14 === "i" || name14 === "em") {
|
|
55020
|
+
state2.italic = !isClose ? true : false;
|
|
55021
|
+
} else if (name14 === "u") {
|
|
55022
|
+
state2.underline = !isClose ? true : false;
|
|
55023
|
+
}
|
|
55024
|
+
lastIndex = re.lastIndex;
|
|
55025
|
+
}
|
|
55026
|
+
pushText(html.slice(lastIndex));
|
|
55027
|
+
const lines = [];
|
|
55028
|
+
const charWidth = 7;
|
|
55029
|
+
const maxCharsPerLine = Math.max(1, Math.floor(maxWidth / charWidth));
|
|
55030
|
+
let current = [];
|
|
55031
|
+
let currentLen = 0;
|
|
55032
|
+
const flush = () => {
|
|
55033
|
+
if (current.length) {
|
|
55034
|
+
lines.push(current);
|
|
55035
|
+
current = [];
|
|
55036
|
+
currentLen = 0;
|
|
55037
|
+
}
|
|
55038
|
+
};
|
|
55039
|
+
const splitWords = (s3) => {
|
|
55040
|
+
if (!s3.text)
|
|
55041
|
+
return [s3];
|
|
55042
|
+
const words = s3.text.split(/(\s+)/);
|
|
55043
|
+
return words.map((w3) => ({ ...s3, text: w3 }));
|
|
55044
|
+
};
|
|
55045
|
+
for (const seg of segments) {
|
|
55046
|
+
if (seg.br) {
|
|
55047
|
+
flush();
|
|
55048
|
+
continue;
|
|
55049
|
+
}
|
|
55050
|
+
for (const w3 of splitWords(seg)) {
|
|
55051
|
+
const wlen = w3.text.length;
|
|
55052
|
+
if (currentLen + wlen > maxCharsPerLine && currentLen > 0) {
|
|
55053
|
+
flush();
|
|
55054
|
+
}
|
|
55055
|
+
current.push(w3);
|
|
55056
|
+
currentLen += wlen;
|
|
55057
|
+
}
|
|
55058
|
+
}
|
|
55059
|
+
flush();
|
|
55060
|
+
const lineHeight = 18;
|
|
55061
|
+
const totalHeight = (lines.length - 1) * lineHeight;
|
|
55062
|
+
const startY = y2 - totalHeight / 2 + this.fontSize * 0.35;
|
|
55063
|
+
const tspans = [];
|
|
55064
|
+
for (let i3 = 0; i3 < lines.length; i3++) {
|
|
55065
|
+
const lineY = startY + i3 * lineHeight;
|
|
55066
|
+
let acc = "";
|
|
55067
|
+
let cursorX = x3;
|
|
55068
|
+
const inner = [];
|
|
55069
|
+
let buffer = "";
|
|
55070
|
+
let style = { bold: false, italic: false, underline: false };
|
|
55071
|
+
const flushInline = () => {
|
|
55072
|
+
if (!buffer)
|
|
55073
|
+
return;
|
|
55074
|
+
const styleAttr = `${style.bold ? 'font-weight="bold" ' : ""}${style.italic ? 'font-style="italic" ' : ""}${style.underline ? 'text-decoration="underline" ' : ""}`;
|
|
55075
|
+
inner.push(`<tspan ${styleAttr}>${this.escapeXml(buffer)}</tspan>`);
|
|
55076
|
+
buffer = "";
|
|
55077
|
+
};
|
|
55078
|
+
for (const w3 of lines[i3]) {
|
|
55079
|
+
const wStyle = { bold: !!w3.bold, italic: !!w3.italic, underline: !!w3.underline };
|
|
55080
|
+
if (wStyle.bold !== style.bold || wStyle.italic !== style.italic || wStyle.underline !== style.underline) {
|
|
55081
|
+
flushInline();
|
|
55082
|
+
style = wStyle;
|
|
55083
|
+
}
|
|
55084
|
+
buffer += w3.text;
|
|
55085
|
+
}
|
|
55086
|
+
flushInline();
|
|
55087
|
+
tspans.push(`<tspan x="${x3}" y="${lineY}" text-anchor="middle">${inner.join("")}</tspan>`);
|
|
55088
|
+
}
|
|
55089
|
+
return `<text font-family="${this.fontFamily}" font-size="${this.fontSize}" fill="#333">${tspans.join("\n ")}</text>`;
|
|
55090
|
+
}
|
|
55091
|
+
normalizeHtml(s3) {
|
|
55092
|
+
let out = s3.replace(/<\s+/g, "<").replace(/\s+>/g, ">").replace(/<\s*\//g, "</").replace(/\s*\/\s*>/g, "/>").replace(/<\s*(br)\s*>/gi, "<$1/>");
|
|
55093
|
+
return out;
|
|
55094
|
+
}
|
|
55095
|
+
htmlDecode(s3) {
|
|
55096
|
+
return s3.replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&").replace(/"/g, '"').replace(/'/g, "'");
|
|
55097
|
+
}
|
|
55098
|
+
generateEdge(edge, padX, padY, nodeMap) {
|
|
55099
|
+
if (!edge.points || edge.points.length < 2) {
|
|
55100
|
+
return { path: "" };
|
|
55101
|
+
}
|
|
55102
|
+
const points = edge.points.map((p3) => ({ x: p3.x + padX, y: p3.y + padY }));
|
|
55103
|
+
const segData = this.buildSmoothSegments(points);
|
|
55104
|
+
let strokeDasharray = "";
|
|
55105
|
+
let strokeWidth = 1.5;
|
|
55106
|
+
let markerEnd = "";
|
|
55107
|
+
let markerStart = "";
|
|
55108
|
+
switch (edge.type) {
|
|
55109
|
+
case "open":
|
|
55110
|
+
markerEnd = "";
|
|
55111
|
+
break;
|
|
55112
|
+
case "dotted":
|
|
55113
|
+
strokeDasharray = "3,3";
|
|
55114
|
+
break;
|
|
55115
|
+
case "thick":
|
|
55116
|
+
strokeWidth = 3;
|
|
55117
|
+
break;
|
|
55118
|
+
case "invisible":
|
|
55119
|
+
strokeDasharray = "0,100000";
|
|
55120
|
+
markerEnd = "";
|
|
55121
|
+
break;
|
|
55122
|
+
}
|
|
55123
|
+
const mStart = edge.markerStart;
|
|
55124
|
+
const mEnd = edge.markerEnd;
|
|
55125
|
+
const sourceNode = nodeMap[edge.source];
|
|
55126
|
+
const targetNode = nodeMap[edge.target];
|
|
55127
|
+
let boundaryStart = points[0];
|
|
55128
|
+
let boundaryEnd = points[points.length - 1];
|
|
55129
|
+
if (sourceNode && points.length >= 2) {
|
|
55130
|
+
const pseudo = { start: points[0], segs: [{ c1: points[1], c2: points[Math.max(0, points.length - 2)], to: points[points.length - 1] }] };
|
|
55131
|
+
boundaryStart = this.intersectSegmentsStart(pseudo, sourceNode).start;
|
|
55132
|
+
}
|
|
55133
|
+
if (targetNode && points.length >= 2) {
|
|
55134
|
+
const pseudo = { start: points[0], segs: [{ c1: points[1], c2: points[Math.max(0, points.length - 2)], to: points[points.length - 1] }] };
|
|
55135
|
+
const after = this.intersectSegmentsEnd(pseudo, targetNode);
|
|
55136
|
+
boundaryEnd = after.segs.length ? after.segs[after.segs.length - 1].to : boundaryEnd;
|
|
55137
|
+
}
|
|
55138
|
+
const pathParts = [];
|
|
55139
|
+
pathParts.push(`M${boundaryStart.x},${boundaryStart.y}`);
|
|
55140
|
+
let startFlat = points.length >= 2 ? points[1] : boundaryStart;
|
|
55141
|
+
if (points.length >= 2) {
|
|
55142
|
+
const svx = points[1].x - boundaryStart.x;
|
|
55143
|
+
const svy = points[1].y - boundaryStart.y;
|
|
55144
|
+
const slen = Math.hypot(svx, svy) || 1;
|
|
55145
|
+
const SFLAT = Math.min(22, Math.max(10, slen * 0.15));
|
|
55146
|
+
startFlat = { x: boundaryStart.x + svx / slen * SFLAT, y: boundaryStart.y + svy / slen * SFLAT };
|
|
55147
|
+
pathParts.push(`L${startFlat.x},${startFlat.y}`);
|
|
55148
|
+
}
|
|
55149
|
+
const orthogonal = edge.pathMode === "orthogonal";
|
|
55150
|
+
if (points.length >= 4 && !orthogonal) {
|
|
55151
|
+
const pts = [points[0], ...points, points[points.length - 1]];
|
|
55152
|
+
for (let i3 = 1; i3 < pts.length - 3; i3++) {
|
|
55153
|
+
const p0 = pts[i3 - 1];
|
|
55154
|
+
const p1 = pts[i3];
|
|
55155
|
+
const p22 = pts[i3 + 1];
|
|
55156
|
+
const p3 = pts[i3 + 2];
|
|
55157
|
+
const c1x = p1.x + (p22.x - p0.x) / 6;
|
|
55158
|
+
const c1y = p1.y + (p22.y - p0.y) / 6;
|
|
55159
|
+
const c2x = p22.x - (p3.x - p1.x) / 6;
|
|
55160
|
+
const c2y = p22.y - (p3.y - p1.y) / 6;
|
|
55161
|
+
pathParts.push(`C${c1x},${c1y} ${c2x},${c2y} ${p22.x},${p22.y}`);
|
|
55162
|
+
}
|
|
55163
|
+
pathParts.push(`L${boundaryEnd.x},${boundaryEnd.y}`);
|
|
55164
|
+
} else if (points.length === 3 && !orthogonal) {
|
|
55165
|
+
const p0 = boundaryStart, p1 = points[1], p22 = boundaryEnd;
|
|
55166
|
+
const ax = boundaryEnd.x - p1.x;
|
|
55167
|
+
const ay = boundaryEnd.y - p1.y;
|
|
55168
|
+
const alen = Math.hypot(ax, ay) || 1;
|
|
55169
|
+
const FLAT_IN = Math.min(20, Math.max(10, alen * 0.15));
|
|
55170
|
+
const preEnd = { x: boundaryEnd.x - ax / alen * FLAT_IN, y: boundaryEnd.y - ay / alen * FLAT_IN };
|
|
55171
|
+
const sdx = startFlat.x - boundaryStart.x;
|
|
55172
|
+
const sdy = startFlat.y - boundaryStart.y;
|
|
55173
|
+
const sdirx = sdx === 0 && sdy === 0 ? p1.x - p0.x : sdx;
|
|
55174
|
+
const sdiry = sdx === 0 && sdy === 0 ? p1.y - p0.y : sdy;
|
|
55175
|
+
const sdlen = Math.hypot(sdirx, sdiry) || 1;
|
|
55176
|
+
const c1len = Math.min(40, Math.max(12, sdlen * 1.2));
|
|
55177
|
+
const c1x = startFlat.x + sdirx / sdlen * c1len;
|
|
55178
|
+
const c1y = startFlat.y + sdiry / sdlen * c1len;
|
|
55179
|
+
const dirx = (boundaryEnd.x - p1.x) / alen;
|
|
55180
|
+
const diry = (boundaryEnd.y - p1.y) / alen;
|
|
55181
|
+
const c2x = preEnd.x - dirx * (FLAT_IN * 0.6);
|
|
55182
|
+
const c2y = preEnd.y - diry * (FLAT_IN * 0.6);
|
|
55183
|
+
pathParts.push(`C${c1x},${c1y} ${c2x},${c2y} ${preEnd.x},${preEnd.y}`);
|
|
55184
|
+
pathParts.push(`L${boundaryEnd.x},${boundaryEnd.y}`);
|
|
55185
|
+
} else {
|
|
55186
|
+
pathParts.push(`L${boundaryEnd.x},${boundaryEnd.y}`);
|
|
55187
|
+
}
|
|
55188
|
+
if (orthogonal) {
|
|
55189
|
+
pathParts.length = 0;
|
|
55190
|
+
pathParts.push(`M${boundaryStart.x},${boundaryStart.y}`);
|
|
55191
|
+
for (const p3 of points.slice(1, -1))
|
|
55192
|
+
pathParts.push(`L${p3.x},${p3.y}`);
|
|
55193
|
+
pathParts.push(`L${boundaryEnd.x},${boundaryEnd.y}`);
|
|
55194
|
+
}
|
|
55195
|
+
const pathData = pathParts.join(" ");
|
|
55196
|
+
let edgeElement = `<path class="edge-path" d="${pathData}" stroke-linecap="round" stroke-linejoin="round"`;
|
|
55197
|
+
if (strokeDasharray) {
|
|
55198
|
+
edgeElement += ` stroke-dasharray="${strokeDasharray}"`;
|
|
55199
|
+
}
|
|
55200
|
+
const startMarkUrl = mStart === "arrow" ? "url(#arrow)" : mStart === "circle" ? "url(#circle-marker)" : mStart === "cross" ? "url(#cross-marker)" : "";
|
|
55201
|
+
const endMarkUrl = mEnd === "arrow" ? "url(#arrow)" : mEnd === "circle" ? "url(#circle-marker)" : mEnd === "cross" ? "url(#cross-marker)" : markerEnd || "";
|
|
55202
|
+
if (startMarkUrl && mStart !== "arrow")
|
|
55203
|
+
edgeElement += ` marker-start="${startMarkUrl}"`;
|
|
55204
|
+
if (endMarkUrl && mEnd !== "arrow")
|
|
55205
|
+
edgeElement += ` marker-end="${endMarkUrl}"`;
|
|
55206
|
+
edgeElement += " />";
|
|
55207
|
+
if (edge.label) {
|
|
55208
|
+
const pos = this.pointAtRatio(points, 0.55);
|
|
55209
|
+
const text = this.escapeXml(edge.label);
|
|
55210
|
+
const padding = 4;
|
|
55211
|
+
const fontSize = this.fontSize - 3;
|
|
55212
|
+
const width = Math.max(18, Math.min(220, text.length * 6 + padding * 2));
|
|
55213
|
+
const height = 14;
|
|
55214
|
+
const x3 = pos.x - width / 2;
|
|
55215
|
+
const y2 = pos.y - height / 2;
|
|
55216
|
+
const labelBg = `<rect class="edge-label-bg" x="${x3}" y="${y2}" width="${width}" height="${height}" rx="3" />`;
|
|
55217
|
+
const labelText = `<text class="edge-label-text" x="${pos.x}" y="${pos.y}" text-anchor="middle" dominant-baseline="middle">${text}</text>`;
|
|
55218
|
+
let overlay2 = "";
|
|
55219
|
+
const prevEndL = points.length >= 2 ? points[points.length - 2] : boundaryEnd;
|
|
55220
|
+
const vxl = boundaryEnd.x - prevEndL.x;
|
|
55221
|
+
const vyl = boundaryEnd.y - prevEndL.y;
|
|
55222
|
+
const vlenl = Math.hypot(vxl, vyl) || 1;
|
|
55223
|
+
const uxl = vxl / vlenl;
|
|
55224
|
+
const uyl = vyl / vlenl;
|
|
55225
|
+
const nxl = -uyl;
|
|
55226
|
+
const nyl = uxl;
|
|
55227
|
+
const triLenL = 8;
|
|
55228
|
+
const triWL = 6;
|
|
55229
|
+
const p1xL = boundaryEnd.x, p1yL = boundaryEnd.y;
|
|
55230
|
+
const baseXL = boundaryEnd.x - uxl * triLenL;
|
|
55231
|
+
const baseYL = boundaryEnd.y - uyl * triLenL;
|
|
55232
|
+
const p2xL = baseXL + nxl * (triWL / 2), p2yL = baseYL + nyl * (triWL / 2);
|
|
55233
|
+
const p3xL = baseXL - nxl * (triWL / 2), p3yL = baseYL - nyl * (triWL / 2);
|
|
55234
|
+
overlay2 += triangleAtEnd(prevEndL, boundaryEnd, this.arrowStroke);
|
|
55235
|
+
if (mStart === "arrow" && points.length >= 2) {
|
|
55236
|
+
const firstLeg = points[1];
|
|
55237
|
+
const svx = boundaryStart.x - firstLeg.x;
|
|
55238
|
+
const svy = boundaryStart.y - firstLeg.y;
|
|
55239
|
+
const slen = Math.hypot(svx, svy) || 1;
|
|
55240
|
+
const sux = svx / slen;
|
|
55241
|
+
const suy = svy / slen;
|
|
55242
|
+
const snx = -suy;
|
|
55243
|
+
const sny = sux;
|
|
55244
|
+
const sbaseX = boundaryStart.x - sux * triLenL;
|
|
55245
|
+
const sbaseY = boundaryStart.y - suy * triLenL;
|
|
55246
|
+
overlay2 += triangleAtStart(boundaryStart, firstLeg, this.arrowStroke);
|
|
55247
|
+
}
|
|
55248
|
+
const pathGroup = `<g>
|
|
55249
|
+
${edgeElement}
|
|
55250
|
+
${labelBg}
|
|
55251
|
+
${labelText}
|
|
55252
|
+
${overlay2}
|
|
55253
|
+
</g>`;
|
|
55254
|
+
return { path: pathGroup };
|
|
55255
|
+
}
|
|
55256
|
+
let overlay = "";
|
|
55257
|
+
const prevEnd = points.length >= 2 ? points[points.length - 2] : boundaryEnd;
|
|
55258
|
+
const vx = boundaryEnd.x - prevEnd.x;
|
|
55259
|
+
const vy = boundaryEnd.y - prevEnd.y;
|
|
55260
|
+
const vlen = Math.hypot(vx, vy) || 1;
|
|
55261
|
+
const ux = vx / vlen;
|
|
55262
|
+
const uy = vy / vlen;
|
|
55263
|
+
const nx = -uy;
|
|
55264
|
+
const ny = ux;
|
|
55265
|
+
const triLen = 8;
|
|
55266
|
+
const triW = 6;
|
|
55267
|
+
const p1x = boundaryEnd.x, p1y = boundaryEnd.y;
|
|
55268
|
+
const baseX = boundaryEnd.x - ux * triLen;
|
|
55269
|
+
const baseY = boundaryEnd.y - uy * triLen;
|
|
55270
|
+
const p2x = baseX + nx * (triW / 2), p2y = baseY + ny * (triW / 2);
|
|
55271
|
+
const p3x = baseX - nx * (triW / 2), p3y = baseY - ny * (triW / 2);
|
|
55272
|
+
if (mEnd === "arrow")
|
|
55273
|
+
overlay += triangleAtEnd(prevEnd, boundaryEnd, this.arrowStroke);
|
|
55274
|
+
if (mStart === "arrow" && points.length >= 2) {
|
|
55275
|
+
const firstLeg = points[1];
|
|
55276
|
+
const svx = boundaryStart.x - firstLeg.x;
|
|
55277
|
+
const svy = boundaryStart.y - firstLeg.y;
|
|
55278
|
+
const slen = Math.hypot(svx, svy) || 1;
|
|
55279
|
+
const sux = svx / slen;
|
|
55280
|
+
const suy = svy / slen;
|
|
55281
|
+
const snx = -suy;
|
|
55282
|
+
const sny = sux;
|
|
55283
|
+
overlay += triangleAtStart(boundaryStart, firstLeg, this.arrowStroke);
|
|
55284
|
+
}
|
|
55285
|
+
if (overlay) {
|
|
55286
|
+
const grouped = `<g>${edgeElement}
|
|
55287
|
+
${overlay}</g>`;
|
|
55288
|
+
return { path: grouped };
|
|
55289
|
+
}
|
|
55290
|
+
return { path: edgeElement };
|
|
55291
|
+
}
|
|
55292
|
+
// --- helpers ---
|
|
55293
|
+
buildSmoothSegments(points) {
|
|
55294
|
+
if (points.length < 2) {
|
|
55295
|
+
const p3 = points[0] || { x: 0, y: 0 };
|
|
55296
|
+
return { start: p3, segs: [] };
|
|
55297
|
+
}
|
|
55298
|
+
if (points.length === 2) {
|
|
55299
|
+
const p0 = points[0];
|
|
55300
|
+
const p1 = points[1];
|
|
55301
|
+
const c1 = { x: p0.x + (p1.x - p0.x) / 3, y: p0.y + (p1.y - p0.y) / 3 };
|
|
55302
|
+
const c22 = { x: p0.x + 2 * (p1.x - p0.x) / 3, y: p0.y + 2 * (p1.y - p0.y) / 3 };
|
|
55303
|
+
return { start: p0, segs: [{ c1, c2: c22, to: p1 }] };
|
|
55304
|
+
}
|
|
55305
|
+
const pts = [points[0], ...points, points[points.length - 1]];
|
|
55306
|
+
const segs = [];
|
|
55307
|
+
const firstIdx = 1;
|
|
55308
|
+
const lastIdx = pts.length - 3;
|
|
55309
|
+
const midFactor = 1;
|
|
55310
|
+
const endFactor = 0.35;
|
|
55311
|
+
const FLAT_LEN = 28;
|
|
55312
|
+
for (let i3 = 1; i3 < pts.length - 2; i3++) {
|
|
55313
|
+
const p0 = pts[i3 - 1];
|
|
55314
|
+
const p1 = pts[i3];
|
|
55315
|
+
const p22 = pts[i3 + 1];
|
|
55316
|
+
const p3 = pts[i3 + 2];
|
|
55317
|
+
const f1 = i3 === firstIdx ? endFactor : midFactor;
|
|
55318
|
+
const f22 = i3 === lastIdx ? endFactor : midFactor;
|
|
55319
|
+
let c1 = { x: p1.x + (p22.x - p0.x) / 6 * f1, y: p1.y + (p22.y - p0.y) / 6 * f1 };
|
|
55320
|
+
let c22 = { x: p22.x - (p3.x - p1.x) / 6 * f22, y: p22.y - (p3.y - p1.y) / 6 * f22 };
|
|
55321
|
+
if (i3 === firstIdx) {
|
|
55322
|
+
const dx = p22.x - p1.x, dy = p22.y - p1.y;
|
|
55323
|
+
const len = Math.hypot(dx, dy) || 1;
|
|
55324
|
+
const t3 = Math.min(FLAT_LEN, len * 0.5);
|
|
55325
|
+
c1 = { x: p1.x + dx / len * t3, y: p1.y + dy / len * t3 };
|
|
55326
|
+
}
|
|
55327
|
+
if (i3 === lastIdx) {
|
|
55328
|
+
const dx = p22.x - p1.x, dy = p22.y - p1.y;
|
|
55329
|
+
const len = Math.hypot(dx, dy) || 1;
|
|
55330
|
+
const t3 = Math.min(FLAT_LEN, len * 0.5);
|
|
55331
|
+
c22 = { x: p22.x - dx / len * t3, y: p22.y - dy / len * t3 };
|
|
55332
|
+
}
|
|
55333
|
+
segs.push({ c1, c2: c22, to: { x: p22.x, y: p22.y } });
|
|
55334
|
+
}
|
|
55335
|
+
return { start: pts[1], segs };
|
|
55336
|
+
}
|
|
55337
|
+
pathFromSegments(data2) {
|
|
55338
|
+
let d3 = `M${data2.start.x},${data2.start.y}`;
|
|
55339
|
+
for (const s3 of data2.segs) {
|
|
55340
|
+
d3 += ` C${s3.c1.x},${s3.c1.y} ${s3.c2.x},${s3.c2.y} ${s3.to.x},${s3.to.y}`;
|
|
55341
|
+
}
|
|
55342
|
+
return d3;
|
|
55343
|
+
}
|
|
55344
|
+
trimSegmentsEnd(data2, cut) {
|
|
55345
|
+
const segs = data2.segs.slice();
|
|
55346
|
+
if (!segs.length)
|
|
55347
|
+
return data2;
|
|
55348
|
+
const last2 = { ...segs[segs.length - 1] };
|
|
55349
|
+
const vx = last2.to.x - last2.c2.x;
|
|
55350
|
+
const vy = last2.to.y - last2.c2.y;
|
|
55351
|
+
const len = Math.hypot(vx, vy) || 1;
|
|
55352
|
+
const eff = Math.max(0.1, Math.min(cut, Math.max(0, len - 0.2)));
|
|
55353
|
+
const nx = vx / len;
|
|
55354
|
+
const ny = vy / len;
|
|
55355
|
+
const newTo = { x: last2.to.x - nx * eff, y: last2.to.y - ny * eff };
|
|
55356
|
+
last2.to = newTo;
|
|
55357
|
+
segs[segs.length - 1] = last2;
|
|
55358
|
+
return { start: data2.start, segs };
|
|
55359
|
+
}
|
|
55360
|
+
trimSegmentsStart(data2, cut) {
|
|
55361
|
+
const segs = data2.segs.slice();
|
|
55362
|
+
if (!segs.length)
|
|
55363
|
+
return data2;
|
|
55364
|
+
const first2 = { ...segs[0] };
|
|
55365
|
+
const vx = first2.c1.x - data2.start.x;
|
|
55366
|
+
const vy = first2.c1.y - data2.start.y;
|
|
55367
|
+
const len = Math.hypot(vx, vy) || 1;
|
|
55368
|
+
const eff = Math.max(0.1, Math.min(cut, Math.max(0, len - 0.2)));
|
|
55369
|
+
const nx = vx / len;
|
|
55370
|
+
const ny = vy / len;
|
|
55371
|
+
const newStart = { x: data2.start.x + nx * eff, y: data2.start.y + ny * eff };
|
|
55372
|
+
return { start: newStart, segs };
|
|
55373
|
+
}
|
|
55374
|
+
// ---- shape intersections ----
|
|
55375
|
+
intersectSegmentsEnd(data2, node) {
|
|
55376
|
+
if (!data2.segs.length)
|
|
55377
|
+
return data2;
|
|
55378
|
+
const last2 = data2.segs[data2.segs.length - 1];
|
|
55379
|
+
const p1 = last2.c2;
|
|
55380
|
+
const p22 = last2.to;
|
|
55381
|
+
const hit = this.intersectLineWithNode(p1, p22, node);
|
|
55382
|
+
if (hit) {
|
|
55383
|
+
const segs = data2.segs.slice();
|
|
55384
|
+
segs[segs.length - 1] = { ...last2, to: hit };
|
|
55385
|
+
return { start: data2.start, segs };
|
|
55386
|
+
}
|
|
55387
|
+
return data2;
|
|
55388
|
+
}
|
|
55389
|
+
intersectSegmentsStart(data2, node) {
|
|
55390
|
+
if (!data2.segs.length)
|
|
55391
|
+
return data2;
|
|
55392
|
+
const first2 = data2.segs[0];
|
|
55393
|
+
const p1 = data2.start;
|
|
55394
|
+
const p22 = first2.c1;
|
|
55395
|
+
const hit = this.intersectLineWithNode(p1, p22, node);
|
|
55396
|
+
if (hit) {
|
|
55397
|
+
return { start: hit, segs: data2.segs };
|
|
55398
|
+
}
|
|
55399
|
+
return data2;
|
|
55400
|
+
}
|
|
55401
|
+
intersectLineWithNode(p1, p22, node) {
|
|
55402
|
+
const shape = node.shape;
|
|
55403
|
+
const rectPoly = () => [
|
|
55404
|
+
{ x: node.x, y: node.y },
|
|
55405
|
+
{ x: node.x + node.width, y: node.y },
|
|
55406
|
+
{ x: node.x + node.width, y: node.y + node.height },
|
|
55407
|
+
{ x: node.x, y: node.y + node.height }
|
|
55408
|
+
];
|
|
55409
|
+
switch (shape) {
|
|
55410
|
+
case "circle": {
|
|
55411
|
+
const cx = node.x + node.width / 2;
|
|
55412
|
+
const cy = node.y + node.height / 2;
|
|
55413
|
+
const r3 = Math.min(node.width, node.height) / 2;
|
|
55414
|
+
return this.lineCircleIntersection(p1, p22, { cx, cy, r: r3 });
|
|
55415
|
+
}
|
|
55416
|
+
case "diamond": {
|
|
55417
|
+
const cx = node.x + node.width / 2;
|
|
55418
|
+
const cy = node.y + node.height / 2;
|
|
55419
|
+
const poly = [{ x: cx, y: node.y }, { x: node.x + node.width, y: cy }, { x: cx, y: node.y + node.height }, { x: node.x, y: cy }];
|
|
55420
|
+
return this.linePolygonIntersection(p1, p22, poly);
|
|
55421
|
+
}
|
|
55422
|
+
case "hexagon": {
|
|
55423
|
+
const s3 = Math.max(10, node.width * 0.2);
|
|
55424
|
+
const poly = [
|
|
55425
|
+
{ x: node.x + s3, y: node.y },
|
|
55426
|
+
{ x: node.x + node.width - s3, y: node.y },
|
|
55427
|
+
{ x: node.x + node.width, y: node.y + node.height / 2 },
|
|
55428
|
+
{ x: node.x + node.width - s3, y: node.y + node.height },
|
|
55429
|
+
{ x: node.x + s3, y: node.y + node.height },
|
|
55430
|
+
{ x: node.x, y: node.y + node.height / 2 }
|
|
55431
|
+
];
|
|
55432
|
+
return this.linePolygonIntersection(p1, p22, poly);
|
|
55433
|
+
}
|
|
55434
|
+
case "parallelogram": {
|
|
55435
|
+
const o3 = Math.min(node.width * 0.25, node.height * 0.6);
|
|
55436
|
+
const poly = [
|
|
55437
|
+
{ x: node.x + o3, y: node.y },
|
|
55438
|
+
{ x: node.x + node.width, y: node.y },
|
|
55439
|
+
{ x: node.x + node.width - o3, y: node.y + node.height },
|
|
55440
|
+
{ x: node.x, y: node.y + node.height }
|
|
55441
|
+
];
|
|
55442
|
+
return this.linePolygonIntersection(p1, p22, poly);
|
|
55443
|
+
}
|
|
55444
|
+
case "trapezoid": {
|
|
55445
|
+
const o3 = Math.min(node.width * 0.2, node.height * 0.5);
|
|
55446
|
+
const poly = [
|
|
55447
|
+
{ x: node.x + o3, y: node.y },
|
|
55448
|
+
{ x: node.x + node.width - o3, y: node.y },
|
|
55449
|
+
{ x: node.x + node.width, y: node.y + node.height },
|
|
55450
|
+
{ x: node.x, y: node.y + node.height }
|
|
55451
|
+
];
|
|
55452
|
+
return this.linePolygonIntersection(p1, p22, poly);
|
|
55453
|
+
}
|
|
55454
|
+
case "trapezoidAlt": {
|
|
55455
|
+
const o3 = Math.min(node.width * 0.2, node.height * 0.5);
|
|
55456
|
+
const poly = [
|
|
55457
|
+
{ x: node.x, y: node.y },
|
|
55458
|
+
{ x: node.x + node.width, y: node.y },
|
|
55459
|
+
{ x: node.x + node.width - o3, y: node.y + node.height },
|
|
55460
|
+
{ x: node.x + o3, y: node.y + node.height }
|
|
55461
|
+
];
|
|
55462
|
+
return this.linePolygonIntersection(p1, p22, poly);
|
|
55463
|
+
}
|
|
55464
|
+
case "stadium": {
|
|
55465
|
+
const r3 = Math.min(node.height / 2, node.width / 2);
|
|
55466
|
+
const rect = [
|
|
55467
|
+
{ x: node.x + r3, y: node.y },
|
|
55468
|
+
{ x: node.x + node.width - r3, y: node.y },
|
|
55469
|
+
{ x: node.x + node.width - r3, y: node.y + node.height },
|
|
55470
|
+
{ x: node.x + r3, y: node.y + node.height }
|
|
55471
|
+
];
|
|
55472
|
+
const hitRect = this.linePolygonIntersection(p1, p22, rect);
|
|
55473
|
+
if (hitRect)
|
|
55474
|
+
return hitRect;
|
|
55475
|
+
const left = this.lineCircleIntersection(p1, p22, { cx: node.x + r3, cy: node.y + node.height / 2, r: r3 });
|
|
55476
|
+
const right = this.lineCircleIntersection(p1, p22, { cx: node.x + node.width - r3, cy: node.y + node.height / 2, r: r3 });
|
|
55477
|
+
const pick = (...pts) => {
|
|
55478
|
+
let best = null;
|
|
55479
|
+
let bestd = -Infinity;
|
|
55480
|
+
for (const pt of pts)
|
|
55481
|
+
if (pt) {
|
|
55482
|
+
const d3 = -((pt.x - p22.x) ** 2 + (pt.y - p22.y) ** 2);
|
|
55483
|
+
if (d3 > bestd) {
|
|
55484
|
+
bestd = d3;
|
|
55485
|
+
best = pt;
|
|
55486
|
+
}
|
|
55487
|
+
}
|
|
55488
|
+
return best;
|
|
55489
|
+
};
|
|
55490
|
+
return pick(left, right);
|
|
55491
|
+
}
|
|
55492
|
+
default: {
|
|
55493
|
+
return this.linePolygonIntersection(p1, p22, rectPoly());
|
|
55494
|
+
}
|
|
55495
|
+
}
|
|
55496
|
+
}
|
|
55497
|
+
lineCircleIntersection(p1, p22, c3) {
|
|
55498
|
+
const dx = p22.x - p1.x;
|
|
55499
|
+
const dy = p22.y - p1.y;
|
|
55500
|
+
const fx = p1.x - c3.cx;
|
|
55501
|
+
const fy = p1.y - c3.cy;
|
|
55502
|
+
const a3 = dx * dx + dy * dy;
|
|
55503
|
+
const b3 = 2 * (fx * dx + fy * dy);
|
|
55504
|
+
const cc2 = fx * fx + fy * fy - c3.r * c3.r;
|
|
55505
|
+
const disc = b3 * b3 - 4 * a3 * cc2;
|
|
55506
|
+
if (disc < 0)
|
|
55507
|
+
return null;
|
|
55508
|
+
const s3 = Math.sqrt(disc);
|
|
55509
|
+
const t1 = (-b3 - s3) / (2 * a3);
|
|
55510
|
+
const t22 = (-b3 + s3) / (2 * a3);
|
|
55511
|
+
const ts = [t1, t22].filter((t4) => t4 >= 0 && t4 <= 1);
|
|
55512
|
+
if (!ts.length)
|
|
55513
|
+
return null;
|
|
55514
|
+
const t3 = Math.max(...ts);
|
|
55515
|
+
return { x: p1.x + dx * t3, y: p1.y + dy * t3 };
|
|
55516
|
+
}
|
|
55517
|
+
linePolygonIntersection(p1, p22, poly) {
|
|
55518
|
+
let bestT = -Infinity;
|
|
55519
|
+
let best = null;
|
|
55520
|
+
for (let i3 = 0; i3 < poly.length; i3++) {
|
|
55521
|
+
const a3 = poly[i3];
|
|
55522
|
+
const b3 = poly[(i3 + 1) % poly.length];
|
|
55523
|
+
const hit = this.segmentIntersection(p1, p22, a3, b3);
|
|
55524
|
+
if (hit && hit.t >= 0 && hit.t <= 1 && hit.u >= 0 && hit.u <= 1) {
|
|
55525
|
+
if (hit.t > bestT) {
|
|
55526
|
+
bestT = hit.t;
|
|
55527
|
+
best = { x: hit.x, y: hit.y };
|
|
55528
|
+
}
|
|
55529
|
+
}
|
|
55530
|
+
}
|
|
55531
|
+
return best;
|
|
55532
|
+
}
|
|
55533
|
+
segmentIntersection(p3, p22, q3, q22) {
|
|
55534
|
+
const r3 = { x: p22.x - p3.x, y: p22.y - p3.y };
|
|
55535
|
+
const s3 = { x: q22.x - q3.x, y: q22.y - q3.y };
|
|
55536
|
+
const rxs = r3.x * s3.y - r3.y * s3.x;
|
|
55537
|
+
if (Math.abs(rxs) < 1e-6)
|
|
55538
|
+
return null;
|
|
55539
|
+
const q_p = { x: q3.x - p3.x, y: q3.y - p3.y };
|
|
55540
|
+
const t3 = (q_p.x * s3.y - q_p.y * s3.x) / rxs;
|
|
55541
|
+
const u3 = (q_p.x * r3.y - q_p.y * r3.x) / rxs;
|
|
55542
|
+
const x3 = p3.x + t3 * r3.x;
|
|
55543
|
+
const y2 = p3.y + t3 * r3.y;
|
|
55544
|
+
return { x: x3, y: y2, t: t3, u: u3 };
|
|
55545
|
+
}
|
|
55546
|
+
pointAtRatio(points, ratio) {
|
|
55547
|
+
const clampRatio = Math.max(0, Math.min(1, ratio));
|
|
55548
|
+
let total = 0;
|
|
55549
|
+
const segs = [];
|
|
55550
|
+
for (let i3 = 0; i3 < points.length - 1; i3++) {
|
|
55551
|
+
const dx = points[i3 + 1].x - points[i3].x;
|
|
55552
|
+
const dy = points[i3 + 1].y - points[i3].y;
|
|
55553
|
+
const len = Math.hypot(dx, dy);
|
|
55554
|
+
segs.push(len);
|
|
55555
|
+
total += len;
|
|
55556
|
+
}
|
|
55557
|
+
if (total === 0)
|
|
55558
|
+
return points[Math.floor(points.length / 2)];
|
|
55559
|
+
let target = total * clampRatio;
|
|
55560
|
+
for (let i3 = 0; i3 < segs.length; i3++) {
|
|
55561
|
+
if (target <= segs[i3]) {
|
|
55562
|
+
const t3 = segs[i3] === 0 ? 0 : target / segs[i3];
|
|
55563
|
+
return {
|
|
55564
|
+
x: points[i3].x + (points[i3 + 1].x - points[i3].x) * t3,
|
|
55565
|
+
y: points[i3].y + (points[i3 + 1].y - points[i3].y) * t3
|
|
55566
|
+
};
|
|
55567
|
+
}
|
|
55568
|
+
target -= segs[i3];
|
|
55569
|
+
}
|
|
55570
|
+
return points[points.length - 1];
|
|
55571
|
+
}
|
|
55572
|
+
escapeXml(text) {
|
|
55573
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
55574
|
+
}
|
|
55575
|
+
};
|
|
55576
|
+
}
|
|
55577
|
+
});
|
|
55578
|
+
|
|
55579
|
+
// node_modules/@probelabs/maid/out/renderer/pie-builder.js
|
|
55580
|
+
function unquote(s3) {
|
|
55581
|
+
if (!s3)
|
|
55582
|
+
return s3;
|
|
55583
|
+
const first2 = s3.charAt(0);
|
|
55584
|
+
const last2 = s3.charAt(s3.length - 1);
|
|
55585
|
+
if (first2 === '"' && last2 === '"' || first2 === "'" && last2 === "'") {
|
|
55586
|
+
const inner = s3.slice(1, -1);
|
|
55587
|
+
return inner.replace(/\\(["'])/g, "$1");
|
|
55588
|
+
}
|
|
55589
|
+
return s3;
|
|
55590
|
+
}
|
|
55591
|
+
function buildPieModel(text) {
|
|
55592
|
+
const errors = [];
|
|
55593
|
+
const lex = tokenize2(text);
|
|
55594
|
+
for (const e3 of lex.errors) {
|
|
55595
|
+
errors.push({
|
|
55596
|
+
line: e3.line ?? 1,
|
|
55597
|
+
column: e3.column ?? 1,
|
|
55598
|
+
message: e3.message,
|
|
55599
|
+
code: "PIE_LEX",
|
|
55600
|
+
severity: "error"
|
|
55601
|
+
});
|
|
55602
|
+
}
|
|
55603
|
+
parserInstance2.reset();
|
|
55604
|
+
parserInstance2.input = lex.tokens;
|
|
55605
|
+
const cst = parserInstance2.diagram();
|
|
55606
|
+
for (const e3 of parserInstance2.errors) {
|
|
55607
|
+
const t3 = e3.token;
|
|
55608
|
+
errors.push({
|
|
55609
|
+
line: t3?.startLine ?? 1,
|
|
55610
|
+
column: t3?.startColumn ?? 1,
|
|
55611
|
+
message: e3.message,
|
|
55612
|
+
code: "PIE_PARSE",
|
|
55613
|
+
severity: "error"
|
|
55614
|
+
});
|
|
55615
|
+
}
|
|
55616
|
+
const model = { title: void 0, showData: false, slices: [] };
|
|
55617
|
+
if (!cst || !cst.children)
|
|
55618
|
+
return { model, errors };
|
|
55619
|
+
if (cst.children.ShowDataKeyword && cst.children.ShowDataKeyword.length > 0) {
|
|
55620
|
+
model.showData = true;
|
|
55621
|
+
}
|
|
55622
|
+
const statements = cst.children.statement ?? [];
|
|
55623
|
+
for (const st of statements) {
|
|
55624
|
+
if (st.children?.titleStmt) {
|
|
55625
|
+
const tnode = st.children.titleStmt[0];
|
|
55626
|
+
const parts = [];
|
|
55627
|
+
const collect = (k3) => {
|
|
55628
|
+
const arr = tnode.children?.[k3] ?? [];
|
|
55629
|
+
for (const tok of arr)
|
|
55630
|
+
parts.push(unquote(tok.image));
|
|
55631
|
+
};
|
|
55632
|
+
collect("QuotedString");
|
|
55633
|
+
collect("Text");
|
|
55634
|
+
collect("NumberLiteral");
|
|
55635
|
+
const title = parts.join(" ").trim();
|
|
55636
|
+
if (title)
|
|
55637
|
+
model.title = title;
|
|
55638
|
+
} else if (st.children?.sliceStmt) {
|
|
55639
|
+
const snode = st.children.sliceStmt[0];
|
|
55640
|
+
const labelTok = snode.children?.sliceLabel?.[0]?.children?.QuotedString?.[0];
|
|
55641
|
+
const numTok = snode.children?.NumberLiteral?.[0];
|
|
55642
|
+
if (labelTok && numTok) {
|
|
55643
|
+
const label = unquote(labelTok.image).trim();
|
|
55644
|
+
const value = Number(numTok.image);
|
|
55645
|
+
if (!Number.isNaN(value)) {
|
|
55646
|
+
model.slices.push({ label, value });
|
|
55647
|
+
}
|
|
55648
|
+
}
|
|
55649
|
+
}
|
|
55650
|
+
}
|
|
55651
|
+
return { model, errors };
|
|
55652
|
+
}
|
|
55653
|
+
var init_pie_builder = __esm({
|
|
55654
|
+
"node_modules/@probelabs/maid/out/renderer/pie-builder.js"() {
|
|
55655
|
+
init_lexer3();
|
|
55656
|
+
init_parser3();
|
|
55657
|
+
}
|
|
55658
|
+
});
|
|
55659
|
+
|
|
55660
|
+
// node_modules/@probelabs/maid/out/renderer/pie-renderer.js
|
|
55661
|
+
function polarToCartesian(cx, cy, r3, angleRad) {
|
|
55662
|
+
return { x: cx + r3 * Math.cos(angleRad), y: cy + r3 * Math.sin(angleRad) };
|
|
55663
|
+
}
|
|
55664
|
+
function renderPie(model, opts = {}) {
|
|
55665
|
+
let width = Math.max(320, Math.floor(opts.width ?? 640));
|
|
55666
|
+
const height = Math.max(240, Math.floor(opts.height ?? 400));
|
|
55667
|
+
const pad = 24;
|
|
55668
|
+
const titleH = model.title ? 28 : 0;
|
|
55669
|
+
let cx = width / 2;
|
|
55670
|
+
const cy = (height + titleH) / 2 + (model.title ? 8 : 0);
|
|
55671
|
+
const baseRadius = Math.max(40, Math.min(width, height - titleH) / 2 - pad);
|
|
55672
|
+
const slices = model.slices.filter((s3) => Math.max(0, s3.value) > 0);
|
|
55673
|
+
const total = slices.reduce((a3, s3) => a3 + Math.max(0, s3.value), 0);
|
|
55674
|
+
const LEG_SW = 12;
|
|
55675
|
+
const LEG_GAP = 8;
|
|
55676
|
+
const LEG_VSPACE = 18;
|
|
55677
|
+
const legendItems = slices.map((s3) => `${s3.label}${model.showData ? ` ${formatNumber(Number(s3.value))}` : ""}`);
|
|
55678
|
+
const legendTextWidth = legendItems.length ? Math.max(...legendItems.map((t3) => measureText(t3, 12))) : 0;
|
|
55679
|
+
const legendBlockWidth = legendItems.length ? LEG_SW + LEG_GAP + legendTextWidth + pad : 0;
|
|
55680
|
+
if (legendItems.length) {
|
|
55681
|
+
const neededWidth = pad + baseRadius * 2 + legendBlockWidth + pad;
|
|
55682
|
+
if (neededWidth > width)
|
|
55683
|
+
width = Math.ceil(neededWidth);
|
|
55684
|
+
}
|
|
55685
|
+
let radius = baseRadius;
|
|
55686
|
+
if (legendItems.length) {
|
|
55687
|
+
const leftPad = Math.max(pad, (width - legendBlockWidth - radius * 2) / 2);
|
|
55688
|
+
cx = leftPad + radius;
|
|
55689
|
+
}
|
|
55690
|
+
let start = -Math.PI / 2;
|
|
55691
|
+
let svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">`;
|
|
55692
|
+
svg += `
|
|
55693
|
+
<style>
|
|
55694
|
+
.pie-title { font-family: Arial, sans-serif; font-size: 16px; font-weight: 600; fill: #222; }
|
|
55695
|
+
.slice-label { font-family: Arial, sans-serif; font-size: 12px; fill: #222; dominant-baseline: middle; }
|
|
55696
|
+
.leader { stroke: #444; stroke-width: 1; fill: none; }
|
|
55697
|
+
.pieCircle { stroke: black; stroke-width: 2px; opacity: 0.7; }
|
|
55698
|
+
.pieOuterCircle { stroke: black; stroke-width: 2px; fill: none; }
|
|
55699
|
+
</style>`;
|
|
55700
|
+
if (model.title) {
|
|
55701
|
+
svg += `
|
|
55702
|
+
<text class="pie-title" x="${cx}" y="${pad + 8}" text-anchor="middle">${escapeXml(model.title)}</text>`;
|
|
55703
|
+
}
|
|
55704
|
+
svg += `
|
|
55705
|
+
<g class="pie" aria-label="pie">`;
|
|
55706
|
+
const minOutsideAngle = 0.35;
|
|
55707
|
+
slices.forEach((s3, i3) => {
|
|
55708
|
+
const pct = total > 0 ? Math.max(0, s3.value) / total : 0;
|
|
55709
|
+
const angle = 2 * Math.PI * pct;
|
|
55710
|
+
const end = start + angle;
|
|
55711
|
+
const large = angle > Math.PI ? 1 : 0;
|
|
55712
|
+
const c0 = polarToCartesian(cx, cy, radius, start);
|
|
55713
|
+
const c1 = polarToCartesian(cx, cy, radius, end);
|
|
55714
|
+
const d3 = [
|
|
55715
|
+
`M ${cx} ${cy}`,
|
|
55716
|
+
`L ${c0.x.toFixed(2)} ${c0.y.toFixed(2)}`,
|
|
55717
|
+
`A ${radius} ${radius} 0 ${large} 1 ${c1.x.toFixed(2)} ${c1.y.toFixed(2)}`,
|
|
55718
|
+
"Z"
|
|
55719
|
+
].join(" ");
|
|
55720
|
+
const fill = s3.color || palette(i3);
|
|
55721
|
+
svg += `
|
|
55722
|
+
<path d="${d3}" class="pieCircle" fill="${fill}" />`;
|
|
55723
|
+
const mid = (start + end) / 2;
|
|
55724
|
+
const cos = Math.cos(mid);
|
|
55725
|
+
const sin = Math.sin(mid);
|
|
55726
|
+
const percentLabel = escapeXml(formatPercent(s3.value, total));
|
|
55727
|
+
if (angle < minOutsideAngle) {
|
|
55728
|
+
const r1 = radius * 0.9;
|
|
55729
|
+
const r22 = radius * 1.06;
|
|
55730
|
+
const p1 = polarToCartesian(cx, cy, r1, mid);
|
|
55731
|
+
const p22 = polarToCartesian(cx, cy, r22, mid);
|
|
55732
|
+
const hlen = 12;
|
|
55733
|
+
const anchorLeft = cos < 0;
|
|
55734
|
+
const hx = anchorLeft ? p22.x - hlen : p22.x + hlen;
|
|
55735
|
+
const hy = p22.y;
|
|
55736
|
+
svg += `
|
|
55737
|
+
<path class="leader" d="M ${p1.x.toFixed(2)} ${p1.y.toFixed(2)} L ${p22.x.toFixed(2)} ${p22.y.toFixed(2)} L ${hx.toFixed(2)} ${hy.toFixed(2)}" />`;
|
|
55738
|
+
const tx = anchorLeft ? hx - 2 : hx + 2;
|
|
55739
|
+
const tAnchor = anchorLeft ? "end" : "start";
|
|
55740
|
+
svg += `
|
|
55741
|
+
<text class="slice-label" x="${tx.toFixed(2)}" y="${hy.toFixed(2)}" text-anchor="${tAnchor}">${percentLabel}</text>`;
|
|
55742
|
+
} else {
|
|
55743
|
+
const lr = radius * 0.62;
|
|
55744
|
+
const lp = { x: cx + lr * cos, y: cy + lr * sin };
|
|
55745
|
+
const tAnchor = Math.abs(cos) < 0.2 ? "middle" : cos > 0 ? "start" : "end";
|
|
55746
|
+
const avail = lr;
|
|
55747
|
+
const textW = measureText(percentLabel, 12);
|
|
55748
|
+
const anchor = textW > avail * 1.2 ? "middle" : tAnchor;
|
|
55749
|
+
svg += `
|
|
55750
|
+
<text class="slice-label" x="${lp.x.toFixed(2)}" y="${lp.y.toFixed(2)}" text-anchor="${anchor}">${percentLabel}</text>`;
|
|
55751
|
+
}
|
|
55752
|
+
start = end;
|
|
55753
|
+
});
|
|
55754
|
+
const rimStroke = opts.rimStroke || "black";
|
|
55755
|
+
const rimWidth = opts.rimStrokeWidth != null ? String(opts.rimStrokeWidth) : "2px";
|
|
55756
|
+
svg += `
|
|
55757
|
+
</g>
|
|
55758
|
+
<circle class="pie-rim pieOuterCircle" cx="${cx}" cy="${cy}" r="${radius}" stroke="${rimStroke}" stroke-width="${rimWidth}" fill="none" />`;
|
|
55759
|
+
if (legendItems.length) {
|
|
55760
|
+
const legendX = cx + radius + pad / 2;
|
|
55761
|
+
const totalH = legendItems.length * LEG_VSPACE;
|
|
55762
|
+
let legendY = cy - totalH / 2 + 10;
|
|
55763
|
+
svg += `
|
|
55764
|
+
<g class="legend">`;
|
|
55765
|
+
slices.forEach((s3, i3) => {
|
|
55766
|
+
const y2 = legendY + i3 * LEG_VSPACE;
|
|
55767
|
+
const fill = s3.color || palette(i3);
|
|
55768
|
+
const text = escapeXml(`${s3.label}${model.showData ? ` ${formatNumber(Number(s3.value))}` : ""}`);
|
|
55769
|
+
svg += `
|
|
55770
|
+
<rect x="${legendX}" y="${y2 - LEG_SW + 6}" width="${LEG_SW}" height="${LEG_SW}" fill="${fill}" stroke="${fill}" stroke-width="1" />`;
|
|
55771
|
+
svg += `
|
|
55772
|
+
<text class="slice-label legend-text" x="${legendX + LEG_SW + LEG_GAP}" y="${y2}" text-anchor="start">${text}</text>`;
|
|
55773
|
+
});
|
|
55774
|
+
svg += `
|
|
55775
|
+
</g>`;
|
|
55776
|
+
}
|
|
55777
|
+
svg += `
|
|
55778
|
+
</svg>`;
|
|
55779
|
+
return svg;
|
|
55780
|
+
}
|
|
55781
|
+
var init_pie_renderer = __esm({
|
|
55782
|
+
"node_modules/@probelabs/maid/out/renderer/pie-renderer.js"() {
|
|
55783
|
+
init_utils4();
|
|
55784
|
+
}
|
|
55785
|
+
});
|
|
55786
|
+
|
|
55787
|
+
// node_modules/@probelabs/maid/out/renderer/sequence-builder.js
|
|
55788
|
+
function textFromTokens(tokens) {
|
|
55789
|
+
if (!tokens || tokens.length === 0)
|
|
55790
|
+
return "";
|
|
55791
|
+
const parts = [];
|
|
55792
|
+
for (const t3 of tokens) {
|
|
55793
|
+
const img = t3.image;
|
|
55794
|
+
if (!img)
|
|
55795
|
+
continue;
|
|
55796
|
+
if (t3.tokenType && t3.tokenType.name === "QuotedString") {
|
|
55797
|
+
if (img.startsWith('"') && img.endsWith('"'))
|
|
55798
|
+
parts.push(img.slice(1, -1));
|
|
55799
|
+
else if (img.startsWith("'") && img.endsWith("'"))
|
|
55800
|
+
parts.push(img.slice(1, -1));
|
|
55801
|
+
else
|
|
55802
|
+
parts.push(img);
|
|
55803
|
+
} else {
|
|
55804
|
+
parts.push(img);
|
|
55805
|
+
}
|
|
55806
|
+
}
|
|
55807
|
+
return parts.join(" ").replace(/\s+/g, " ").trim();
|
|
55808
|
+
}
|
|
55809
|
+
function actorRefToText(refCst) {
|
|
55810
|
+
const ch = refCst.children || {};
|
|
55811
|
+
const toks = [];
|
|
55812
|
+
["Identifier", "QuotedString", "NumberLiteral", "Text"].forEach((k3) => {
|
|
55813
|
+
const a3 = ch[k3];
|
|
55814
|
+
a3?.forEach((t3) => toks.push(t3));
|
|
55815
|
+
});
|
|
55816
|
+
toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
|
|
55817
|
+
return textFromTokens(toks);
|
|
55818
|
+
}
|
|
55819
|
+
function lineRemainderToText(lineRem) {
|
|
55820
|
+
if (!lineRem)
|
|
55821
|
+
return void 0;
|
|
55822
|
+
const ch = lineRem.children || {};
|
|
55823
|
+
const toks = [];
|
|
55824
|
+
const order = [
|
|
55825
|
+
"Identifier",
|
|
55826
|
+
"NumberLiteral",
|
|
55827
|
+
"QuotedString",
|
|
55828
|
+
"Text",
|
|
55829
|
+
"Plus",
|
|
55830
|
+
"Minus",
|
|
55831
|
+
"Comma",
|
|
55832
|
+
"Colon",
|
|
55833
|
+
"LParen",
|
|
55834
|
+
"RParen",
|
|
55835
|
+
"AndKeyword",
|
|
55836
|
+
"ElseKeyword",
|
|
55837
|
+
"OptKeyword",
|
|
55838
|
+
"OptionKeyword",
|
|
55839
|
+
"LoopKeyword",
|
|
55840
|
+
"ParKeyword",
|
|
55841
|
+
"RectKeyword",
|
|
55842
|
+
"CriticalKeyword",
|
|
55843
|
+
"BreakKeyword",
|
|
55844
|
+
"BoxKeyword",
|
|
55845
|
+
"EndKeyword",
|
|
55846
|
+
"NoteKeyword",
|
|
55847
|
+
"LeftKeyword",
|
|
55848
|
+
"RightKeyword",
|
|
55849
|
+
"OverKeyword",
|
|
55850
|
+
"OfKeyword",
|
|
55851
|
+
"AutonumberKeyword",
|
|
55852
|
+
"OffKeyword",
|
|
55853
|
+
"LinkKeyword",
|
|
55854
|
+
"LinksKeyword",
|
|
55855
|
+
"CreateKeyword",
|
|
55856
|
+
"DestroyKeyword",
|
|
55857
|
+
"ParticipantKeyword",
|
|
55858
|
+
"ActorKeyword",
|
|
55859
|
+
"ActivateKeyword",
|
|
55860
|
+
"DeactivateKeyword"
|
|
55861
|
+
];
|
|
55862
|
+
for (const k3 of order)
|
|
55863
|
+
ch[k3]?.forEach((t3) => toks.push(t3));
|
|
55864
|
+
toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
|
|
55865
|
+
return textFromTokens(toks) || void 0;
|
|
55866
|
+
}
|
|
55867
|
+
function canonicalId(raw) {
|
|
55868
|
+
const t3 = raw.trim().replace(/\s+/g, "_");
|
|
55869
|
+
return t3;
|
|
55870
|
+
}
|
|
55871
|
+
function ensureParticipant(map4, byDisplay, idLike, display) {
|
|
55872
|
+
const idGuess = canonicalId(idLike);
|
|
55873
|
+
const existing = map4.get(idGuess) || (byDisplay.get(idLike) ? map4.get(byDisplay.get(idLike)) : void 0);
|
|
55874
|
+
if (existing)
|
|
55875
|
+
return existing;
|
|
55876
|
+
const p3 = { id: idGuess, display: display || idLike };
|
|
55877
|
+
map4.set(p3.id, p3);
|
|
55878
|
+
byDisplay.set(p3.display, p3.id);
|
|
55879
|
+
return p3;
|
|
55880
|
+
}
|
|
55881
|
+
function msgFromArrow(arrowCst) {
|
|
55882
|
+
const ch = arrowCst.children || {};
|
|
55883
|
+
if (ch.BidirAsyncDotted)
|
|
55884
|
+
return { line: "dotted", start: "arrow", end: "arrow", async: true };
|
|
55885
|
+
if (ch.BidirAsync)
|
|
55886
|
+
return { line: "solid", start: "arrow", end: "arrow", async: true };
|
|
55887
|
+
if (ch.DottedAsync)
|
|
55888
|
+
return { line: "dotted", start: "none", end: "arrow", async: true };
|
|
55889
|
+
if (ch.Async)
|
|
55890
|
+
return { line: "solid", start: "none", end: "arrow", async: true };
|
|
55891
|
+
if (ch.Dotted)
|
|
55892
|
+
return { line: "dotted", start: "none", end: "arrow" };
|
|
55893
|
+
if (ch.Solid)
|
|
55894
|
+
return { line: "solid", start: "none", end: "arrow" };
|
|
55895
|
+
if (ch.DottedCross)
|
|
55896
|
+
return { line: "dotted", start: "none", end: "cross" };
|
|
55897
|
+
if (ch.Cross)
|
|
55898
|
+
return { line: "solid", start: "none", end: "cross" };
|
|
55899
|
+
if (ch.DottedOpen)
|
|
55900
|
+
return { line: "dotted", start: "none", end: "open" };
|
|
55901
|
+
if (ch.Open)
|
|
55902
|
+
return { line: "solid", start: "none", end: "open" };
|
|
55903
|
+
return { line: "solid", start: "none", end: "arrow" };
|
|
55904
|
+
}
|
|
55905
|
+
function buildSequenceModel(text) {
|
|
55906
|
+
const { tokens } = tokenize3(text);
|
|
55907
|
+
parserInstance3.input = tokens;
|
|
55908
|
+
const cst = parserInstance3.diagram();
|
|
55909
|
+
const participantsMap = /* @__PURE__ */ new Map();
|
|
55910
|
+
const byDisplay = /* @__PURE__ */ new Map();
|
|
55911
|
+
const events = [];
|
|
55912
|
+
let autonumber = { on: false };
|
|
55913
|
+
const diagramChildren = cst.children || {};
|
|
55914
|
+
const lines = diagramChildren.line || [];
|
|
55915
|
+
const openBlocks = [];
|
|
55916
|
+
function processLineNode(ln) {
|
|
55917
|
+
const ch = ln.children || {};
|
|
55918
|
+
if (ch.participantDecl) {
|
|
55919
|
+
const decl = ch.participantDecl[0];
|
|
55920
|
+
const dch = decl.children || {};
|
|
55921
|
+
const ref1 = dch.actorRef?.[0];
|
|
55922
|
+
const ref2 = dch.actorRef?.[1];
|
|
55923
|
+
const idText = actorRefToText(ref1);
|
|
55924
|
+
const aliasText = ref2 ? actorRefToText(ref2) : void 0;
|
|
55925
|
+
const id = canonicalId(idText);
|
|
55926
|
+
const display = aliasText || idText;
|
|
55927
|
+
const p3 = ensureParticipant(participantsMap, byDisplay, id, display);
|
|
55928
|
+
events.push({ kind: "create", actor: p3.id, display: p3.display });
|
|
55929
|
+
return;
|
|
55930
|
+
}
|
|
55931
|
+
if (ch.autonumberStmt) {
|
|
55932
|
+
const stmt = ch.autonumberStmt[0];
|
|
55933
|
+
const sch = stmt.children || {};
|
|
55934
|
+
autonumber = { on: true };
|
|
55935
|
+
const nums = sch.NumberLiteral || [];
|
|
55936
|
+
if (nums.length >= 1)
|
|
55937
|
+
autonumber.start = Number(nums[0].image);
|
|
55938
|
+
if (nums.length >= 2)
|
|
55939
|
+
autonumber.step = Number(nums[1].image);
|
|
55940
|
+
if (sch.OffKeyword)
|
|
55941
|
+
autonumber = { on: false };
|
|
55942
|
+
return;
|
|
55943
|
+
}
|
|
55944
|
+
if (ch.activateStmt) {
|
|
55945
|
+
const st = ch.activateStmt[0];
|
|
55946
|
+
const sch = st.children || {};
|
|
55947
|
+
const idTxt = actorRefToText(sch.actorRef?.[0]);
|
|
55948
|
+
const p3 = ensureParticipant(participantsMap, byDisplay, idTxt);
|
|
55949
|
+
events.push({ kind: "activate", actor: p3.id });
|
|
55950
|
+
return;
|
|
55951
|
+
}
|
|
55952
|
+
if (ch.deactivateStmt) {
|
|
55953
|
+
const st = ch.deactivateStmt[0];
|
|
55954
|
+
const sch = st.children || {};
|
|
55955
|
+
const idTxt = actorRefToText(sch.actorRef?.[0]);
|
|
55956
|
+
const p3 = ensureParticipant(participantsMap, byDisplay, idTxt);
|
|
55957
|
+
events.push({ kind: "deactivate", actor: p3.id });
|
|
55958
|
+
return;
|
|
55959
|
+
}
|
|
55960
|
+
if (ch.createStmt) {
|
|
55961
|
+
const st = ch.createStmt[0];
|
|
55962
|
+
const sch = st.children || {};
|
|
55963
|
+
const idTxt = actorRefToText(sch.actorRef?.[0]);
|
|
55964
|
+
const alias = sch.lineRemainder ? lineRemainderToText(sch.lineRemainder[0]) : void 0;
|
|
55965
|
+
const p3 = ensureParticipant(participantsMap, byDisplay, idTxt, alias || idTxt);
|
|
55966
|
+
events.push({ kind: "create", actor: p3.id, display: p3.display });
|
|
55967
|
+
return;
|
|
55968
|
+
}
|
|
55969
|
+
if (ch.destroyStmt) {
|
|
55970
|
+
const st = ch.destroyStmt[0];
|
|
55971
|
+
const sch = st.children || {};
|
|
55972
|
+
const idTxt = actorRefToText(sch.actorRef?.[0]);
|
|
55973
|
+
const p3 = ensureParticipant(participantsMap, byDisplay, idTxt);
|
|
55974
|
+
events.push({ kind: "destroy", actor: p3.id });
|
|
55975
|
+
return;
|
|
55976
|
+
}
|
|
55977
|
+
if (ch.noteStmt) {
|
|
55978
|
+
const st = ch.noteStmt[0];
|
|
55979
|
+
const sch = st.children || {};
|
|
55980
|
+
const text2 = lineRemainderToText(sch.lineRemainder?.[0]) || "";
|
|
55981
|
+
if (sch.LeftKeyword || sch.RightKeyword) {
|
|
55982
|
+
const pos = sch.LeftKeyword ? "leftOf" : "rightOf";
|
|
55983
|
+
const actorTxt = actorRefToText(sch.actorRef?.[0]);
|
|
55984
|
+
const p3 = ensureParticipant(participantsMap, byDisplay, actorTxt);
|
|
55985
|
+
const note = { pos, actors: [p3.id], text: text2 };
|
|
55986
|
+
events.push({ kind: "note", note });
|
|
55987
|
+
} else if (sch.OverKeyword) {
|
|
55988
|
+
const a1 = actorRefToText(sch.actorRef?.[0]);
|
|
55989
|
+
const a22 = sch.actorRef?.[1] ? actorRefToText(sch.actorRef?.[1]) : void 0;
|
|
55990
|
+
const p1 = ensureParticipant(participantsMap, byDisplay, a1);
|
|
55991
|
+
const ids = [p1.id];
|
|
55992
|
+
if (a22) {
|
|
55993
|
+
const p22 = ensureParticipant(participantsMap, byDisplay, a22);
|
|
55994
|
+
ids.push(p22.id);
|
|
55995
|
+
}
|
|
55996
|
+
events.push({ kind: "note", note: { pos: "over", actors: ids, text: text2 } });
|
|
55997
|
+
}
|
|
55998
|
+
return;
|
|
55999
|
+
}
|
|
56000
|
+
const blockKinds = [
|
|
56001
|
+
{ key: "altBlock", type: "alt", branchKeys: [{ key: "ElseKeyword", kind: "else" }] },
|
|
56002
|
+
{ key: "optBlock", type: "opt" },
|
|
56003
|
+
{ key: "loopBlock", type: "loop" },
|
|
56004
|
+
{ key: "parBlock", type: "par", branchKeys: [{ key: "AndKeyword", kind: "and" }] },
|
|
56005
|
+
{ key: "criticalBlock", type: "critical", branchKeys: [{ key: "OptionKeyword", kind: "option" }] },
|
|
56006
|
+
{ key: "breakBlock", type: "break" },
|
|
56007
|
+
{ key: "rectBlock", type: "rect" },
|
|
56008
|
+
{ key: "boxBlock", type: "box" }
|
|
56009
|
+
];
|
|
56010
|
+
let handledBlock = false;
|
|
56011
|
+
for (const spec of blockKinds) {
|
|
56012
|
+
if (ch[spec.key]) {
|
|
56013
|
+
handledBlock = true;
|
|
56014
|
+
const bnode = ch[spec.key][0];
|
|
56015
|
+
const bch = bnode.children || {};
|
|
56016
|
+
const title = lineRemainderToText(bch.lineRemainder?.[0]);
|
|
56017
|
+
const block = { type: spec.type, title, branches: spec.branchKeys ? [] : void 0 };
|
|
56018
|
+
openBlocks.push(block);
|
|
56019
|
+
events.push({ kind: "block-start", block });
|
|
56020
|
+
if (spec.branchKeys) {
|
|
56021
|
+
const newlines = bch.Newline || [];
|
|
56022
|
+
const branchKey = spec.branchKeys[0].key;
|
|
56023
|
+
const branchTokArr = bch[branchKey];
|
|
56024
|
+
const lrArr = bch.lineRemainder;
|
|
56025
|
+
if (branchTokArr && branchTokArr.length) {
|
|
56026
|
+
const lr = (lrArr || []).slice(1);
|
|
56027
|
+
for (let i3 = 0; i3 < branchTokArr.length; i3++) {
|
|
56028
|
+
const title2 = lr[i3] ? lineRemainderToText(lr[i3]) : void 0;
|
|
56029
|
+
const br = { kind: spec.branchKeys[0].kind, title: title2 };
|
|
56030
|
+
block.branches.push(br);
|
|
56031
|
+
events.push({ kind: "block-branch", block, branch: br });
|
|
56032
|
+
}
|
|
56033
|
+
}
|
|
56034
|
+
}
|
|
56035
|
+
events.push({ kind: "block-end", block });
|
|
56036
|
+
openBlocks.pop();
|
|
56037
|
+
break;
|
|
56038
|
+
}
|
|
56039
|
+
}
|
|
56040
|
+
if (handledBlock)
|
|
56041
|
+
return;
|
|
56042
|
+
if (ch.messageStmt) {
|
|
56043
|
+
const st = ch.messageStmt[0];
|
|
56044
|
+
const sch = st.children || {};
|
|
56045
|
+
const fromTxt = actorRefToText(sch.actorRef?.[0]);
|
|
56046
|
+
const toTxt = actorRefToText(sch.actorRef?.[1]);
|
|
56047
|
+
const from = ensureParticipant(participantsMap, byDisplay, fromTxt).id;
|
|
56048
|
+
const to = ensureParticipant(participantsMap, byDisplay, toTxt).id;
|
|
56049
|
+
const arrow = msgFromArrow(sch.arrow?.[0]);
|
|
56050
|
+
const text2 = lineRemainderToText(sch.lineRemainder?.[0]);
|
|
56051
|
+
const activateTarget = !!sch.Plus;
|
|
56052
|
+
const deactivateTarget = !!sch.Minus;
|
|
56053
|
+
const msg = { from, to, text: text2, line: arrow.line, startMarker: arrow.start, endMarker: arrow.end, async: arrow.async, activateTarget, deactivateTarget };
|
|
56054
|
+
events.push({ kind: "message", msg });
|
|
56055
|
+
return;
|
|
56056
|
+
}
|
|
56057
|
+
if (ch.linkStmt) {
|
|
56058
|
+
events.push({ kind: "noop" });
|
|
56059
|
+
return;
|
|
56060
|
+
}
|
|
56061
|
+
events.push({ kind: "noop" });
|
|
56062
|
+
}
|
|
56063
|
+
function collectInnerLines(blockNode) {
|
|
56064
|
+
const out = [];
|
|
56065
|
+
const ch = blockNode.children || {};
|
|
56066
|
+
for (const key of Object.keys(ch)) {
|
|
56067
|
+
const arr = ch[key];
|
|
56068
|
+
if (Array.isArray(arr)) {
|
|
56069
|
+
for (const node of arr) {
|
|
56070
|
+
if (node && typeof node === "object" && node.name === "line")
|
|
56071
|
+
out.push(node);
|
|
56072
|
+
}
|
|
56073
|
+
}
|
|
56074
|
+
}
|
|
56075
|
+
return out;
|
|
56076
|
+
}
|
|
56077
|
+
for (const ln of lines) {
|
|
56078
|
+
processLineNode(ln);
|
|
56079
|
+
const ch = ln.children || {};
|
|
56080
|
+
const block = ch.altBlock?.[0] || ch.optBlock?.[0] || ch.loopBlock?.[0] || ch.parBlock?.[0] || ch.criticalBlock?.[0] || ch.breakBlock?.[0] || ch.rectBlock?.[0] || ch.boxBlock?.[0];
|
|
56081
|
+
if (block) {
|
|
56082
|
+
for (const inner of collectInnerLines(block))
|
|
56083
|
+
processLineNode(inner);
|
|
56084
|
+
}
|
|
56085
|
+
}
|
|
56086
|
+
return {
|
|
56087
|
+
participants: Array.from(participantsMap.values()),
|
|
56088
|
+
events,
|
|
56089
|
+
autonumber: autonumber.on === true || autonumber.on === false ? autonumber : { on: false }
|
|
56090
|
+
};
|
|
56091
|
+
}
|
|
56092
|
+
var init_sequence_builder = __esm({
|
|
56093
|
+
"node_modules/@probelabs/maid/out/renderer/sequence-builder.js"() {
|
|
56094
|
+
init_lexer4();
|
|
56095
|
+
init_parser4();
|
|
56096
|
+
}
|
|
56097
|
+
});
|
|
56098
|
+
|
|
56099
|
+
// node_modules/@probelabs/maid/out/renderer/sequence-layout.js
|
|
56100
|
+
function layoutSequence(model) {
|
|
56101
|
+
const order = [];
|
|
56102
|
+
const seen = /* @__PURE__ */ new Set();
|
|
56103
|
+
const partById = new Map(model.participants.map((p3) => [p3.id, p3]));
|
|
56104
|
+
function touch(id) {
|
|
56105
|
+
if (!seen.has(id)) {
|
|
56106
|
+
seen.add(id);
|
|
56107
|
+
order.push(id);
|
|
56108
|
+
}
|
|
56109
|
+
}
|
|
56110
|
+
for (const ev of model.events) {
|
|
56111
|
+
if (ev.kind === "message") {
|
|
56112
|
+
touch(ev.msg.from);
|
|
56113
|
+
touch(ev.msg.to);
|
|
56114
|
+
}
|
|
56115
|
+
if (ev.kind === "note") {
|
|
56116
|
+
ev.note.actors.forEach(touch);
|
|
56117
|
+
}
|
|
56118
|
+
if (ev.kind === "activate" || ev.kind === "deactivate" || ev.kind === "create" || ev.kind === "destroy")
|
|
56119
|
+
touch(ev.actor);
|
|
56120
|
+
}
|
|
56121
|
+
for (const p3 of model.participants)
|
|
56122
|
+
touch(p3.id);
|
|
56123
|
+
const participants = [];
|
|
56124
|
+
let x3 = MARGIN_X;
|
|
56125
|
+
for (const id of order) {
|
|
56126
|
+
const p3 = partById.get(id) || { id, display: id };
|
|
56127
|
+
const w3 = Math.max(COL_MIN, measureText(p3.display, ACTOR_FONT_SIZE) + ACTOR_PAD_X * 2);
|
|
56128
|
+
participants.push({ id, display: p3.display, x: x3, y: MARGIN_Y, width: w3, height: ACTOR_H });
|
|
56129
|
+
x3 += w3 + MARGIN_X;
|
|
56130
|
+
}
|
|
56131
|
+
const width = Math.max(320, x3);
|
|
56132
|
+
const rowIndexForEvent = /* @__PURE__ */ new Map();
|
|
56133
|
+
let row = 0;
|
|
56134
|
+
const openBlocks = [];
|
|
56135
|
+
function consumeRow(idx) {
|
|
56136
|
+
rowIndexForEvent.set(idx, row++);
|
|
56137
|
+
}
|
|
56138
|
+
model.events.forEach((ev, idx) => {
|
|
56139
|
+
switch (ev.kind) {
|
|
56140
|
+
case "message":
|
|
56141
|
+
consumeRow(idx);
|
|
56142
|
+
break;
|
|
56143
|
+
case "note":
|
|
56144
|
+
consumeRow(idx);
|
|
56145
|
+
break;
|
|
56146
|
+
case "block-start":
|
|
56147
|
+
openBlocks.push({ block: ev.block, startRow: row, branches: [] });
|
|
56148
|
+
consumeRow(idx);
|
|
56149
|
+
break;
|
|
56150
|
+
case "block-branch": {
|
|
56151
|
+
const top = openBlocks[openBlocks.length - 1];
|
|
56152
|
+
if (top)
|
|
56153
|
+
top.branches.push({ title: ev.branch.title, row });
|
|
56154
|
+
consumeRow(idx);
|
|
56155
|
+
break;
|
|
56156
|
+
}
|
|
56157
|
+
case "block-end":
|
|
56158
|
+
break;
|
|
56159
|
+
case "activate":
|
|
56160
|
+
case "deactivate":
|
|
56161
|
+
case "create":
|
|
56162
|
+
case "destroy":
|
|
56163
|
+
case "noop":
|
|
56164
|
+
break;
|
|
56165
|
+
}
|
|
56166
|
+
});
|
|
56167
|
+
const lifelineTop = MARGIN_Y + ACTOR_H + LIFELINE_GAP;
|
|
56168
|
+
const contentHeight = row * ROW_H;
|
|
56169
|
+
const height = lifelineTop + contentHeight + MARGIN_Y + ACTOR_H;
|
|
56170
|
+
const lifelines = participants.map((p3) => ({ x: p3.x + p3.width / 2, y1: lifelineTop, y2: height - MARGIN_Y - ACTOR_H }));
|
|
56171
|
+
function yForRow(r3) {
|
|
56172
|
+
return lifelineTop + r3 * ROW_H + ROW_H / 2;
|
|
56173
|
+
}
|
|
56174
|
+
const col = new Map(participants.map((p3) => [p3.id, p3]));
|
|
56175
|
+
const messages = [];
|
|
56176
|
+
const notes = [];
|
|
56177
|
+
const blocks = [];
|
|
56178
|
+
const activations = [];
|
|
56179
|
+
const actStack = /* @__PURE__ */ new Map();
|
|
56180
|
+
const startAct = (actor, r3) => {
|
|
56181
|
+
const arr = actStack.get(actor) || [];
|
|
56182
|
+
arr.push(r3);
|
|
56183
|
+
actStack.set(actor, arr);
|
|
56184
|
+
};
|
|
56185
|
+
const endAct = (actor, r3) => {
|
|
56186
|
+
const arr = actStack.get(actor) || [];
|
|
56187
|
+
const start = arr.pop();
|
|
56188
|
+
if (start != null) {
|
|
56189
|
+
const p3 = col.get(actor);
|
|
56190
|
+
if (p3) {
|
|
56191
|
+
activations.push({ actor, x: p3.x + p3.width / 2 - 4, y: yForRow(start) - ROW_H / 2, width: 8, height: yForRow(r3) - yForRow(start) });
|
|
56192
|
+
}
|
|
53368
56193
|
}
|
|
53369
|
-
|
|
53370
|
-
|
|
53371
|
-
|
|
53372
|
-
|
|
53373
|
-
|
|
53374
|
-
|
|
56194
|
+
actStack.set(actor, arr);
|
|
56195
|
+
};
|
|
56196
|
+
const openForLayout = [];
|
|
56197
|
+
model.events.forEach((ev, idx) => {
|
|
56198
|
+
const r3 = rowIndexForEvent.has(idx) ? rowIndexForEvent.get(idx) : null;
|
|
56199
|
+
switch (ev.kind) {
|
|
56200
|
+
case "message": {
|
|
56201
|
+
const p1 = col.get(ev.msg.from), p22 = col.get(ev.msg.to);
|
|
56202
|
+
if (p1 && p22 && r3 != null) {
|
|
56203
|
+
const y2 = yForRow(r3);
|
|
56204
|
+
const x1 = p1.x + p1.width / 2;
|
|
56205
|
+
const x22 = p22.x + p22.width / 2;
|
|
56206
|
+
messages.push({ from: p1.id, to: p22.id, text: ev.msg.text, y: y2, x1, x2: x22, line: ev.msg.line, startMarker: ev.msg.startMarker, endMarker: ev.msg.endMarker, async: ev.msg.async });
|
|
56207
|
+
if (ev.msg.activateTarget)
|
|
56208
|
+
startAct(ev.msg.to, r3);
|
|
56209
|
+
if (ev.msg.deactivateTarget)
|
|
56210
|
+
endAct(ev.msg.to, r3);
|
|
56211
|
+
const top = openForLayout[openForLayout.length - 1];
|
|
56212
|
+
if (top)
|
|
56213
|
+
top.lastRow = r3;
|
|
56214
|
+
}
|
|
56215
|
+
break;
|
|
56216
|
+
}
|
|
56217
|
+
case "note": {
|
|
56218
|
+
if (r3 == null)
|
|
56219
|
+
break;
|
|
56220
|
+
const estLines = (text, width2) => {
|
|
56221
|
+
const charsPerLine = Math.max(8, Math.floor((width2 - NOTE_PAD * 2) / 7));
|
|
56222
|
+
const length = text ? text.length : 0;
|
|
56223
|
+
return Math.max(1, Math.ceil(length / charsPerLine));
|
|
56224
|
+
};
|
|
56225
|
+
const y2 = yForRow(r3) - NOTE_PAD;
|
|
56226
|
+
if (ev.note.pos === "over") {
|
|
56227
|
+
const [a3, b3] = ev.note.actors;
|
|
56228
|
+
const p1 = col.get(a3), p22 = b3 ? col.get(b3) : p1;
|
|
56229
|
+
if (p1 && p22) {
|
|
56230
|
+
const left = Math.min(p1.x + p1.width / 2, p22.x + p22.width / 2);
|
|
56231
|
+
const right = Math.max(p1.x + p1.width / 2, p22.x + p22.width / 2);
|
|
56232
|
+
const w3 = right - left + NOTE_PAD * 2;
|
|
56233
|
+
const lines = estLines(ev.note.text, w3);
|
|
56234
|
+
const h3 = Math.max(ROW_H - NOTE_PAD, lines * 16 + NOTE_PAD);
|
|
56235
|
+
notes.push({ x: left - NOTE_PAD, y: y2, width: w3, height: h3, text: ev.note.text, anchor: "over" });
|
|
56236
|
+
}
|
|
56237
|
+
} else {
|
|
56238
|
+
const actor = ev.note.actors[0];
|
|
56239
|
+
const p3 = col.get(actor);
|
|
56240
|
+
if (p3) {
|
|
56241
|
+
const leftSide = ev.note.pos === "leftOf";
|
|
56242
|
+
const x4 = leftSide ? p3.x - NOTE_W - 10 : p3.x + p3.width + 10;
|
|
56243
|
+
const lines = estLines(ev.note.text, NOTE_W);
|
|
56244
|
+
const h3 = Math.max(ROW_H - NOTE_PAD, lines * 16 + NOTE_PAD);
|
|
56245
|
+
notes.push({ x: x4, y: y2, width: NOTE_W, height: h3, text: ev.note.text, anchor: leftSide ? "left" : "right" });
|
|
56246
|
+
}
|
|
56247
|
+
}
|
|
56248
|
+
const top = openForLayout[openForLayout.length - 1];
|
|
56249
|
+
if (top && r3 != null)
|
|
56250
|
+
top.lastRow = r3;
|
|
56251
|
+
break;
|
|
56252
|
+
}
|
|
56253
|
+
case "activate":
|
|
56254
|
+
if (r3 != null)
|
|
56255
|
+
startAct(ev.actor, r3);
|
|
56256
|
+
break;
|
|
56257
|
+
case "deactivate":
|
|
56258
|
+
if (r3 != null)
|
|
56259
|
+
endAct(ev.actor, r3);
|
|
56260
|
+
break;
|
|
56261
|
+
case "block-start": {
|
|
56262
|
+
const startRow = r3 != null ? r3 : row;
|
|
56263
|
+
openForLayout.push({ block: ev.block, startRow, branches: [] });
|
|
56264
|
+
break;
|
|
56265
|
+
}
|
|
56266
|
+
case "block-branch": {
|
|
56267
|
+
const top = openForLayout[openForLayout.length - 1];
|
|
56268
|
+
if (top && r3 != null) {
|
|
56269
|
+
top.branches.push({ title: ev.branch.title, row: r3 });
|
|
56270
|
+
top.lastRow = r3;
|
|
56271
|
+
}
|
|
56272
|
+
break;
|
|
56273
|
+
}
|
|
56274
|
+
case "block-end": {
|
|
56275
|
+
const top = openForLayout.pop();
|
|
56276
|
+
if (top) {
|
|
56277
|
+
const first2 = participants.length > 0 ? participants[0] : void 0;
|
|
56278
|
+
const last2 = participants.length > 0 ? participants[participants.length - 1] : void 0;
|
|
56279
|
+
const left = first2 ? first2.x : MARGIN_X;
|
|
56280
|
+
const right = last2 ? last2.x + last2.width : left + 200;
|
|
56281
|
+
const yTop = yForRow(top.startRow) - ROW_H / 2 - (BLOCK_PAD + TITLE_EXTRA_TOP);
|
|
56282
|
+
const endRow = top.lastRow != null ? top.lastRow : top.startRow;
|
|
56283
|
+
const yBot = yForRow(endRow) + ROW_H / 2 + BLOCK_PAD;
|
|
56284
|
+
const layout = { type: top.block.type, title: top.block.title, x: left - BLOCK_PAD, y: yTop, width: right - left + BLOCK_PAD * 2, height: yBot - yTop };
|
|
56285
|
+
if (top.branches.length)
|
|
56286
|
+
layout.branches = top.branches.map((b3) => ({ title: b3.title, y: yForRow(b3.row) - ROW_H / 2 }));
|
|
56287
|
+
blocks.push(layout);
|
|
56288
|
+
}
|
|
56289
|
+
break;
|
|
56290
|
+
}
|
|
56291
|
+
default:
|
|
56292
|
+
break;
|
|
53375
56293
|
}
|
|
56294
|
+
});
|
|
56295
|
+
const lastRow = row;
|
|
56296
|
+
for (const [actor, arr] of actStack.entries()) {
|
|
56297
|
+
while (arr.length) {
|
|
56298
|
+
const start = arr.pop();
|
|
56299
|
+
const p3 = col.get(actor);
|
|
56300
|
+
if (p3)
|
|
56301
|
+
activations.push({ actor, x: p3.x + p3.width / 2 - 4, y: yForRow(start) - ROW_H / 2, width: 8, height: yForRow(lastRow) - yForRow(start) });
|
|
56302
|
+
}
|
|
56303
|
+
}
|
|
56304
|
+
return { width, height, participants, lifelines, messages, notes, blocks, activations };
|
|
56305
|
+
}
|
|
56306
|
+
var MARGIN_X, MARGIN_Y, ACTOR_FONT_SIZE, ACTOR_H, LIFELINE_GAP, ACTOR_PAD_X, COL_MIN, ROW_H, NOTE_W, NOTE_PAD, BLOCK_PAD, TITLE_EXTRA_TOP;
|
|
56307
|
+
var init_sequence_layout = __esm({
|
|
56308
|
+
"node_modules/@probelabs/maid/out/renderer/sequence-layout.js"() {
|
|
56309
|
+
init_utils4();
|
|
56310
|
+
MARGIN_X = 24;
|
|
56311
|
+
MARGIN_Y = 24;
|
|
56312
|
+
ACTOR_FONT_SIZE = 16;
|
|
56313
|
+
ACTOR_H = 32;
|
|
56314
|
+
LIFELINE_GAP = 4;
|
|
56315
|
+
ACTOR_PAD_X = 12;
|
|
56316
|
+
COL_MIN = 110;
|
|
56317
|
+
ROW_H = 36;
|
|
56318
|
+
NOTE_W = 160;
|
|
56319
|
+
NOTE_PAD = 8;
|
|
56320
|
+
BLOCK_PAD = 8;
|
|
56321
|
+
TITLE_EXTRA_TOP = 12;
|
|
56322
|
+
}
|
|
56323
|
+
});
|
|
56324
|
+
|
|
56325
|
+
// node_modules/@probelabs/maid/out/renderer/sequence-renderer.js
|
|
56326
|
+
function renderSequence(model, opts = {}) {
|
|
56327
|
+
const layout = layoutSequence(model);
|
|
56328
|
+
const svgParts = [];
|
|
56329
|
+
const width = Math.ceil(layout.width);
|
|
56330
|
+
const height = Math.ceil(layout.height);
|
|
56331
|
+
svgParts.push(`<svg xmlns="http://www.w3.org/2000/svg" width="${width + 50}" height="${height + 40}" viewBox="-50 -10 ${width + 50} ${height + 40}">`);
|
|
56332
|
+
const sharedCss = buildSharedCss({
|
|
56333
|
+
fontFamily: "Arial, sans-serif",
|
|
56334
|
+
fontSize: 14,
|
|
56335
|
+
nodeFill: "#eef0ff",
|
|
56336
|
+
nodeStroke: "#3f3f3f",
|
|
56337
|
+
edgeStroke: "#555555"
|
|
56338
|
+
});
|
|
56339
|
+
svgParts.push(` <style>${sharedCss}</style>`);
|
|
56340
|
+
for (const p3 of layout.participants)
|
|
56341
|
+
drawParticipant(svgParts, p3);
|
|
56342
|
+
for (const b3 of layout.blocks)
|
|
56343
|
+
svgParts.push(blockBackground(b3.x, b3.y, b3.width, b3.height, 0));
|
|
56344
|
+
for (const l3 of layout.lifelines)
|
|
56345
|
+
svgParts.push(` <line class="lifeline" x1="${l3.x}" y1="${l3.y1}" x2="${l3.x}" y2="${l3.y2}"/>`);
|
|
56346
|
+
for (const a3 of layout.activations)
|
|
56347
|
+
svgParts.push(` <rect class="activation" x="${a3.x}" y="${a3.y}" width="${a3.width}" height="${a3.height}" />`);
|
|
56348
|
+
let counter = model.autonumber?.on ? model.autonumber.start ?? 1 : void 0;
|
|
56349
|
+
const step = model.autonumber?.on ? model.autonumber.step ?? 1 : void 0;
|
|
56350
|
+
for (const m3 of layout.messages) {
|
|
56351
|
+
drawMessage(svgParts, m3);
|
|
56352
|
+
const label = formatMessageLabel(m3.text, counter);
|
|
56353
|
+
if (label)
|
|
56354
|
+
drawMessageLabel(svgParts, m3, label, counter);
|
|
56355
|
+
if (counter != null)
|
|
56356
|
+
counter += step;
|
|
56357
|
+
}
|
|
56358
|
+
for (const n3 of layout.notes)
|
|
56359
|
+
drawNote(svgParts, n3);
|
|
56360
|
+
for (const b3 of layout.blocks) {
|
|
56361
|
+
const title = b3.title ? `${b3.type}: ${b3.title}` : b3.type;
|
|
56362
|
+
const branches = (b3.branches || []).map((br) => ({ y: br.y, title: br.title }));
|
|
56363
|
+
svgParts.push(blockOverlay(b3.x, b3.y, b3.width, b3.height, title, branches, 0, "left", "left", 0));
|
|
56364
|
+
}
|
|
56365
|
+
for (const p3 of layout.participants)
|
|
56366
|
+
drawParticipantBottom(svgParts, p3, layout);
|
|
56367
|
+
svgParts.push("</svg>");
|
|
56368
|
+
let svg = svgParts.join("\n");
|
|
56369
|
+
if (opts.theme)
|
|
56370
|
+
svg = applySequenceTheme(svg, opts.theme);
|
|
56371
|
+
return svg;
|
|
56372
|
+
}
|
|
56373
|
+
function drawParticipant(out, p3) {
|
|
56374
|
+
out.push(` <g class="actor" transform="translate(${p3.x},${p3.y})">`);
|
|
56375
|
+
out.push(` <rect class="node-shape" width="${p3.width}" height="${p3.height}" rx="0"/>`);
|
|
56376
|
+
out.push(` <text class="node-label" x="${p3.width / 2}" y="${p3.height / 2}" text-anchor="middle" dominant-baseline="middle">${escapeXml(p3.display)}</text>`);
|
|
56377
|
+
out.push(" </g>");
|
|
56378
|
+
}
|
|
56379
|
+
function drawParticipantBottom(out, p3, layout) {
|
|
56380
|
+
const lifeline = layout.lifelines.find((l3) => Math.abs(l3.x - (p3.x + p3.width / 2)) < 1e-3);
|
|
56381
|
+
const y2 = lifeline ? lifeline.y2 : layout.height - 28;
|
|
56382
|
+
out.push(` <g class="actor" transform="translate(${p3.x},${y2})">`);
|
|
56383
|
+
out.push(` <rect class="node-shape" width="${p3.width}" height="${p3.height}" rx="0"/>`);
|
|
56384
|
+
out.push(` <text class="node-label" x="${p3.width / 2}" y="${p3.height / 2}" text-anchor="middle" dominant-baseline="middle">${escapeXml(p3.display)}</text>`);
|
|
56385
|
+
out.push(" </g>");
|
|
56386
|
+
}
|
|
56387
|
+
function drawMessage(out, m3) {
|
|
56388
|
+
const cls = `msg-line ${m3.line}`.trim();
|
|
56389
|
+
const x1 = m3.x1, x22 = m3.x2, y2 = m3.y;
|
|
56390
|
+
out.push(` <path class="${cls}" d="M ${x1} ${y2} L ${x22} ${y2}" />`);
|
|
56391
|
+
const start = { x: x1, y: y2 };
|
|
56392
|
+
const end = { x: x22, y: y2 };
|
|
56393
|
+
if (m3.endMarker === "arrow")
|
|
56394
|
+
out.push(" " + triangleAtEnd(start, end));
|
|
56395
|
+
if (m3.startMarker === "arrow")
|
|
56396
|
+
out.push(" " + triangleAtStart(start, end));
|
|
56397
|
+
if (m3.endMarker === "open")
|
|
56398
|
+
out.push(` <circle class="openhead" cx="${x22}" cy="${y2}" r="4" />`);
|
|
56399
|
+
if (m3.startMarker === "open")
|
|
56400
|
+
out.push(` <circle class="openhead" cx="${x1}" cy="${y2}" r="4" />`);
|
|
56401
|
+
if (m3.endMarker === "cross")
|
|
56402
|
+
out.push(` <g class="crosshead" transform="translate(${x22},${y2})"><path d="M -4 -4 L 4 4"/><path d="M -4 4 L 4 -4"/></g>`);
|
|
56403
|
+
if (m3.startMarker === "cross")
|
|
56404
|
+
out.push(` <g class="crosshead" transform="translate(${x1},${y2})"><path d="M -4 -4 L 4 4"/><path d="M -4 4 L 4 -4"/></g>`);
|
|
56405
|
+
}
|
|
56406
|
+
function formatMessageLabel(text, counter) {
|
|
56407
|
+
if (!text && counter == null)
|
|
56408
|
+
return void 0;
|
|
56409
|
+
if (counter != null && text)
|
|
56410
|
+
return `${counter}: ${text}`;
|
|
56411
|
+
if (counter != null)
|
|
56412
|
+
return String(counter);
|
|
56413
|
+
return text;
|
|
56414
|
+
}
|
|
56415
|
+
function drawMessageLabel(out, m3, label, _counter) {
|
|
56416
|
+
const xMid = (m3.x1 + m3.x2) / 2;
|
|
56417
|
+
const h3 = 16;
|
|
56418
|
+
const w3 = Math.max(20, measureText(label, 12) + 10);
|
|
56419
|
+
const x3 = xMid - w3 / 2;
|
|
56420
|
+
const y2 = m3.y - 10 - h3 / 2;
|
|
56421
|
+
out.push(` <rect class="msg-label-bg" x="${x3}" y="${y2}" width="${w3}" height="${h3}" rx="0"/>`);
|
|
56422
|
+
out.push(` <text class="msg-label" x="${xMid}" y="${y2 + h3 / 2}" text-anchor="middle">${escapeXml(label)}</text>`);
|
|
56423
|
+
}
|
|
56424
|
+
function drawNote(out, n3) {
|
|
56425
|
+
out.push(` <g class="note" transform="translate(${n3.x},${n3.y})">`);
|
|
56426
|
+
out.push(` <rect width="${n3.width}" height="${n3.height}" rx="0"/>`);
|
|
56427
|
+
out.push(` <text class="note-text" x="${n3.width / 2}" y="${n3.height / 2 + 4}" text-anchor="middle">${escapeXml(n3.text)}</text>`);
|
|
56428
|
+
out.push(" </g>");
|
|
56429
|
+
}
|
|
56430
|
+
function applySequenceTheme(svg, theme) {
|
|
56431
|
+
let out = svg;
|
|
56432
|
+
if (theme.actorBkg)
|
|
56433
|
+
out = out.replace(/\.actor-rect\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.actorBkg)};`));
|
|
56434
|
+
if (theme.actorBorder)
|
|
56435
|
+
out = out.replace(/\.actor-rect\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.actorBorder)};`));
|
|
56436
|
+
if (theme.actorTextColor)
|
|
56437
|
+
out = out.replace(/\.actor-label\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.actorTextColor)};`));
|
|
56438
|
+
if (theme.lifelineColor)
|
|
56439
|
+
out = out.replace(/\.lifeline\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.lifelineColor)};`));
|
|
56440
|
+
if (theme.lineColor)
|
|
56441
|
+
out = out.replace(/\.msg-line\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.lineColor)};`));
|
|
56442
|
+
if (theme.arrowheadColor) {
|
|
56443
|
+
out = out.replace(/\.arrowhead\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.arrowheadColor)};`));
|
|
56444
|
+
out = out.replace(/\.openhead\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
|
|
56445
|
+
out = out.replace(/\.crosshead\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
|
|
56446
|
+
}
|
|
56447
|
+
if (theme.noteBkg)
|
|
56448
|
+
out = out.replace(/\.note\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.noteBkg)};`));
|
|
56449
|
+
if (theme.noteBorder)
|
|
56450
|
+
out = out.replace(/\.note\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.noteBorder)};`));
|
|
56451
|
+
if (theme.noteTextColor)
|
|
56452
|
+
out = out.replace(/\.note-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.noteTextColor)};`));
|
|
56453
|
+
if (theme.activationBkg)
|
|
56454
|
+
out = out.replace(/\.activation\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.activationBkg)};`));
|
|
56455
|
+
if (theme.activationBorder)
|
|
56456
|
+
out = out.replace(/\.activation\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.activationBorder)};`));
|
|
56457
|
+
return out;
|
|
56458
|
+
}
|
|
56459
|
+
var init_sequence_renderer = __esm({
|
|
56460
|
+
"node_modules/@probelabs/maid/out/renderer/sequence-renderer.js"() {
|
|
56461
|
+
init_sequence_layout();
|
|
56462
|
+
init_utils4();
|
|
56463
|
+
init_arrow_utils();
|
|
56464
|
+
init_block_utils();
|
|
56465
|
+
init_styles();
|
|
53376
56466
|
}
|
|
53377
56467
|
});
|
|
53378
56468
|
|
|
53379
|
-
// node_modules/
|
|
53380
|
-
|
|
53381
|
-
"
|
|
53382
|
-
|
|
53383
|
-
|
|
53384
|
-
|
|
53385
|
-
|
|
53386
|
-
|
|
53387
|
-
|
|
53388
|
-
|
|
53389
|
-
|
|
53390
|
-
|
|
53391
|
-
|
|
53392
|
-
|
|
53393
|
-
|
|
53394
|
-
|
|
53395
|
-
|
|
53396
|
-
|
|
53397
|
-
|
|
53398
|
-
|
|
53399
|
-
|
|
53400
|
-
|
|
53401
|
-
|
|
53402
|
-
|
|
53403
|
-
|
|
53404
|
-
|
|
53405
|
-
|
|
53406
|
-
|
|
56469
|
+
// node_modules/@probelabs/maid/out/core/frontmatter.js
|
|
56470
|
+
function parseFrontmatter(input) {
|
|
56471
|
+
const text = input.startsWith("\uFEFF") ? input.slice(1) : input;
|
|
56472
|
+
const lines = text.split(/\r?\n/);
|
|
56473
|
+
if (lines.length < 3 || lines[0].trim() !== "---")
|
|
56474
|
+
return null;
|
|
56475
|
+
let i3 = 1;
|
|
56476
|
+
const block = [];
|
|
56477
|
+
while (i3 < lines.length && lines[i3].trim() !== "---") {
|
|
56478
|
+
block.push(lines[i3]);
|
|
56479
|
+
i3++;
|
|
56480
|
+
}
|
|
56481
|
+
if (i3 >= lines.length)
|
|
56482
|
+
return null;
|
|
56483
|
+
const body = lines.slice(i3 + 1).join("\n");
|
|
56484
|
+
const raw = block.join("\n");
|
|
56485
|
+
const config = {};
|
|
56486
|
+
const themeVars = {};
|
|
56487
|
+
let themeUnderConfig = false;
|
|
56488
|
+
let ctx = "root";
|
|
56489
|
+
for (const line of block) {
|
|
56490
|
+
if (!line.trim())
|
|
56491
|
+
continue;
|
|
56492
|
+
const indent = line.match(/^\s*/)?.[0].length ?? 0;
|
|
56493
|
+
const mKey = line.match(/^\s*([A-Za-z0-9_\-]+):\s*(.*)$/);
|
|
56494
|
+
if (!mKey)
|
|
56495
|
+
continue;
|
|
56496
|
+
const key = mKey[1];
|
|
56497
|
+
let value = mKey[2] || "";
|
|
56498
|
+
if (indent === 0) {
|
|
56499
|
+
if (key === "config") {
|
|
56500
|
+
ctx = "config";
|
|
56501
|
+
continue;
|
|
56502
|
+
}
|
|
56503
|
+
if (key === "themeVariables") {
|
|
56504
|
+
ctx = "theme";
|
|
56505
|
+
continue;
|
|
56506
|
+
}
|
|
56507
|
+
ctx = "root";
|
|
56508
|
+
continue;
|
|
56509
|
+
}
|
|
56510
|
+
if (ctx === "config") {
|
|
56511
|
+
if (indent <= 2 && key !== "pie" && key !== "themeVariables")
|
|
56512
|
+
continue;
|
|
56513
|
+
if (key === "pie") {
|
|
56514
|
+
ctx = "config.pie";
|
|
56515
|
+
ensure(config, "pie", {});
|
|
56516
|
+
continue;
|
|
56517
|
+
}
|
|
56518
|
+
if (key === "themeVariables") {
|
|
56519
|
+
ctx = "theme";
|
|
56520
|
+
themeUnderConfig = true;
|
|
56521
|
+
continue;
|
|
56522
|
+
}
|
|
56523
|
+
continue;
|
|
56524
|
+
}
|
|
56525
|
+
if (ctx === "config.pie") {
|
|
56526
|
+
if (indent < 4) {
|
|
56527
|
+
if (key === "pie") {
|
|
56528
|
+
ctx = "config.pie";
|
|
56529
|
+
ensure(config, "pie", {});
|
|
56530
|
+
continue;
|
|
56531
|
+
}
|
|
56532
|
+
if (key === "themeVariables") {
|
|
56533
|
+
ctx = "theme";
|
|
56534
|
+
themeUnderConfig = true;
|
|
56535
|
+
continue;
|
|
56536
|
+
}
|
|
56537
|
+
ctx = "config";
|
|
56538
|
+
continue;
|
|
56539
|
+
}
|
|
56540
|
+
setKV(config.pie, key, value);
|
|
56541
|
+
continue;
|
|
56542
|
+
}
|
|
56543
|
+
if (ctx === "theme") {
|
|
56544
|
+
if (indent < 2) {
|
|
56545
|
+
ctx = "root";
|
|
56546
|
+
continue;
|
|
56547
|
+
}
|
|
56548
|
+
setKV(themeVars, key, value);
|
|
56549
|
+
continue;
|
|
53407
56550
|
}
|
|
53408
56551
|
}
|
|
53409
|
-
|
|
53410
|
-
|
|
53411
|
-
|
|
53412
|
-
var require_version2 = __commonJS({
|
|
53413
|
-
"node_modules/dagre/lib/version.js"(exports2, module2) {
|
|
53414
|
-
module2.exports = "0.8.5";
|
|
56552
|
+
if (themeUnderConfig && Object.keys(themeVars).length) {
|
|
56553
|
+
ensure(config, "themeVariables", {});
|
|
56554
|
+
Object.assign(config.themeVariables, themeVars);
|
|
53415
56555
|
}
|
|
53416
|
-
}
|
|
53417
|
-
|
|
53418
|
-
|
|
53419
|
-
|
|
53420
|
-
|
|
53421
|
-
|
|
53422
|
-
|
|
53423
|
-
|
|
53424
|
-
|
|
53425
|
-
|
|
53426
|
-
time: require_util().time,
|
|
53427
|
-
notime: require_util().notime
|
|
53428
|
-
},
|
|
53429
|
-
version: require_version2()
|
|
53430
|
-
};
|
|
56556
|
+
return { raw, body, config: Object.keys(config).length ? config : void 0, themeVariables: Object.keys(themeVars).length ? themeVars : void 0 };
|
|
56557
|
+
}
|
|
56558
|
+
function ensure(obj, key, def) {
|
|
56559
|
+
if (obj[key] == null)
|
|
56560
|
+
obj[key] = def;
|
|
56561
|
+
}
|
|
56562
|
+
function unquote2(val) {
|
|
56563
|
+
const v3 = val.trim();
|
|
56564
|
+
if (v3.startsWith('"') && v3.endsWith('"') || v3.startsWith("'") && v3.endsWith("'")) {
|
|
56565
|
+
return v3.slice(1, -1);
|
|
53431
56566
|
}
|
|
53432
|
-
|
|
53433
|
-
|
|
53434
|
-
|
|
53435
|
-
|
|
53436
|
-
|
|
53437
|
-
|
|
53438
|
-
|
|
56567
|
+
return v3;
|
|
56568
|
+
}
|
|
56569
|
+
function setKV(target, key, rawValue) {
|
|
56570
|
+
const v3 = unquote2(rawValue);
|
|
56571
|
+
if (v3 === "") {
|
|
56572
|
+
target[key] = "";
|
|
56573
|
+
return;
|
|
53439
56574
|
}
|
|
53440
|
-
|
|
53441
|
-
|
|
53442
|
-
|
|
53443
|
-
|
|
53444
|
-
|
|
56575
|
+
const num = Number(v3);
|
|
56576
|
+
if (!Number.isNaN(num) && /^-?[0-9]+(\.[0-9]+)?$/.test(v3)) {
|
|
56577
|
+
target[key] = num;
|
|
56578
|
+
return;
|
|
56579
|
+
}
|
|
56580
|
+
if (/^(true|false)$/i.test(v3)) {
|
|
56581
|
+
target[key] = /^true$/i.test(v3);
|
|
56582
|
+
return;
|
|
56583
|
+
}
|
|
56584
|
+
target[key] = v3;
|
|
56585
|
+
}
|
|
56586
|
+
var init_frontmatter = __esm({
|
|
56587
|
+
"node_modules/@probelabs/maid/out/core/frontmatter.js"() {
|
|
53445
56588
|
}
|
|
53446
56589
|
});
|
|
53447
56590
|
|
|
@@ -53452,6 +56595,102 @@ var init_dot_renderer = __esm({
|
|
|
53452
56595
|
});
|
|
53453
56596
|
|
|
53454
56597
|
// node_modules/@probelabs/maid/out/renderer/index.js
|
|
56598
|
+
function applyPieTheme(svg, theme) {
|
|
56599
|
+
if (!theme)
|
|
56600
|
+
return svg;
|
|
56601
|
+
let out = svg;
|
|
56602
|
+
if (theme.pieOuterStrokeWidth != null || theme.pieStrokeColor) {
|
|
56603
|
+
out = out.replace(/\.pieOuterCircle\s*\{[^}]*\}/, (m3) => {
|
|
56604
|
+
let rule = m3;
|
|
56605
|
+
if (theme.pieStrokeColor)
|
|
56606
|
+
rule = rule.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.pieStrokeColor)};`);
|
|
56607
|
+
if (theme.pieOuterStrokeWidth != null)
|
|
56608
|
+
rule = rule.replace(/stroke-width:\s*[^;]+;/, `stroke-width: ${String(theme.pieOuterStrokeWidth)};`);
|
|
56609
|
+
return rule;
|
|
56610
|
+
});
|
|
56611
|
+
if (theme.pieStrokeColor) {
|
|
56612
|
+
out = out.replace(/\.pieCircle\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.pieStrokeColor)};`));
|
|
56613
|
+
}
|
|
56614
|
+
}
|
|
56615
|
+
if (theme.pieSectionTextColor) {
|
|
56616
|
+
const c3 = String(theme.pieSectionTextColor);
|
|
56617
|
+
out = out.replace(/\.slice-label \{[^}]*\}/, (m3) => m3.replace(/fill:\s*#[0-9A-Fa-f]{3,8}|fill:\s*rgb\([^)]*\)/, `fill: ${c3}`));
|
|
56618
|
+
out = out.replace(/<text class="slice-label"([^>]*)>/g, `<text class="slice-label"$1 fill="${c3}">`);
|
|
56619
|
+
}
|
|
56620
|
+
if (theme.pieTitleTextColor) {
|
|
56621
|
+
const c3 = String(theme.pieTitleTextColor);
|
|
56622
|
+
out = out.replace(/<text class="pie-title"([^>]*)>/g, `<text class="pie-title"$1 fill="${c3}">`);
|
|
56623
|
+
}
|
|
56624
|
+
if (theme.pieSectionTextSize) {
|
|
56625
|
+
const size = String(theme.pieSectionTextSize);
|
|
56626
|
+
out = out.replace(/<text class="slice-label"([^>]*)>/g, `<text class="slice-label"$1 font-size="${size}">`);
|
|
56627
|
+
}
|
|
56628
|
+
if (theme.pieTitleTextSize) {
|
|
56629
|
+
const size = String(theme.pieTitleTextSize);
|
|
56630
|
+
out = out.replace(/<text class="pie-title"([^>]*)>/g, `<text class="pie-title"$1 font-size="${size}">`);
|
|
56631
|
+
}
|
|
56632
|
+
const colors = [];
|
|
56633
|
+
for (let i3 = 1; i3 <= 24; i3++) {
|
|
56634
|
+
const key = "pie" + i3;
|
|
56635
|
+
if (theme[key])
|
|
56636
|
+
colors.push(String(theme[key]));
|
|
56637
|
+
}
|
|
56638
|
+
if (colors.length) {
|
|
56639
|
+
let idx = 0;
|
|
56640
|
+
out = out.replace(/<path[^>]*class="pieCircle"[^>]*\sfill="([^"]+)"/g, (_m2) => {
|
|
56641
|
+
const color = colors[idx] ?? null;
|
|
56642
|
+
idx++;
|
|
56643
|
+
if (color)
|
|
56644
|
+
return _m2.replace(/fill="([^"]+)"/, `fill="${color}"`);
|
|
56645
|
+
return _m2;
|
|
56646
|
+
});
|
|
56647
|
+
}
|
|
56648
|
+
return out;
|
|
56649
|
+
}
|
|
56650
|
+
function applyFlowchartTheme(svg, theme) {
|
|
56651
|
+
if (!theme)
|
|
56652
|
+
return svg;
|
|
56653
|
+
let out = svg;
|
|
56654
|
+
if (theme.nodeBkg || theme.nodeBorder) {
|
|
56655
|
+
out = out.replace(/\.node-shape\s*\{[^}]*\}/, (m3) => {
|
|
56656
|
+
let rule = m3;
|
|
56657
|
+
if (theme.nodeBkg)
|
|
56658
|
+
rule = rule.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.nodeBkg)};`);
|
|
56659
|
+
if (theme.nodeBorder)
|
|
56660
|
+
rule = rule.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.nodeBorder)};`);
|
|
56661
|
+
return rule;
|
|
56662
|
+
});
|
|
56663
|
+
}
|
|
56664
|
+
if (theme.nodeTextColor) {
|
|
56665
|
+
out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.nodeTextColor)};`));
|
|
56666
|
+
}
|
|
56667
|
+
if (theme.lineColor) {
|
|
56668
|
+
out = out.replace(/\.edge-path\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.lineColor)};`));
|
|
56669
|
+
}
|
|
56670
|
+
if (theme.arrowheadColor) {
|
|
56671
|
+
out = out.replace(/(<path d="M0,0 L0,[0-9.]+ L[0-9.]+,[0-9.]+ z"[^>]*)(fill="[^"]*")/g, (_m2, p1) => `${p1}fill="${String(theme.arrowheadColor)}"`);
|
|
56672
|
+
out = out.replace(/(<circle cx="4\.5" cy="4\.5" r="4\.5"[^>]*)(fill="[^"]*")/g, (_m2, p1) => `${p1}fill="${String(theme.arrowheadColor)}"`);
|
|
56673
|
+
}
|
|
56674
|
+
if (theme.clusterBkg) {
|
|
56675
|
+
out = out.replace(/\.cluster-bg\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterBkg)};`));
|
|
56676
|
+
}
|
|
56677
|
+
if (theme.clusterBorder) {
|
|
56678
|
+
out = out.replace(/\.cluster-border\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.clusterBorder)};`));
|
|
56679
|
+
}
|
|
56680
|
+
if (theme.clusterTextColor) {
|
|
56681
|
+
out = out.replace(/\.cluster-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterTextColor)};`));
|
|
56682
|
+
}
|
|
56683
|
+
if (theme.fontFamily)
|
|
56684
|
+
out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/font-family:\s*[^;]+;/, `font-family: ${String(theme.fontFamily)};`));
|
|
56685
|
+
if (theme.fontSize)
|
|
56686
|
+
out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/font-size:\s*[^;]+;/, `font-size: ${String(theme.fontSize)};`));
|
|
56687
|
+
return out;
|
|
56688
|
+
}
|
|
56689
|
+
function renderMermaid(text, options = {}) {
|
|
56690
|
+
const renderer = new MermaidRenderer(options.layoutEngine, options.renderer);
|
|
56691
|
+
return renderer.renderAny(text, options);
|
|
56692
|
+
}
|
|
56693
|
+
var MermaidRenderer;
|
|
53455
56694
|
var init_renderer = __esm({
|
|
53456
56695
|
"node_modules/@probelabs/maid/out/renderer/index.js"() {
|
|
53457
56696
|
init_lexer2();
|
|
@@ -53459,9 +56698,244 @@ var init_renderer = __esm({
|
|
|
53459
56698
|
init_graph_builder();
|
|
53460
56699
|
init_layout();
|
|
53461
56700
|
init_svg_generator();
|
|
56701
|
+
init_pie_builder();
|
|
56702
|
+
init_pie_renderer();
|
|
56703
|
+
init_sequence_builder();
|
|
56704
|
+
init_sequence_renderer();
|
|
56705
|
+
init_frontmatter();
|
|
53462
56706
|
init_layout();
|
|
53463
56707
|
init_svg_generator();
|
|
53464
56708
|
init_dot_renderer();
|
|
56709
|
+
MermaidRenderer = class {
|
|
56710
|
+
constructor(layoutEngine, renderer) {
|
|
56711
|
+
this.graphBuilder = new GraphBuilder();
|
|
56712
|
+
this.layoutEngine = layoutEngine || new DagreLayoutEngine();
|
|
56713
|
+
this.renderer = renderer || new SVGRenderer();
|
|
56714
|
+
}
|
|
56715
|
+
/**
|
|
56716
|
+
* Renders a Mermaid flowchart diagram
|
|
56717
|
+
*/
|
|
56718
|
+
render(text, options = {}) {
|
|
56719
|
+
const errors = [];
|
|
56720
|
+
const layoutEngine = options.layoutEngine || this.layoutEngine;
|
|
56721
|
+
const renderer = options.renderer || this.renderer;
|
|
56722
|
+
try {
|
|
56723
|
+
const lexResult = tokenize(text);
|
|
56724
|
+
if (lexResult.errors && lexResult.errors.length > 0) {
|
|
56725
|
+
for (const error2 of lexResult.errors) {
|
|
56726
|
+
errors.push({
|
|
56727
|
+
line: error2.line || 1,
|
|
56728
|
+
column: error2.column || 1,
|
|
56729
|
+
message: error2.message,
|
|
56730
|
+
severity: "error",
|
|
56731
|
+
code: "LEXER_ERROR"
|
|
56732
|
+
});
|
|
56733
|
+
}
|
|
56734
|
+
}
|
|
56735
|
+
parserInstance.reset();
|
|
56736
|
+
parserInstance.input = lexResult.tokens;
|
|
56737
|
+
const cst = parserInstance.diagram();
|
|
56738
|
+
if (parserInstance.errors && parserInstance.errors.length > 0) {
|
|
56739
|
+
for (const error2 of parserInstance.errors) {
|
|
56740
|
+
const token = error2.token;
|
|
56741
|
+
errors.push({
|
|
56742
|
+
line: token?.startLine || 1,
|
|
56743
|
+
column: token?.startColumn || 1,
|
|
56744
|
+
message: error2.message,
|
|
56745
|
+
severity: "error",
|
|
56746
|
+
code: "PARSER_ERROR"
|
|
56747
|
+
});
|
|
56748
|
+
}
|
|
56749
|
+
}
|
|
56750
|
+
const graph = this.graphBuilder.build(cst);
|
|
56751
|
+
let layout;
|
|
56752
|
+
try {
|
|
56753
|
+
layout = layoutEngine.layout(graph);
|
|
56754
|
+
} catch (layoutError) {
|
|
56755
|
+
errors.push({
|
|
56756
|
+
line: 1,
|
|
56757
|
+
column: 1,
|
|
56758
|
+
message: layoutError.message || "Layout calculation failed",
|
|
56759
|
+
severity: "error",
|
|
56760
|
+
code: "LAYOUT_ERROR"
|
|
56761
|
+
});
|
|
56762
|
+
return {
|
|
56763
|
+
svg: this.generateErrorSvg(layoutError.message || "Layout calculation failed"),
|
|
56764
|
+
graph,
|
|
56765
|
+
errors
|
|
56766
|
+
};
|
|
56767
|
+
}
|
|
56768
|
+
let svg = renderer.render(layout);
|
|
56769
|
+
if (options.showErrors && errors.length > 0) {
|
|
56770
|
+
svg = this.addErrorOverlays(svg, errors);
|
|
56771
|
+
}
|
|
56772
|
+
return {
|
|
56773
|
+
svg,
|
|
56774
|
+
graph,
|
|
56775
|
+
errors
|
|
56776
|
+
};
|
|
56777
|
+
} catch (error2) {
|
|
56778
|
+
const errorSvg = this.generateErrorSvg(error2.message || "Unknown error occurred");
|
|
56779
|
+
errors.push({
|
|
56780
|
+
line: 1,
|
|
56781
|
+
column: 1,
|
|
56782
|
+
message: error2.message || "Unknown error occurred",
|
|
56783
|
+
severity: "error",
|
|
56784
|
+
code: "RENDER_ERROR"
|
|
56785
|
+
});
|
|
56786
|
+
return {
|
|
56787
|
+
svg: errorSvg,
|
|
56788
|
+
graph: { nodes: [], edges: [], direction: "TD" },
|
|
56789
|
+
errors
|
|
56790
|
+
};
|
|
56791
|
+
}
|
|
56792
|
+
}
|
|
56793
|
+
/**
|
|
56794
|
+
* Renders supported diagram types (flowchart + pie for now)
|
|
56795
|
+
*/
|
|
56796
|
+
renderAny(text, options = {}) {
|
|
56797
|
+
let content = text;
|
|
56798
|
+
let theme;
|
|
56799
|
+
if (text.trimStart().startsWith("---")) {
|
|
56800
|
+
const fm = parseFrontmatter(text);
|
|
56801
|
+
if (fm) {
|
|
56802
|
+
content = fm.body;
|
|
56803
|
+
theme = fm.themeVariables || fm.config && fm.config.themeVariables || void 0;
|
|
56804
|
+
}
|
|
56805
|
+
}
|
|
56806
|
+
const firstLine = content.trim().split("\n")[0];
|
|
56807
|
+
if (/^(flowchart|graph)\s+/i.test(firstLine)) {
|
|
56808
|
+
const res = this.render(content, options);
|
|
56809
|
+
const svg2 = theme ? applyFlowchartTheme(res.svg, theme) : res.svg;
|
|
56810
|
+
return { svg: svg2, graph: res.graph, errors: res.errors };
|
|
56811
|
+
}
|
|
56812
|
+
if (/^pie\b/i.test(firstLine)) {
|
|
56813
|
+
try {
|
|
56814
|
+
const { model, errors } = buildPieModel(content);
|
|
56815
|
+
const svg = renderPie(model, {
|
|
56816
|
+
width: options.width,
|
|
56817
|
+
height: options.height,
|
|
56818
|
+
rimStroke: theme?.pieStrokeColor,
|
|
56819
|
+
rimStrokeWidth: theme?.pieOuterStrokeWidth
|
|
56820
|
+
});
|
|
56821
|
+
const themedSvg = applyPieTheme(svg, theme);
|
|
56822
|
+
return { svg: themedSvg, graph: { nodes: [], edges: [], direction: "TD" }, errors };
|
|
56823
|
+
} catch (e3) {
|
|
56824
|
+
const msg = e3?.message || "Pie render error";
|
|
56825
|
+
const err = [{ line: 1, column: 1, message: msg, severity: "error", code: "PIE_RENDER" }];
|
|
56826
|
+
return { svg: this.generateErrorSvg(msg), graph: { nodes: [], edges: [], direction: "TD" }, errors: err };
|
|
56827
|
+
}
|
|
56828
|
+
}
|
|
56829
|
+
if (/^sequenceDiagram\b/.test(firstLine)) {
|
|
56830
|
+
try {
|
|
56831
|
+
const model = buildSequenceModel(content);
|
|
56832
|
+
const svg = renderSequence(model, { theme });
|
|
56833
|
+
return { svg, graph: { nodes: [], edges: [], direction: "TD" }, errors: [] };
|
|
56834
|
+
} catch (e3) {
|
|
56835
|
+
const msg = e3?.message || "Sequence render error";
|
|
56836
|
+
const err = [{ line: 1, column: 1, message: msg, severity: "error", code: "SEQUENCE_RENDER" }];
|
|
56837
|
+
return { svg: this.generateErrorSvg(msg), graph: { nodes: [], edges: [], direction: "TD" }, errors: err };
|
|
56838
|
+
}
|
|
56839
|
+
}
|
|
56840
|
+
const errorSvg = this.generateErrorSvg("Unsupported diagram type. Rendering supports flowchart, pie, and sequence for now.");
|
|
56841
|
+
return {
|
|
56842
|
+
svg: errorSvg,
|
|
56843
|
+
graph: { nodes: [], edges: [], direction: "TD" },
|
|
56844
|
+
errors: [{
|
|
56845
|
+
line: 1,
|
|
56846
|
+
column: 1,
|
|
56847
|
+
message: "Unsupported diagram type",
|
|
56848
|
+
severity: "error",
|
|
56849
|
+
code: "UNSUPPORTED_TYPE"
|
|
56850
|
+
}]
|
|
56851
|
+
};
|
|
56852
|
+
}
|
|
56853
|
+
addErrorOverlays(svg, errors) {
|
|
56854
|
+
const errorStyle = `
|
|
56855
|
+
<style>
|
|
56856
|
+
.error-indicator {
|
|
56857
|
+
fill: #ff0000;
|
|
56858
|
+
opacity: 0.8;
|
|
56859
|
+
}
|
|
56860
|
+
.error-text {
|
|
56861
|
+
fill: white;
|
|
56862
|
+
font-family: Arial, sans-serif;
|
|
56863
|
+
font-size: 12px;
|
|
56864
|
+
font-weight: bold;
|
|
56865
|
+
}
|
|
56866
|
+
</style>`;
|
|
56867
|
+
const errorIndicator = `
|
|
56868
|
+
<g id="errors">
|
|
56869
|
+
<rect x="5" y="5" width="100" height="25" rx="3" class="error-indicator" />
|
|
56870
|
+
<text x="55" y="20" text-anchor="middle" class="error-text">${errors.length} error${errors.length !== 1 ? "s" : ""}</text>
|
|
56871
|
+
</g>`;
|
|
56872
|
+
return svg.replace("</svg>", `${errorStyle}${errorIndicator}</svg>`);
|
|
56873
|
+
}
|
|
56874
|
+
generateErrorSvg(message) {
|
|
56875
|
+
const width = 400;
|
|
56876
|
+
const height = 200;
|
|
56877
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
|
56878
|
+
<rect width="${width}" height="${height}" fill="#fee" stroke="#c00" stroke-width="2" />
|
|
56879
|
+
<text x="${width / 2}" y="${height / 2 - 20}" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#c00">
|
|
56880
|
+
Render Error
|
|
56881
|
+
</text>
|
|
56882
|
+
<text x="${width / 2}" y="${height / 2 + 10}" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#666">
|
|
56883
|
+
${this.wrapText(message, 40).map((line, i3) => `<tspan x="${width / 2}" dy="${i3 === 0 ? 0 : 15}">${this.escapeXml(line)}</tspan>`).join("")}
|
|
56884
|
+
</text>
|
|
56885
|
+
</svg>`;
|
|
56886
|
+
}
|
|
56887
|
+
wrapText(text, maxLength) {
|
|
56888
|
+
const words = text.split(" ");
|
|
56889
|
+
const lines = [];
|
|
56890
|
+
let currentLine = "";
|
|
56891
|
+
for (const word of words) {
|
|
56892
|
+
if (currentLine.length + word.length + 1 <= maxLength) {
|
|
56893
|
+
currentLine += (currentLine ? " " : "") + word;
|
|
56894
|
+
} else {
|
|
56895
|
+
if (currentLine)
|
|
56896
|
+
lines.push(currentLine);
|
|
56897
|
+
currentLine = word;
|
|
56898
|
+
}
|
|
56899
|
+
}
|
|
56900
|
+
if (currentLine)
|
|
56901
|
+
lines.push(currentLine);
|
|
56902
|
+
return lines.slice(0, 3);
|
|
56903
|
+
}
|
|
56904
|
+
escapeXml(text) {
|
|
56905
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
56906
|
+
}
|
|
56907
|
+
};
|
|
56908
|
+
}
|
|
56909
|
+
});
|
|
56910
|
+
|
|
56911
|
+
// node_modules/@probelabs/maid/out/mermaid-compat.js
|
|
56912
|
+
function createMermaidAPI() {
|
|
56913
|
+
return {
|
|
56914
|
+
initialize(_config) {
|
|
56915
|
+
},
|
|
56916
|
+
async render(_id, text, options) {
|
|
56917
|
+
try {
|
|
56918
|
+
const result = renderMermaid(text, options);
|
|
56919
|
+
return { svg: result.svg };
|
|
56920
|
+
} catch (error2) {
|
|
56921
|
+
throw new Error(`Maid render failed: ${error2.message || "Unknown error"}`);
|
|
56922
|
+
}
|
|
56923
|
+
},
|
|
56924
|
+
renderSync(_id, text, options) {
|
|
56925
|
+
try {
|
|
56926
|
+
const result = renderMermaid(text, options);
|
|
56927
|
+
return { svg: result.svg };
|
|
56928
|
+
} catch (error2) {
|
|
56929
|
+
throw new Error(`Maid render failed: ${error2.message || "Unknown error"}`);
|
|
56930
|
+
}
|
|
56931
|
+
}
|
|
56932
|
+
};
|
|
56933
|
+
}
|
|
56934
|
+
var maid;
|
|
56935
|
+
var init_mermaid_compat = __esm({
|
|
56936
|
+
"node_modules/@probelabs/maid/out/mermaid-compat.js"() {
|
|
56937
|
+
init_renderer();
|
|
56938
|
+
maid = createMermaidAPI();
|
|
53465
56939
|
}
|
|
53466
56940
|
});
|
|
53467
56941
|
|
|
@@ -53495,6 +56969,7 @@ var init_out = __esm({
|
|
|
53495
56969
|
init_edits();
|
|
53496
56970
|
init_fixes();
|
|
53497
56971
|
init_renderer();
|
|
56972
|
+
init_mermaid_compat();
|
|
53498
56973
|
init_router();
|
|
53499
56974
|
init_fixes();
|
|
53500
56975
|
init_edits();
|
|
@@ -54210,8 +57685,8 @@ When presented with a broken Mermaid diagram, analyze it thoroughly and provide
|
|
|
54210
57685
|
debug: this.options.debug,
|
|
54211
57686
|
tracer: this.options.tracer,
|
|
54212
57687
|
allowEdit: this.options.allowEdit,
|
|
54213
|
-
maxIterations:
|
|
54214
|
-
//
|
|
57688
|
+
maxIterations: 10,
|
|
57689
|
+
// Allow more iterations for mermaid fixing to handle complex diagrams
|
|
54215
57690
|
disableMermaidValidation: true
|
|
54216
57691
|
// CRITICAL: Disable mermaid validation in nested agent to prevent infinite recursion
|
|
54217
57692
|
});
|
|
@@ -55111,6 +58586,18 @@ var init_ProbeAgent = __esm({
|
|
|
55111
58586
|
this.toolImplementations.bash = wrappedTools.bashToolInstance;
|
|
55112
58587
|
}
|
|
55113
58588
|
this.wrappedTools = wrappedTools;
|
|
58589
|
+
if (this.debug) {
|
|
58590
|
+
console.error("\n[DEBUG] ========================================");
|
|
58591
|
+
console.error("[DEBUG] ProbeAgent Tools Initialized");
|
|
58592
|
+
console.error("[DEBUG] Session ID:", this.sessionId);
|
|
58593
|
+
console.error("[DEBUG] Available tools:");
|
|
58594
|
+
for (const toolName of Object.keys(this.toolImplementations)) {
|
|
58595
|
+
console.error(`[DEBUG] - ${toolName}`);
|
|
58596
|
+
}
|
|
58597
|
+
console.error("[DEBUG] Allowed folders:", this.allowedFolders);
|
|
58598
|
+
console.error("[DEBUG] Outline mode:", this.outline);
|
|
58599
|
+
console.error("[DEBUG] ========================================\n");
|
|
58600
|
+
}
|
|
55114
58601
|
}
|
|
55115
58602
|
/**
|
|
55116
58603
|
* Initialize the AI model based on available API keys and forced provider setting
|
|
@@ -55881,12 +59368,28 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
55881
59368
|
const { type } = parsedTool;
|
|
55882
59369
|
if (type === "mcp" && this.mcpBridge && this.mcpBridge.isMcpTool(toolName)) {
|
|
55883
59370
|
try {
|
|
55884
|
-
if (this.debug)
|
|
59371
|
+
if (this.debug) {
|
|
59372
|
+
console.error(`
|
|
59373
|
+
[DEBUG] ========================================`);
|
|
59374
|
+
console.error(`[DEBUG] Executing MCP tool: ${toolName}`);
|
|
59375
|
+
console.error(`[DEBUG] Arguments:`);
|
|
59376
|
+
for (const [key, value] of Object.entries(params)) {
|
|
59377
|
+
const displayValue = typeof value === "string" && value.length > 100 ? value.substring(0, 100) + "..." : value;
|
|
59378
|
+
console.error(`[DEBUG] ${key}: ${JSON.stringify(displayValue)}`);
|
|
59379
|
+
}
|
|
59380
|
+
console.error(`[DEBUG] ========================================
|
|
59381
|
+
`);
|
|
59382
|
+
}
|
|
55885
59383
|
const executionResult = await this.mcpBridge.mcpTools[toolName].execute(params);
|
|
55886
59384
|
const toolResultContent = typeof executionResult === "string" ? executionResult : JSON.stringify(executionResult, null, 2);
|
|
55887
|
-
const preview = createMessagePreview(toolResultContent);
|
|
55888
59385
|
if (this.debug) {
|
|
55889
|
-
|
|
59386
|
+
const preview = toolResultContent.length > 500 ? toolResultContent.substring(0, 500) + "..." : toolResultContent;
|
|
59387
|
+
console.error(`[DEBUG] ========================================`);
|
|
59388
|
+
console.error(`[DEBUG] MCP tool '${toolName}' completed successfully`);
|
|
59389
|
+
console.error(`[DEBUG] Result preview:`);
|
|
59390
|
+
console.error(preview);
|
|
59391
|
+
console.error(`[DEBUG] ========================================
|
|
59392
|
+
`);
|
|
55890
59393
|
}
|
|
55891
59394
|
currentMessages.push({ role: "user", content: `<tool_result>
|
|
55892
59395
|
${toolResultContent}
|
|
@@ -55894,7 +59397,13 @@ ${toolResultContent}
|
|
|
55894
59397
|
} catch (error2) {
|
|
55895
59398
|
console.error(`Error executing MCP tool ${toolName}:`, error2);
|
|
55896
59399
|
const toolResultContent = `Error executing MCP tool ${toolName}: ${error2.message}`;
|
|
55897
|
-
if (this.debug)
|
|
59400
|
+
if (this.debug) {
|
|
59401
|
+
console.error(`[DEBUG] ========================================`);
|
|
59402
|
+
console.error(`[DEBUG] MCP tool '${toolName}' failed with error:`);
|
|
59403
|
+
console.error(`[DEBUG] ${error2.message}`);
|
|
59404
|
+
console.error(`[DEBUG] ========================================
|
|
59405
|
+
`);
|
|
59406
|
+
}
|
|
55898
59407
|
currentMessages.push({ role: "user", content: `<tool_result>
|
|
55899
59408
|
${toolResultContent}
|
|
55900
59409
|
</tool_result>` });
|
|
@@ -55906,6 +59415,18 @@ ${toolResultContent}
|
|
|
55906
59415
|
sessionId: this.sessionId,
|
|
55907
59416
|
workingDirectory: this.allowedFolders && this.allowedFolders[0] || process.cwd()
|
|
55908
59417
|
};
|
|
59418
|
+
if (this.debug) {
|
|
59419
|
+
console.error(`
|
|
59420
|
+
[DEBUG] ========================================`);
|
|
59421
|
+
console.error(`[DEBUG] Executing tool: ${toolName}`);
|
|
59422
|
+
console.error(`[DEBUG] Arguments:`);
|
|
59423
|
+
for (const [key, value] of Object.entries(params)) {
|
|
59424
|
+
const displayValue = typeof value === "string" && value.length > 100 ? value.substring(0, 100) + "..." : value;
|
|
59425
|
+
console.error(`[DEBUG] ${key}: ${JSON.stringify(displayValue)}`);
|
|
59426
|
+
}
|
|
59427
|
+
console.error(`[DEBUG] ========================================
|
|
59428
|
+
`);
|
|
59429
|
+
}
|
|
55909
59430
|
this.events.emit("toolCall", {
|
|
55910
59431
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
55911
59432
|
name: toolName,
|
|
@@ -55947,6 +59468,15 @@ ${toolResultContent}
|
|
|
55947
59468
|
} else {
|
|
55948
59469
|
toolResult = await executeToolCall();
|
|
55949
59470
|
}
|
|
59471
|
+
if (this.debug) {
|
|
59472
|
+
const resultPreview = typeof toolResult === "string" ? toolResult.length > 500 ? toolResult.substring(0, 500) + "..." : toolResult : toolResult ? JSON.stringify(toolResult, null, 2).substring(0, 500) + "..." : "No Result";
|
|
59473
|
+
console.error(`[DEBUG] ========================================`);
|
|
59474
|
+
console.error(`[DEBUG] Tool '${toolName}' completed successfully`);
|
|
59475
|
+
console.error(`[DEBUG] Result preview:`);
|
|
59476
|
+
console.error(resultPreview);
|
|
59477
|
+
console.error(`[DEBUG] ========================================
|
|
59478
|
+
`);
|
|
59479
|
+
}
|
|
55950
59480
|
this.events.emit("toolCall", {
|
|
55951
59481
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
55952
59482
|
name: toolName,
|
|
@@ -55955,6 +59485,13 @@ ${toolResultContent}
|
|
|
55955
59485
|
status: "completed"
|
|
55956
59486
|
});
|
|
55957
59487
|
} catch (toolError) {
|
|
59488
|
+
if (this.debug) {
|
|
59489
|
+
console.error(`[DEBUG] ========================================`);
|
|
59490
|
+
console.error(`[DEBUG] Tool '${toolName}' failed with error:`);
|
|
59491
|
+
console.error(`[DEBUG] ${toolError.message}`);
|
|
59492
|
+
console.error(`[DEBUG] ========================================
|
|
59493
|
+
`);
|
|
59494
|
+
}
|
|
55958
59495
|
this.events.emit("toolCall", {
|
|
55959
59496
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
55960
59497
|
name: toolName,
|
|
@@ -56004,6 +59541,16 @@ Error: Unknown tool '${toolName}'. Available tools: ${allAvailableTools.join(",
|
|
|
56004
59541
|
}
|
|
56005
59542
|
}
|
|
56006
59543
|
} else {
|
|
59544
|
+
const hasMermaidCodeBlock = /```mermaid\s*\n[\s\S]*?\n```/.test(assistantResponseContent);
|
|
59545
|
+
const hasNoSchemaOrTools = !options.schema && validTools.length === 0;
|
|
59546
|
+
if (hasMermaidCodeBlock && hasNoSchemaOrTools) {
|
|
59547
|
+
finalResult = assistantResponseContent;
|
|
59548
|
+
completionAttempted = true;
|
|
59549
|
+
if (this.debug) {
|
|
59550
|
+
console.error(`[DEBUG] Accepting mermaid code block as valid completion (no schema, no tools)`);
|
|
59551
|
+
}
|
|
59552
|
+
break;
|
|
59553
|
+
}
|
|
56007
59554
|
currentMessages.push({ role: "assistant", content: assistantResponseContent });
|
|
56008
59555
|
let reminderContent;
|
|
56009
59556
|
if (options.schema) {
|