Files
Claude 2040792699 Refactor to v0.2.0: context chaining, new output nodes, simplified switch
Major changes:
- PD Project Context: accepts incoming context for override chaining,
  adds auto_increment_version (persistent via widget state, like seed)
- New PD Custom Context: 5 user-defined key/value token pairs
- Replace PD Output Namer + PD Network Output with:
  - PD Output Relative (saves to ComfyUI output dir)
  - PD Output Absolute (saves to absolute/UNC paths)
  Both show a token reference panel via JS after execution
- PD Switch simplified to single-channel with auto-growing inputs (2-8)
  managed by JS extension (onConnectionsChange pattern)
- 💭 emoji prefix on all node display names (with Windows fallback)
- Consolidated all JS extensions into web/pipedream.js
- Backward compat: PDOutputNamer/PDNetworkOutput aliases preserved

https://claude.ai/code/session_015UV4rjSvFatMiNtKhd1sT3
2026-04-03 06:03:18 +00:00

157 lines
5.6 KiB
JavaScript

import { app } from "../../scripts/app.js";
/* ------------------------------------------------------------------ */
/* Pipedream.Rasterizer — read-only preview textarea */
/* ------------------------------------------------------------------ */
app.registerExtension({
name: "Pipedream.Rasterizer",
async nodeCreated(node) {
if (node.comfyClass !== "PDRasterizer") return;
const widget = node.addWidget("customtext", "preview_display", "", () => {}, {
multiline: true,
dynamicPrompts: false,
});
widget.inputEl.readOnly = true;
widget.inputEl.style.fontFamily = "monospace";
widget.inputEl.style.fontSize = "11px";
widget.inputEl.style.opacity = "0.85";
const origOnExecuted = node.onExecuted;
node.onExecuted = function (output) {
if (origOnExecuted) origOnExecuted.call(this, output);
if (output?.preview_table?.length > 0) {
widget.value = output.preview_table[0];
}
};
},
});
/* ------------------------------------------------------------------ */
/* Pipedream.OutputTokenRef — read-only token reference display */
/* Shared by PDOutputRelative and PDOutputAbsolute */
/* ------------------------------------------------------------------ */
app.registerExtension({
name: "Pipedream.OutputTokenRef",
async nodeCreated(node) {
if (node.comfyClass !== "PDOutputRelative" &&
node.comfyClass !== "PDOutputAbsolute") return;
const widget = node.addWidget("customtext", "token_display", "", () => {}, {
multiline: true,
dynamicPrompts: false,
});
widget.inputEl.readOnly = true;
widget.inputEl.style.fontFamily = "monospace";
widget.inputEl.style.fontSize = "11px";
widget.inputEl.style.opacity = "0.85";
widget.inputEl.placeholder = "Token reference appears after execution...";
const origOnExecuted = node.onExecuted;
node.onExecuted = function (output) {
if (origOnExecuted) origOnExecuted.call(this, output);
if (output?.token_reference?.length > 0) {
widget.value = output.token_reference[0];
}
};
},
});
/* ------------------------------------------------------------------ */
/* Pipedream.Switch — auto-growing input slots */
/* ------------------------------------------------------------------ */
app.registerExtension({
name: "Pipedream.Switch",
async nodeCreated(node) {
if (node.comfyClass !== "PDSwitch") return;
const MIN_INPUTS = 2;
const MAX_INPUTS = 8;
const PREFIX = "input_";
function getInputSlots() {
return (node.inputs || []).filter(inp => inp.name.startsWith(PREFIX));
}
function getHighestConnected() {
const slots = node.inputs || [];
let highest = -1;
for (let i = slots.length - 1; i >= 0; i--) {
if (slots[i].name.startsWith(PREFIX) && slots[i].link != null) {
const num = parseInt(slots[i].name.replace(PREFIX, ""), 10);
if (num > highest) highest = num;
}
}
return highest;
}
function syncSlots() {
const current = getInputSlots().length;
const highestConnected = getHighestConnected();
// Target: one more than highest connected, clamped to [MIN, MAX]
let target = Math.max(MIN_INPUTS, highestConnected + 1);
target = Math.min(target, MAX_INPUTS);
// Add slots if needed
while (getInputSlots().length < target) {
const next = getInputSlots().length + 1;
node.addInput(PREFIX + next, "*");
}
// Remove trailing empty slots if needed
while (getInputSlots().length > target) {
const slots = getInputSlots();
const last = slots[slots.length - 1];
if (last.link != null) break; // don't remove connected
const idx = node.inputs.indexOf(last);
if (idx !== -1) node.removeInput(idx);
}
}
// Initial setup: show 3 inputs
const existing = getInputSlots().length;
for (let i = existing + 1; i <= 3; i++) {
if (!node.inputs?.find(inp => inp.name === PREFIX + i)) {
node.addInput(PREFIX + i, "*");
}
}
const origOnConnectionsChange = node.onConnectionsChange;
node.onConnectionsChange = function (type, index, connected, linkInfo) {
if (origOnConnectionsChange) {
origOnConnectionsChange.call(this, type, index, connected, linkInfo);
}
syncSlots();
};
},
});
/* ------------------------------------------------------------------ */
/* Pipedream.ProjectContext — version auto-increment widget update */
/* ------------------------------------------------------------------ */
app.registerExtension({
name: "Pipedream.ProjectContext",
async nodeCreated(node) {
if (node.comfyClass !== "PDProjectContext") return;
const origOnExecuted = node.onExecuted;
node.onExecuted = function (output) {
if (origOnExecuted) origOnExecuted.call(this, output);
if (output?.version?.length > 0) {
const versionWidget = this.widgets?.find(w => w.name === "version");
if (versionWidget) {
versionWidget.value = output.version[0];
}
}
};
},
});