Recurse appearance sweeps into subgraphs
This commit is contained in:
@@ -2,6 +2,7 @@ import { app } from "/scripts/app.js";
|
||||
import {
|
||||
DEFAULT_SCHEME,
|
||||
NODE_COLOR_SCHEMES,
|
||||
collectGraphNodes,
|
||||
schemeColors,
|
||||
shouldRecolor,
|
||||
titleInk,
|
||||
@@ -30,10 +31,9 @@ function applyScheme(node, colors) {
|
||||
}
|
||||
|
||||
function repaintAll(nextScheme, previousScheme) {
|
||||
const nodes = app.graph?._nodes || app.graph?.nodes || [];
|
||||
const next = schemeColors(nextScheme);
|
||||
const previous = schemeColors(previousScheme);
|
||||
for (const node of nodes) {
|
||||
for (const node of collectGraphNodes(app.graph)) {
|
||||
if (!isAusbossNode(node)) continue;
|
||||
if (!shouldRecolor(node, previous)) continue;
|
||||
applyScheme(node, next);
|
||||
|
||||
@@ -36,6 +36,22 @@ export function titleInk(hex) {
|
||||
return luminance > 0.6 ? "#1a1a1a" : "#ffffff";
|
||||
}
|
||||
|
||||
// Flatten every node reachable from a graph, descending into subgraph
|
||||
// containers via `node.subgraph`. Accepts a graph exposing `_nodes` or
|
||||
// `nodes`, or a plain node array; the visited set breaks reference cycles.
|
||||
export function collectGraphNodes(graph, visited = new Set()) {
|
||||
if (!graph || visited.has(graph)) return [];
|
||||
visited.add(graph);
|
||||
const nodes = Array.isArray(graph) ? graph : graph._nodes || graph.nodes || [];
|
||||
const collected = [];
|
||||
for (const node of nodes) {
|
||||
if (!node) continue;
|
||||
collected.push(node);
|
||||
if (node.subgraph) collected.push(...collectGraphNodes(node.subgraph, visited));
|
||||
}
|
||||
return collected;
|
||||
}
|
||||
|
||||
// A node is repainted only while it is still "following the setting": either
|
||||
// it carries no colors while the previous scheme was the theme default, or it
|
||||
// still wears exactly the previous scheme's pair. Anything else — a color the
|
||||
|
||||
@@ -4,6 +4,7 @@ import assert from "node:assert/strict";
|
||||
import {
|
||||
DEFAULT_SCHEME,
|
||||
NODE_COLOR_SCHEMES,
|
||||
collectGraphNodes,
|
||||
schemeColors,
|
||||
shouldRecolor,
|
||||
titleInk,
|
||||
@@ -78,3 +79,30 @@ test("titleInk falls back to light ink on malformed input", () => {
|
||||
assert.equal(titleInk("e0e0e0"), "#ffffff");
|
||||
assert.equal(titleInk("#zzzzzz"), "#ffffff");
|
||||
});
|
||||
|
||||
test("collectGraphNodes flattens nested subgraphs", () => {
|
||||
const inner = { _nodes: [{ id: 3 }] };
|
||||
const graph = { _nodes: [{ id: 1 }, { id: 2, subgraph: inner }] };
|
||||
assert.deepEqual(
|
||||
collectGraphNodes(graph).map((node) => node.id),
|
||||
[1, 2, 3],
|
||||
);
|
||||
});
|
||||
|
||||
test("collectGraphNodes accepts nodes arrays and plain arrays", () => {
|
||||
const viaNodes = { nodes: [{ id: 1 }] };
|
||||
assert.deepEqual(collectGraphNodes(viaNodes).map((node) => node.id), [1]);
|
||||
const plain = [{ id: 1 }, { id: 2, subgraph: [{ id: 3 }] }];
|
||||
assert.deepEqual(collectGraphNodes(plain).map((node) => node.id), [1, 2, 3]);
|
||||
assert.deepEqual(collectGraphNodes(null), []);
|
||||
assert.deepEqual(collectGraphNodes({}), []);
|
||||
});
|
||||
|
||||
test("collectGraphNodes survives subgraph reference cycles", () => {
|
||||
const graph = { _nodes: [{ id: 1 }] };
|
||||
graph._nodes.push({ id: 2, subgraph: graph });
|
||||
assert.deepEqual(
|
||||
collectGraphNodes(graph).map((node) => node.id),
|
||||
[1, 2],
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user