Files
IxMxAMAR-ComfyUI-Utility-Me…/web/themes/synthwave.js
T
IxMxAMAR 3f9e39bb44 v0.3.0: security hardening, audit fixes, 10 new ops, theme UX (matchMedia perf fix + sandbox + leaks + features)
Critical security fixes
-----------------------
- Sandbox Jinja2 in template_render + prompt_template_render (was RCE via shared workflows)
- Drop user home dir from filesystem allow-list (was arbitrary delete/overwrite)
- Confine save_image_with_manifest + sanitize filename basename
- SSRF block on http_get/http_post/notify_webhook (catches 169.254.169.254 metadata)
- Case-insensitive path confinement on Windows

Critical correctness/perf
-------------------------
- halftone_dots: O(N^2) -> O(cells*36); was freezing worker on 1024+ images
- Preserve latent dict keys (noise_mask, batch_index) in latent_math/noise/upscale
- Preserve alpha channel in invert + threshold_binary on RGBA inputs
- Force odd kernel in mask_erode/mask_dilate to prevent H+1 shape mismatch
- Snap aspect_ratio_pick output to multiples of 8 (was crashing SD UNet)

Theme engine (JS)
-----------------
- Hoist window.matchMedia() out of per-frame hot path -> recovers 200 FPS from 25
- Wrap-once draw method to stop stomping other extensions wrappers
- nodeRemoved hook + WeakMap groups + in-place canvas reuse -> three memory leaks closed
- Wire thickness now uses connections_width (the wrap was a no-op vs LiteGraph)
- onGroupAdded auto-themes new groups; budget change triggers redraw
- Gradient caching in synthwave/glassmorphic

New ops (10)
------------
- json_path (programming): dotted/bracketed path extract
- latent_nan_guard, latent_pad_crop (mask_latent)
- mask_from_depth, mask_invert (mask_latent)
- color_match_histogram, image_composite_over (image_pro/value)
- frequency_separation (image_pro/style)
- pad_to_multiple (image_pro/spatial)
- save_images_zip (io_workflow)
- llm_enhance_prompt via Ollama / LM Studio / llama.cpp (prompt)

Theme UX
--------
- Right-click "Theme..." submenu on every node (including vanilla ComfyUI nodes)
- Auto-contrast title text (WCAG AA-based flip)

Tests: 373 Python + 33 JS = 406 passing (added 33 new tests for security + features).
Full review notes in CHANGELOG.md.
2026-05-17 15:41:19 +05:30

63 lines
1.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Synthwave: 80s retro-futurism. Neon pink-to-purple header gradient,
// cyan accent. Distinguished from Cyberpunk by hot horizontal gradients
// rather than corner clips + glow.
const HEADER_STOPS = ["#ff007f", "#7900ff"];
export default {
id: "synthwave",
displayName: "Synthwave",
motion: "low",
staticConfig: {
bgcolor: "#120424",
color: "#1a0533",
titlecolor: "#1a0533",
titletext: "#ffffff",
boxcolor: "#00f0ff",
},
wirePalette: {
default: "#ff007f",
IMAGE: "#ff61dc",
LATENT: "#bf5af2",
MASK: "#00f0ff",
CONDITIONING: "#ffea00",
MODEL: "#ff5e5e",
},
categoryAccents: {
image: "#ff61dc",
latent: "#bf5af2",
conditioning: "#ffea00",
sampling: "#00f0ff",
default: "#ff007f",
},
groupColors: { color: "#ff007f", bgcolor: "#1a0533" },
bgGridColor: "#08011a",
drawForeground(ctx, node, themeApi) {
const w = node.size?.[0] ?? 0;
const h = node.size?.[1] ?? 0;
if (w <= 0 || h <= 0) return;
ctx.save();
// Cache the pink→purple gradient per (node, width). Reallocating a
// CanvasGradient every frame was measurable churn at 200Hz × many nodes.
let cached = node._mp_synthwave_grad;
if (!cached || cached.w !== w) {
const grad = ctx.createLinearGradient(0, 0, w, 0);
grad.addColorStop(0, HEADER_STOPS[0]);
grad.addColorStop(1, HEADER_STOPS[1]);
cached = node._mp_synthwave_grad = { w, grad };
}
ctx.fillStyle = cached.grad;
ctx.fillRect(0, -3, w, 3);
if (themeApi && themeApi.motionAllowed("low")) {
ctx.strokeStyle = "#00f0ff";
ctx.globalAlpha = 0.25;
ctx.lineWidth = 3;
ctx.strokeRect(0.5, 0.5, w - 1, h - 1);
ctx.globalAlpha = 0.8;
ctx.lineWidth = 1;
ctx.strokeRect(0.5, 0.5, w - 1, h - 1);
}
ctx.restore();
},
themeApiVersion: 2,
};