Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
729084ca78 |
@@ -4,8 +4,6 @@ All notable changes to ComfyUI-AusBoss are documented here.
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 2.21.2 - 2026-11-06
|
||||
|
||||
- **Colored link buttons and pop-out notes keep their tile layout when shared.**
|
||||
Callout Tile and Workflow Note Tile save as distinct node types, so an older
|
||||
install can report what is missing. Tiles have larger editors and visible
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="105" height="20" role="img" aria-label="release: v2.21.2">
|
||||
<title>release: v2.21.2</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="105" height="20" role="img" aria-label="release: v2.21.1">
|
||||
<title>release: v2.21.1</title>
|
||||
<path fill="#555" d="M0 0h48v20H0z"/>
|
||||
<path fill="#00b4aa" d="M48 0h57v20H48z"/>
|
||||
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" font-size="11">
|
||||
<text x="24" y="14">release</text>
|
||||
<text x="76.5" y="14">v2.21.2</text>
|
||||
<text x="76.5" y="14">v2.21.1</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 425 B After Width: | Height: | Size: 425 B |
+1
-1
@@ -9,7 +9,7 @@ import { app } from "../../../scripts/app.js";
|
||||
// Must match `version` in pyproject.toml — scripts/release_preflight.py
|
||||
// enforces it. The backend serves its copy at /ausboss/pack_version; a
|
||||
// mismatch means the browser cached JavaScript from an older install.
|
||||
export const AUSBOSS_JS_VERSION = "2.21.2";
|
||||
export const AUSBOSS_JS_VERSION = "2.21.1";
|
||||
|
||||
export const BRAND = "#00b4aa"; // AusBoss teal — keep node accents consistent.
|
||||
export const BRAND_DARK = "#007f78";
|
||||
|
||||
@@ -166,14 +166,6 @@ export function noteIsEmpty(note) {
|
||||
);
|
||||
}
|
||||
|
||||
// A note shows its tile face when it is in tile layout and has anything to
|
||||
// show. The node is then just a button: the note itself opens in a dialog,
|
||||
// so there is no card inside the node whose height needs fitting.
|
||||
export function noteShowsTileFace(note) {
|
||||
if (!note || typeof note !== "object") return false;
|
||||
return note.layout === "tile" && !noteIsEmpty(note);
|
||||
}
|
||||
|
||||
// "ComfyUI/models/loras" - the folder hint under each group of rows.
|
||||
export function folderPath(dir) {
|
||||
if (!dir) return "ComfyUI/models";
|
||||
|
||||
@@ -34,7 +34,6 @@ import {
|
||||
matchInstalled,
|
||||
noteFit,
|
||||
noteIsEmpty,
|
||||
noteShowsTileFace,
|
||||
normalizeNote,
|
||||
packsFromGraph,
|
||||
parseMarkdown,
|
||||
@@ -709,13 +708,13 @@ function naturalHeight(state, width) {
|
||||
// as the node's floor. It never shrinks the node: a taller note keeps its
|
||||
// empty space until someone drags it shorter.
|
||||
function fitNote(state) {
|
||||
if (!classicCanvas()) return;
|
||||
// A tile face is a button, not a card: fitting it would measure the note
|
||||
// behind the button and grow a new tile straight back to full height.
|
||||
if (noteShowsTileFace(state.note)) {
|
||||
// A tile opens its content in a dialog. Keep its chosen canvas size,
|
||||
// rather than growing it to a full note's measured height.
|
||||
if (state.note.layout === "tile") {
|
||||
state.fitHeight = undefined;
|
||||
return;
|
||||
}
|
||||
if (!classicCanvas()) return;
|
||||
const { node, root, domWidget } = state;
|
||||
const width = node.size[0] - WIDGET_FRAME;
|
||||
if (!(width > 0)) return;
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ name = "ausboss-nodes"
|
||||
# Manager/registry search matches against this text, so it names the actual
|
||||
# nodes instead of describing the collection abstractly.
|
||||
description = "ComfyUI-AusBoss (AusBoss nodes): image and video nodes with compact controls: Image and Video Crop + Rotate + Pad (frame or clip), Load Image + Pad, Image Folder, Image Resize, Align Image, Image Size, Color Match, Image Compare A/B, Realign to Source (experimental), Save Image (PNG, WebP/JXL, captions), Load Video, Load Audio, Save Video, Select Frame, Frame Interpolate, Mask Refine, Mask by Name and Mask by Touch (type a name or click a thing, get its mask), LaMa Inpaint, Crop For Inpaint, Stitch Inpaint, Tiled Upscale and Tiled Upscale Stitch, LoRA Loader, Krea 2 Encode and Outpaint Model Patch, Latent Size, Layout Boxes, Seed, Select Every Nth, Split Batch, Merge Batches, Text, H3 Prompt Writer, Integer, Float, Math Expression, Show Text, Free Memory, Workflow Note, Workflow Note Tile, Callout, Callout Tile, Workflow Switches, Run Timer, and Step Preview (stop bad runs). Example workflows for Qwen Image 2.1, Krea 2, Klein 9B and LTX 2.3."
|
||||
version = "2.21.2"
|
||||
version = "2.21.1"
|
||||
# comfy-cli serializes this to JSON verbatim, so `file` publishes the literal
|
||||
# string {"file": "LICENSE"} to the registry listing. `text` puts a readable
|
||||
# name there instead. Both forms are supported; the LICENSE file is unchanged.
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
matchInstalled,
|
||||
noteFit,
|
||||
noteIsEmpty,
|
||||
noteShowsTileFace,
|
||||
normalizeNote,
|
||||
packsFromGraph,
|
||||
parseInline,
|
||||
@@ -199,23 +198,6 @@ test("noteFit ignores a card it could not measure", () => {
|
||||
assert.deepEqual(noteFit({ natural: 794.125, nodeHeight: undefined, chrome: 22 }), { fit: null, grow: false });
|
||||
});
|
||||
|
||||
test("a tile face shows only for a tile layout note that has content", () => {
|
||||
assert.equal(noteShowsTileFace(normalizeNote('{"title":"Workflow info","layout":"tile"}')), true);
|
||||
assert.equal(noteShowsTileFace(normalizeNote('{"title":"Workflow info","layout":"card"}')), false);
|
||||
assert.equal(noteShowsTileFace(normalizeNote('{"layout":"tile"}')), false);
|
||||
assert.equal(noteShowsTileFace(normalizeNote("")), false);
|
||||
assert.equal(noteShowsTileFace(null), false);
|
||||
});
|
||||
|
||||
test("the classic fit leaves a tile face compact", () => {
|
||||
const source = readFileSync(new URL("../js/workflow_note/index.js", import.meta.url), "utf-8");
|
||||
assert.match(
|
||||
source,
|
||||
/function fitNote\(state\) \{\n if \(!classicCanvas\(\)\) return;\n \/\/ A tile face is a button, not a card: fitting it would measure the note\n \/\/ behind the button and grow a new tile straight back to full height\.\n if \(noteShowsTileFace\(state\.note\)\) \{\n state\.fitHeight = undefined;\n return;\n \}/,
|
||||
"fitNote skips a note that shows its tile face, so a new tile keeps its compact start",
|
||||
);
|
||||
});
|
||||
|
||||
test("parseInline handles bold, italic, code and safe links", () => {
|
||||
assert.deepEqual(parseInline("a **b** *c* `d` [e](https://f.g) [h](javascript:x) i"), [
|
||||
{ type: "text", text: "a " },
|
||||
@@ -326,3 +308,35 @@ test("note formatting leaves old prose, unsafe markup and code literal", () => {
|
||||
assert.equal(parseInline("`[amber]warning[/amber]`")[0].type, "code");
|
||||
assert.equal(parseMarkdown("```\n|a|\n|---|\n```")[0].type, "code");
|
||||
});
|
||||
|
||||
// Exercise the actual browser fitter with measured layout inputs. Keeping the
|
||||
// DOM read behind a stub also proves a tile never measures its dialog content.
|
||||
const noteFrontend = readFileSync(new URL("../js/workflow_note/index.js", import.meta.url), "utf-8");
|
||||
const fitNoteSource = noteFrontend.slice(noteFrontend.indexOf("function fitNote(state) {"), noteFrontend.indexOf("// Every list widget", noteFrontend.indexOf("function fitNote(state) {")));
|
||||
const runFitNote = new Function("classicCanvas", "naturalHeight", "noteFit", "WIDGET_FRAME", "PANEL_TOP", `${fitNoteSource}; return fitNote;`);
|
||||
|
||||
test("tile fitting preserves default and saved heights despite a stale widget position", () => {
|
||||
const fit = runFitNote(() => true, () => 50, noteFit, 8, 2);
|
||||
for (const height of [80, 110, 160]) {
|
||||
const state = { note: { layout: "tile" }, fitHeight: 284,
|
||||
node: { size: [380, height], setSize: () => assert.fail("tile fitting must preserve its size") },
|
||||
root: { isConnected: true }, domWidget: { computedHeight: 50, y: 226 } };
|
||||
fit(state);
|
||||
assert.equal(state.fitHeight, undefined, "a tile must not retain a full note's resize floor");
|
||||
assert.equal(state.node.size[1], height);
|
||||
}
|
||||
});
|
||||
|
||||
test("card and banner fitting still grows to measured content and keeps taller saved sizes", () => {
|
||||
const fit = runFitNote(() => true, () => 300, noteFit, 8, 2);
|
||||
for (const layout of ["card", "banner"]) {
|
||||
for (const height of [80, 500]) {
|
||||
const state = { note: { layout }, node: { size: [380, height],
|
||||
setSize(size) { this.size = size; }, setDirtyCanvas() {} },
|
||||
root: { isConnected: true }, domWidget: { computedHeight: 50, y: 2 } };
|
||||
fit(state);
|
||||
assert.equal(state.fitHeight, 310);
|
||||
assert.equal(state.node.size[1], Math.max(height, 310));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user