From b3e49f28a981c0dda665239587bbaf82dfa09a05 Mon Sep 17 00:00:00 2001 From: 78wesley <9322930+78wesley@users.noreply.github.com> Date: Wed, 18 Jun 2025 11:09:40 +0200 Subject: [PATCH 1/4] added cross-link detection --- lib/rules/index.js | 3 ++- lib/rules/no-cross-links.js | 46 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 lib/rules/no-cross-links.js diff --git a/lib/rules/index.js b/lib/rules/index.js index bc4af7e..4c6b3bf 100644 --- a/lib/rules/index.js +++ b/lib/rules/index.js @@ -6,5 +6,6 @@ module.exports = { "no-overlapping-nodes": require("./no-overlapping-nodes"), "no-unconnected-http-nodes": require("./no-unconnected-http-nodes"), "no-unnamed-functions": require("./no-unnamed-functions"), - "no-unnamed-links": require("./no-unnamed-links") + "no-unnamed-links": require("./no-unnamed-links"), + "no-cross-links": require("./no-cross-links") } diff --git a/lib/rules/no-cross-links.js b/lib/rules/no-cross-links.js new file mode 100644 index 0000000..42ad628 --- /dev/null +++ b/lib/rules/no-cross-links.js @@ -0,0 +1,46 @@ +module.exports = { + meta: { + type: "problem", + severity: "warn", + docs: { + description: "Detect link nodes that cross tabs" + }, + options: { + crossTabLinks: { type: "boolean", default: true } + } + }, + create: function(context, ruleConfig) { + const crossTabLinksEnabled = ruleConfig?.crossTabLinks !== false; + + if (!crossTabLinksEnabled) { + return {}; // Rule is disabled, no-op + } + + let linkInNodes = []; + let linkOutNodes = []; + let tabs = []; + let tabLabels = {}; + + return { + "start": function(flow) { + linkInNodes = flow.filter(n => n.type === "link in"); + linkOutNodes = flow.filter(n => n.type === "link out"); + tabs = flow.filter(n => n.type === "tab"); + tabLabels = Object.fromEntries(tabs.map(tab => [tab.id, tab.label])); + }, + "node": function(node) { + if (node.type === "link out" && Array.isArray(node.links)) { + node.links.forEach(linkId => { + const targetNode = linkInNodes.find(inNode => inNode.id === linkId); + if (targetNode && node.z !== targetNode.z) { + context.report({ + location: [node.id], + message: `Cross-tab link from '${node.name || node.id}' (tab: '${tabLabels[node.z] || node.z}') to '${targetNode.name || targetNode.id}' (tab: '${tabLabels[targetNode.z] || targetNode.z}')` + }); + } + }); + } + } + }; + } +}; From 1f95226db08bb20e4b90e624de0922a6efb648cc Mon Sep 17 00:00:00 2001 From: 78wesley Date: Sat, 5 Jul 2025 01:07:14 +0200 Subject: [PATCH 2/4] Refactor cross-tab link detection logic for improved clarity and performance --- lib/rules/no-cross-links.js | 89 ++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 36 deletions(-) diff --git a/lib/rules/no-cross-links.js b/lib/rules/no-cross-links.js index 42ad628..dfedd6d 100644 --- a/lib/rules/no-cross-links.js +++ b/lib/rules/no-cross-links.js @@ -1,46 +1,63 @@ +function findCrossTabLinks(flowSet) { + const linkIns = new Map(); + const linkOuts = []; + const tabLabel = new Map(); + + flowSet.flows.forEach((tab) => { + tabLabel.set(tab.id, (tab.config && tab.config.label) || ""); + }); + + flowSet.nodes.forEach((n) => { + if (n.type === "link in") linkIns.set(n.id, n); + if (n.type === "link out") linkOuts.push(n); + }); + + const results = []; + + for (const out of linkOuts) { + const targets = (out.outboundWires || []).flat(); + + for (const wire of targets) { + const destNode = wire.destinationNode; + if (!destNode) continue; + const inn = linkIns.get(destNode.id); + if (inn) { + if (out.z !== inn.z) { + results.push({ + from: out.id, + fromName: out.config.name || "", + fromTab: out.z, + fromTabLabel: tabLabel.get(out.z) || "", + to: inn.id, + toName: inn.config.name || "", + toTab: inn.z, + toTabLabel: tabLabel.get(inn.z) || "", + }); + } + } + } + } + return results; +} + module.exports = { meta: { type: "problem", severity: "warn", - docs: { - description: "Detect link nodes that cross tabs" - }, - options: { - crossTabLinks: { type: "boolean", default: true } - } + docs: { description: "Detect link nodes that cross tabs" }, }, - create: function(context, ruleConfig) { - const crossTabLinksEnabled = ruleConfig?.crossTabLinks !== false; - - if (!crossTabLinksEnabled) { - return {}; // Rule is disabled, no-op - } - - let linkInNodes = []; - let linkOutNodes = []; - let tabs = []; - let tabLabels = {}; + create(context) { return { - "start": function(flow) { - linkInNodes = flow.filter(n => n.type === "link in"); - linkOutNodes = flow.filter(n => n.type === "link out"); - tabs = flow.filter(n => n.type === "tab"); - tabLabels = Object.fromEntries(tabs.map(tab => [tab.id, tab.label])); - }, - "node": function(node) { - if (node.type === "link out" && Array.isArray(node.links)) { - node.links.forEach(linkId => { - const targetNode = linkInNodes.find(inNode => inNode.id === linkId); - if (targetNode && node.z !== targetNode.z) { - context.report({ - location: [node.id], - message: `Cross-tab link from '${node.name || node.id}' (tab: '${tabLabels[node.z] || node.z}') to '${targetNode.name || targetNode.id}' (tab: '${tabLabels[targetNode.z] || targetNode.z}')` - }); - } + start(flowSet) { + const crossTab = findCrossTabLinks(flowSet); + crossTab.forEach((link) => { + context.report({ + location: [link.to, link.from], + message: `Cross tab link node found, between flow "${link.toTabLabel}" and flow "${link.fromTabLabel}"`, }); - } - } + }); + }, }; - } + }, }; From caa9cdfbf31df3f3b4fb0d6211a8e18da8416b12 Mon Sep 17 00:00:00 2001 From: 78wesley Date: Sat, 5 Jul 2025 01:18:45 +0200 Subject: [PATCH 3/4] Add default property to meta for cross-tab link detection rule --- lib/rules/no-cross-links.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/rules/no-cross-links.js b/lib/rules/no-cross-links.js index dfedd6d..c126ca2 100644 --- a/lib/rules/no-cross-links.js +++ b/lib/rules/no-cross-links.js @@ -45,6 +45,7 @@ module.exports = { type: "problem", severity: "warn", docs: { description: "Detect link nodes that cross tabs" }, + default: false, }, create(context) { From de007d46ade21977ea997776795aaa296308f6b6 Mon Sep 17 00:00:00 2001 From: 78wesley Date: Sat, 5 Jul 2025 15:33:02 +0200 Subject: [PATCH 4/4] Add default rule handling in initialise function --- lib/cli/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/cli/index.js b/lib/cli/index.js index cb7747a..5ede809 100644 --- a/lib/cli/index.js +++ b/lib/cli/index.js @@ -73,7 +73,11 @@ async function initialise() { config.rules[r] = true; } } else { - config.rules[r] = true; + if (rule.meta && rule.meta.hasOwnProperty('default')) { + config.rules[r] = rule.meta.default; + } else { + config.rules[r] = true; + } } } console.log("module.exports = "+JSON.stringify(config,null,4))