diff --git a/__init__.py b/__init__.py index ae4acf0..111379f 100644 --- a/__init__.py +++ b/__init__.py @@ -19,6 +19,7 @@ class WASComfyViewer: }, "hidden": { "manual_content": ("STRING", {"default": ""}), + "excluded_indices": ("STRING", {"default": "[]"}), }, } @@ -30,7 +31,7 @@ class WASComfyViewer: FUNCTION = "run" CATEGORY = "WAS/View" - def run(self, content=None, manual_content=None): + def run(self, content=None, manual_content=None, excluded_indices=None): import json import logging @@ -63,10 +64,22 @@ class WASComfyViewer: if not isinstance(manual_content, list): manual_content = [manual_content] - content_trimmed = [c[:256] for c in content] - manual_content_trimmed = [c[:256] for c in manual_content] + excluded = [] + if excluded_indices: + excluded_str = excluded_indices[0] if isinstance(excluded_indices, list) else excluded_indices + try: + parsed = json.loads(excluded_str) + if isinstance(parsed, dict) and "excluded" in parsed: + excluded = parsed["excluded"] if isinstance(parsed["excluded"], list) else [] + elif isinstance(parsed, list): + excluded = parsed + except: + excluded = [] - logger.info(f"\n[WAS Viewer] Content:\n{content_trimmed}\nManual Content:\n{manual_content_trimmed}\n") + content_trimmed = [c[:256] if isinstance(c, str) else str(c)[:256] for c in content] + manual_content_trimmed = [c[:256] if isinstance(c, str) else str(c)[:256] for c in manual_content] + + logger.info(f"\n[WAS Viewer] Content:\n{content_trimmed}\nManual Content:\n{manual_content_trimmed}\nExcluded: {excluded}\n") if len(content) > 0 and any(c for c in content): values = [to_string(c) for c in content] @@ -79,7 +92,12 @@ class WASComfyViewer: logger.info("[WAS Viewer] No content, using empty") display_text = "\n---LIST_SEPARATOR---\n".join(values) - return {"ui": {"text": (display_text,)}, "result": (values,)} + + output_values = [v for i, v in enumerate(values) if i not in excluded] + if not output_values: + output_values = [""] + + return {"ui": {"text": (display_text,)}, "result": (output_values,)} NODE_CLASS_MAPPINGS = { diff --git a/web/comfy_viewer.js b/web/comfy_viewer.js index ec956b6..428d5fc 100644 --- a/web/comfy_viewer.js +++ b/web/comfy_viewer.js @@ -13,8 +13,40 @@ const STATE = { cleanupIntervalId: null, cleanupListenersAttached: false, lastScale: 1, + prismScripts: null, }; +const PRISM_FILES = [ + "prism.min.txt", + "prism-python.min.txt", + "prism-javascript.min.txt", + "prism-css.min.txt", + "prism-markup.min.txt", + "prism-json.min.txt", + "prism-bash.min.txt", +]; + +async function loadPrismScripts() { + if (STATE.prismScripts) return STATE.prismScripts; + + try { + const basePath = import.meta.url.substring(0, import.meta.url.lastIndexOf("/")); + const scripts = await Promise.all( + PRISM_FILES.map(async (file) => { + const res = await fetch(`${basePath}/${file}`); + return res.ok ? res.text() : ""; + }) + ); + STATE.prismScripts = scripts.join("\n"); + return STATE.prismScripts; + } catch (e) { + console.error("[WAS Viewer] Failed to load Prism scripts:", e); + return ""; + } +} + +loadPrismScripts(); + function readCssVar(style, name) { const v = style.getPropertyValue(name); return v ? String(v).trim() : ""; @@ -323,7 +355,7 @@ async function createZipBlob(files) { return new Blob(parts, { type: "application/zip" }); } -function buildIframeContent(content, contentType, theme) { +function buildIframeContent(content, contentType, theme, excluded = []) { const baseStyles = ` * { box-sizing: border-box; } html, body { @@ -406,6 +438,17 @@ function buildIframeContent(content, contentType, theme) { align-items: center; margin-bottom: 8px; } + .list-header-left { + display: flex; + align-items: center; + gap: 8px; + } + .list-checkbox { + width: 16px; + height: 16px; + cursor: pointer; + accent-color: ${theme.accent}; + } .list-index { display: inline-block; background: ${theme.accent}; @@ -415,6 +458,12 @@ function buildIframeContent(content, contentType, theme) { padding: 2px 6px; border-radius: 4px; } + .list-item.excluded { + opacity: 0.5; + } + .list-item.excluded .list-index { + background: #666; + } .copy-btn { background: transparent; border: 1px solid ${theme.border}; @@ -462,9 +511,13 @@ function buildIframeContent(content, contentType, theme) { } else { itemHtml = `
${escapeHtml(item)}
`; } - return `
+ const isExcluded = excluded.includes(idx); + return `
- ${idx + 1} / ${items.length} +
+ + ${idx + 1} / ${items.length} +