Merge pull request #95 from space-nuko/frontend-note
Frontend Markdown note
This commit is contained in:
Submodule litegraph updated: 9b8d28d3e2...7c38fa4aed
@@ -50,6 +50,7 @@
|
|||||||
"@codemirror/search": "^6.2.2",
|
"@codemirror/search": "^6.2.2",
|
||||||
"@codemirror/state": "^6.1.2",
|
"@codemirror/state": "^6.1.2",
|
||||||
"@codemirror/view": "^6.4.1",
|
"@codemirror/view": "^6.4.1",
|
||||||
|
"@dogagenc/svelte-markdown": "^0.2.4",
|
||||||
"@gradio/accordion": "workspace:*",
|
"@gradio/accordion": "workspace:*",
|
||||||
"@gradio/atoms": "workspace:*",
|
"@gradio/atoms": "workspace:*",
|
||||||
"@gradio/button": "workspace:*",
|
"@gradio/button": "workspace:*",
|
||||||
@@ -85,6 +86,7 @@
|
|||||||
"framework7": "^8.0.3",
|
"framework7": "^8.0.3",
|
||||||
"framework7-svelte": "^8.0.3",
|
"framework7-svelte": "^8.0.3",
|
||||||
"img-comparison-slider": "^8.0.0",
|
"img-comparison-slider": "^8.0.0",
|
||||||
|
"marked": "^5.0.3",
|
||||||
"pollen-css": "^4.6.2",
|
"pollen-css": "^4.6.2",
|
||||||
"radix-icons-svelte": "^1.2.1",
|
"radix-icons-svelte": "^1.2.1",
|
||||||
"style-mod": "^4.0.3",
|
"style-mod": "^4.0.3",
|
||||||
|
|||||||
35
pnpm-lock.yaml
generated
35
pnpm-lock.yaml
generated
@@ -25,6 +25,9 @@ importers:
|
|||||||
'@codemirror/view':
|
'@codemirror/view':
|
||||||
specifier: ^6.4.1
|
specifier: ^6.4.1
|
||||||
version: 6.11.0
|
version: 6.11.0
|
||||||
|
'@dogagenc/svelte-markdown':
|
||||||
|
specifier: ^0.2.4
|
||||||
|
version: 0.2.4(svelte@3.58.0)
|
||||||
'@gradio/accordion':
|
'@gradio/accordion':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:gradio/js/accordion
|
version: link:gradio/js/accordion
|
||||||
@@ -130,6 +133,9 @@ importers:
|
|||||||
img-comparison-slider:
|
img-comparison-slider:
|
||||||
specifier: ^8.0.0
|
specifier: ^8.0.0
|
||||||
version: 8.0.0
|
version: 8.0.0
|
||||||
|
marked:
|
||||||
|
specifier: ^5.0.3
|
||||||
|
version: 5.0.3
|
||||||
pollen-css:
|
pollen-css:
|
||||||
specifier: ^4.6.2
|
specifier: ^4.6.2
|
||||||
version: 4.6.2
|
version: 4.6.2
|
||||||
@@ -1357,7 +1363,6 @@ packages:
|
|||||||
'@codemirror/language': ^6.0.0
|
'@codemirror/language': ^6.0.0
|
||||||
'@codemirror/state': ^6.0.0
|
'@codemirror/state': ^6.0.0
|
||||||
'@codemirror/view': ^6.0.0
|
'@codemirror/view': ^6.0.0
|
||||||
'@lezer/common': ^1.0.0
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@codemirror/language': 6.6.0
|
'@codemirror/language': 6.6.0
|
||||||
'@codemirror/state': 6.2.0
|
'@codemirror/state': 6.2.0
|
||||||
@@ -1501,6 +1506,16 @@ packages:
|
|||||||
w3c-keyname: 2.2.6
|
w3c-keyname: 2.2.6
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@dogagenc/svelte-markdown@0.2.4(svelte@3.58.0):
|
||||||
|
resolution: {integrity: sha512-UmmHHZ7rilAbBYiNsxuL5d8Ac79EhFXrhjsUNr30BPzn+T7ohJR8kHMFjDYDQc0tOQOfKbICvkPAQ6cprqS3Eg==}
|
||||||
|
peerDependencies:
|
||||||
|
svelte: ^3.0.0
|
||||||
|
dependencies:
|
||||||
|
'@types/marked': 4.3.1
|
||||||
|
marked: 4.3.0
|
||||||
|
svelte: 3.58.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@esbuild/android-arm64@0.17.18:
|
/@esbuild/android-arm64@0.17.18:
|
||||||
resolution: {integrity: sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==}
|
resolution: {integrity: sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -2423,6 +2438,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
|
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/marked@4.3.1:
|
||||||
|
resolution: {integrity: sha512-vSSbKZFbNktrQ15v7o1EaH78EbWV+sPQbPjHG+Cp8CaNcPFUEfjZ0Iml/V0bFDwsTlYe8o6XC5Hfdp91cqPV2g==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/node@10.17.60:
|
/@types/node@10.17.60:
|
||||||
resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==}
|
resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==}
|
||||||
dev: false
|
dev: false
|
||||||
@@ -3098,8 +3117,6 @@ packages:
|
|||||||
'@codemirror/search': 6.4.0
|
'@codemirror/search': 6.4.0
|
||||||
'@codemirror/state': 6.2.0
|
'@codemirror/state': 6.2.0
|
||||||
'@codemirror/view': 6.11.0
|
'@codemirror/view': 6.11.0
|
||||||
transitivePeerDependencies:
|
|
||||||
- '@lezer/common'
|
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/codemirror@6.0.1(@lezer/common@1.0.2):
|
/codemirror@6.0.1(@lezer/common@1.0.2):
|
||||||
@@ -5481,6 +5498,18 @@ packages:
|
|||||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/marked@4.3.0:
|
||||||
|
resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==}
|
||||||
|
engines: {node: '>= 12'}
|
||||||
|
hasBin: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/marked@5.0.3:
|
||||||
|
resolution: {integrity: sha512-KUONa43Uk74uUNWMxh6lfaNYmSAsRMiDAaX8QBCCRVXzEufR0zX6T33vrGbvTnQLL02ungDM3KSzZtO+chJaHg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
hasBin: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
/md5-hex@3.0.1:
|
/md5-hex@3.0.1:
|
||||||
resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==}
|
resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
export let elem_classes: string[] = []
|
export let elem_classes: string[] = []
|
||||||
export let style: string = ""
|
export let style: string = ""
|
||||||
export let label: string = ""
|
export let label: string = ""
|
||||||
|
export let mask: ComfyImageLocation | null;
|
||||||
// let propsChanged: Writable<number> | null = null;
|
// let propsChanged: Writable<number> | null = null;
|
||||||
let dragging = false;
|
let dragging = false;
|
||||||
let pending_upload = false;
|
let pending_upload = false;
|
||||||
@@ -172,6 +173,15 @@
|
|||||||
bind:naturalWidth={imgWidth}
|
bind:naturalWidth={imgWidth}
|
||||||
bind:naturalHeight={imgHeight}
|
bind:naturalHeight={imgHeight}
|
||||||
/>
|
/>
|
||||||
|
{#key mask}
|
||||||
|
{#if mask}
|
||||||
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<img src={convertComfyOutputToComfyURL(mask)}
|
||||||
|
alt={firstImage.filename}
|
||||||
|
on:click={onImgClicked}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
{/key}
|
||||||
{:else}
|
{:else}
|
||||||
<Upload
|
<Upload
|
||||||
file_count={fileCount}
|
file_count={fileCount}
|
||||||
@@ -201,6 +211,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ function getConnectionPos(node: SerializedLGraphNode, is_input: boolean, slotNum
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSerializedWidgetNode(vanillaWorkflow: ComfyVanillaWorkflow, node: SerializedLGraphNode, slotIndex: number, isInput: boolean, widgetNodeType: string, value: any): [ComfyWidgetNode, SerializedComfyWidgetNode] {
|
function createSerializedWidgetNode(vanillaWorkflow: ComfyVanillaWorkflow, widgetNodeType: string, value: any, node?: SerializedLGraphNode, slotIndex?: number, isInput?: boolean): [ComfyWidgetNode, SerializedComfyWidgetNode] {
|
||||||
const comfyWidgetNode = LiteGraph.createNode<ComfyWidgetNode>(widgetNodeType);
|
const comfyWidgetNode = LiteGraph.createNode<ComfyWidgetNode>(widgetNodeType);
|
||||||
comfyWidgetNode.flags.collapsed = true;
|
comfyWidgetNode.flags.collapsed = true;
|
||||||
const size: Vector2 = [0, 0];
|
const size: Vector2 = [0, 0];
|
||||||
@@ -85,12 +85,15 @@ function createSerializedWidgetNode(vanillaWorkflow: ComfyVanillaWorkflow, node:
|
|||||||
const serWidgetNode = comfyWidgetNode.serialize() as SerializedComfyWidgetNode;
|
const serWidgetNode = comfyWidgetNode.serialize() as SerializedComfyWidgetNode;
|
||||||
serWidgetNode.comfyValue = value;
|
serWidgetNode.comfyValue = value;
|
||||||
serWidgetNode.shownOutputProperties = {};
|
serWidgetNode.shownOutputProperties = {};
|
||||||
getConnectionPos(node, isInput, slotIndex, serWidgetNode.pos);
|
|
||||||
if (isInput)
|
if (node != null) {
|
||||||
serWidgetNode.pos[0] -= size[0] - 20;
|
getConnectionPos(node, isInput, slotIndex, serWidgetNode.pos);
|
||||||
else
|
if (isInput)
|
||||||
serWidgetNode.pos[0] += 20;
|
serWidgetNode.pos[0] -= size[0] - 20;
|
||||||
serWidgetNode.pos[1] += LiteGraph.NODE_TITLE_HEIGHT / 2;
|
else
|
||||||
|
serWidgetNode.pos[0] += 20;
|
||||||
|
serWidgetNode.pos[1] += LiteGraph.NODE_TITLE_HEIGHT / 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (widgetNodeType === "ui/text" && typeof value === "string" && value.indexOf("\n") != -1) {
|
if (widgetNodeType === "ui/text" && typeof value === "string" && value.indexOf("\n") != -1) {
|
||||||
const lineCount = countNewLines(value);
|
const lineCount = countNewLines(value);
|
||||||
@@ -260,11 +263,12 @@ function convertPrimitiveNode(vanillaWorkflow: ComfyVanillaWorkflow, node: Seria
|
|||||||
|
|
||||||
const [comfyWidgetNode, serWidgetNode] = createSerializedWidgetNode(
|
const [comfyWidgetNode, serWidgetNode] = createSerializedWidgetNode(
|
||||||
vanillaWorkflow,
|
vanillaWorkflow,
|
||||||
|
widgetNodeType,
|
||||||
|
value,
|
||||||
node,
|
node,
|
||||||
0, // first output on the PrimitiveNode
|
0, // first output on the PrimitiveNode
|
||||||
false, // this is an output slot index
|
false // this is an output slot index
|
||||||
widgetNodeType,
|
);
|
||||||
value);
|
|
||||||
|
|
||||||
// Set the UI node's min/max/step from the node def
|
// Set the UI node's min/max/step from the node def
|
||||||
configureWidgetNodeProperties(serWidgetNode, widgetOpts)
|
configureWidgetNodeProperties(serWidgetNode, widgetOpts)
|
||||||
@@ -381,6 +385,20 @@ export default function convertVanillaWorkflow(vanillaWorkflow: ComfyVanillaWork
|
|||||||
removeSerializedNode(vanillaWorkflow, node);
|
removeSerializedNode(vanillaWorkflow, node);
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
else if (node.type === "Note") {
|
||||||
|
const [comfyWidgetNode, serWidgetNode] = createSerializedWidgetNode(
|
||||||
|
vanillaWorkflow,
|
||||||
|
"ui/markdown",
|
||||||
|
node.widgets_values[0]
|
||||||
|
);
|
||||||
|
serWidgetNode.pos = [node.pos[0], node.pos[1]]
|
||||||
|
|
||||||
|
const group = layoutState.addContainer(left, { title: "" })
|
||||||
|
layoutState.addWidget(group, comfyWidgetNode)
|
||||||
|
|
||||||
|
removeSerializedNode(vanillaWorkflow, node);
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
const def = ComfyApp.knownBackendNodes[node.type];
|
const def = ComfyApp.knownBackendNodes[node.type];
|
||||||
if (def == null) {
|
if (def == null) {
|
||||||
@@ -449,11 +467,12 @@ export default function convertVanillaWorkflow(vanillaWorkflow: ComfyVanillaWork
|
|||||||
|
|
||||||
const [comfyWidgetNode, serWidgetNode] = createSerializedWidgetNode(
|
const [comfyWidgetNode, serWidgetNode] = createSerializedWidgetNode(
|
||||||
vanillaWorkflow,
|
vanillaWorkflow,
|
||||||
|
widgetNodeType,
|
||||||
|
value,
|
||||||
node,
|
node,
|
||||||
connInputIndex,
|
connInputIndex,
|
||||||
true,
|
true
|
||||||
widgetNodeType,
|
);
|
||||||
value);
|
|
||||||
|
|
||||||
configureWidgetNodeProperties(serWidgetNode, inputOpts)
|
configureWidgetNodeProperties(serWidgetNode, inputOpts)
|
||||||
|
|
||||||
@@ -492,11 +511,12 @@ export default function convertVanillaWorkflow(vanillaWorkflow: ComfyVanillaWork
|
|||||||
// Let's create a gallery for this output node and hook it up
|
// Let's create a gallery for this output node and hook it up
|
||||||
const [comfyGalleryNode, serGalleryNode] = createSerializedWidgetNode(
|
const [comfyGalleryNode, serGalleryNode] = createSerializedWidgetNode(
|
||||||
vanillaWorkflow,
|
vanillaWorkflow,
|
||||||
|
"ui/gallery",
|
||||||
|
[],
|
||||||
node,
|
node,
|
||||||
connOutputIndex,
|
connOutputIndex,
|
||||||
false,
|
false,
|
||||||
"ui/gallery",
|
);
|
||||||
[]);
|
|
||||||
|
|
||||||
if (group == null)
|
if (group == null)
|
||||||
group = layoutState.addContainer(isOutputNode ? right : left, { title: node.title || node.type })
|
group = layoutState.addContainer(isOutputNode ? right : left, { title: node.title || node.type })
|
||||||
|
|||||||
57
src/lib/nodes/widgets/ComfyMarkdownNode.ts
Normal file
57
src/lib/nodes/widgets/ComfyMarkdownNode.ts
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import { BuiltInSlotType, LiteGraph, type ITextWidget, type SlotLayout } from "@litegraph-ts/core";
|
||||||
|
|
||||||
|
import MarkdownWidget from "$lib/widgets/MarkdownWidget.svelte";
|
||||||
|
import ComfyWidgetNode, { type ComfyWidgetProperties } from "./ComfyWidgetNode";
|
||||||
|
|
||||||
|
export interface ComfyMarkdownProperties extends ComfyWidgetProperties {
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ComfyMarkdownNode extends ComfyWidgetNode<string> {
|
||||||
|
override properties: ComfyMarkdownProperties = {
|
||||||
|
tags: [],
|
||||||
|
defaultValue: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
static slotLayout: SlotLayout = {
|
||||||
|
inputs: [
|
||||||
|
{ name: "store", type: BuiltInSlotType.ACTION }
|
||||||
|
],
|
||||||
|
outputs: [
|
||||||
|
{ name: "value", type: "string" },
|
||||||
|
{ name: "changed", type: BuiltInSlotType.EVENT },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
override svelteComponentType = MarkdownWidget;
|
||||||
|
override defaultValue = "";
|
||||||
|
|
||||||
|
constructor(name?: string) {
|
||||||
|
super(name, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
override createDisplayWidget(): ITextWidget {
|
||||||
|
const widget = this.addWidget<ITextWidget>(
|
||||||
|
"text",
|
||||||
|
"Value",
|
||||||
|
"",
|
||||||
|
(v: string) => {
|
||||||
|
if (v == null || v === this.getValue()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setValue(v);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
multiline: true,
|
||||||
|
inputStyle: { fontFamily: "monospace" }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteGraph.registerNodeType({
|
||||||
|
class: ComfyMarkdownNode,
|
||||||
|
title: "UI.Markdown",
|
||||||
|
desc: "Displays Markdown in the UI",
|
||||||
|
type: "ui/markdown"
|
||||||
|
})
|
||||||
@@ -106,13 +106,18 @@ export default abstract class ComfyWidgetNode<T = any> extends ComfyGraphNode {
|
|||||||
this.value = writable(value)
|
this.value = writable(value)
|
||||||
this.color ||= color.color
|
this.color ||= color.color
|
||||||
this.bgColor ||= color.bgColor
|
this.bgColor ||= color.bgColor
|
||||||
this.displayWidget = this.addWidget<ITextWidget>(
|
this.displayWidget = this.createDisplayWidget();
|
||||||
|
this.unsubscribe = this.value.subscribe(this.onValueUpdated.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
protected createDisplayWidget(): ITextWidget {
|
||||||
|
const widget = this.addWidget<ITextWidget>(
|
||||||
"text",
|
"text",
|
||||||
"Value",
|
"Value",
|
||||||
""
|
""
|
||||||
);
|
)
|
||||||
this.displayWidget.disabled = true; // prevent editing
|
widget.disabled = true; // prevent editing
|
||||||
this.unsubscribe = this.value.subscribe(this.onValueUpdated.bind(this))
|
return widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
addPropertyAsOutput(propertyName: string, type: string) {
|
addPropertyAsOutput(propertyName: string, type: string) {
|
||||||
|
|||||||
@@ -9,3 +9,4 @@ export { default as ComfyRadioNode } from "./ComfyRadioNode"
|
|||||||
export { default as ComfyNumberNode } from "./ComfyNumberNode"
|
export { default as ComfyNumberNode } from "./ComfyNumberNode"
|
||||||
export { default as ComfyTextNode } from "./ComfyTextNode"
|
export { default as ComfyTextNode } from "./ComfyTextNode"
|
||||||
export { default as ComfyMultiRegionNode } from "./ComfyMultiRegionNode"
|
export { default as ComfyMultiRegionNode } from "./ComfyMultiRegionNode"
|
||||||
|
export { default as ComfyMarkdownNode } from "./ComfyMarkdownNode"
|
||||||
|
|||||||
@@ -52,12 +52,19 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
let hasImage = false;
|
let hasImage = false;
|
||||||
|
|
||||||
$: hasImage = $nodeValue && $nodeValue.length > 0;
|
$: hasImage = $nodeValue && $nodeValue.length > 0;
|
||||||
$: if (!hasImage) {
|
$: if (!hasImage) {
|
||||||
editMask = false;
|
editMask = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mask: ComfyImageLocation | null;
|
||||||
|
$: if (hasImage && canMask) {
|
||||||
|
mask = $nodeValue[0].children?.find(i => i.tags.includes("mask"))?.comfyUIFile;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mask = null;
|
||||||
|
}
|
||||||
|
|
||||||
const MASK_FILENAME: string = "ComfyBoxMask.png"
|
const MASK_FILENAME: string = "ComfyBoxMask.png"
|
||||||
|
|
||||||
async function onMaskReleased(e: CustomEvent<MaskCanvasData>) {
|
async function onMaskReleased(e: CustomEvent<MaskCanvasData>) {
|
||||||
@@ -122,6 +129,7 @@
|
|||||||
// TODO other child image types preserved here?
|
// TODO other child image types preserved here?
|
||||||
image.children = [];
|
image.children = [];
|
||||||
}
|
}
|
||||||
|
mask = null;
|
||||||
if (maskCanvasComp) {
|
if (maskCanvasComp) {
|
||||||
maskCanvasComp.clearStrokes();
|
maskCanvasComp.clearStrokes();
|
||||||
}
|
}
|
||||||
@@ -232,6 +240,7 @@
|
|||||||
<ImageUpload value={_value}
|
<ImageUpload value={_value}
|
||||||
bind:imgWidth={$imgWidth}
|
bind:imgWidth={$imgWidth}
|
||||||
bind:imgHeight={$imgHeight}
|
bind:imgHeight={$imgHeight}
|
||||||
|
{mask}
|
||||||
fileCount={"single"}
|
fileCount={"single"}
|
||||||
elem_classes={[]}
|
elem_classes={[]}
|
||||||
style={""}
|
style={""}
|
||||||
|
|||||||
233
src/lib/widgets/MarkdownWidget.svelte
Normal file
233
src/lib/widgets/MarkdownWidget.svelte
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { type WidgetLayout } from "$lib/stores/layoutStates";
|
||||||
|
import { get, type Writable, writable } from "svelte/store";
|
||||||
|
import { Block } from "@gradio/atoms";
|
||||||
|
import type { ComfyMarkdownNode } from "$lib/nodes/widgets";
|
||||||
|
import SvelteMarkdown from "@dogagenc/svelte-markdown"
|
||||||
|
import NullMarkdownRenderer from "./markdown/NullMarkdownRenderer.svelte"
|
||||||
|
import { SvelteComponentDev } from "svelte/internal";
|
||||||
|
|
||||||
|
export let widget: WidgetLayout | null = null;
|
||||||
|
export let isMobile: boolean = false;
|
||||||
|
|
||||||
|
let node: ComfyMarkdownNode | null = null;
|
||||||
|
let nodeValue: Writable<string> = writable("");
|
||||||
|
let attrsChanged: Writable<number> = writable(0);
|
||||||
|
|
||||||
|
let renderers: Record<string, typeof SvelteComponentDev> = {
|
||||||
|
"html": NullMarkdownRenderer
|
||||||
|
}
|
||||||
|
|
||||||
|
$: widget && setNodeValue(widget);
|
||||||
|
|
||||||
|
function setNodeValue(widget: WidgetLayout) {
|
||||||
|
if (widget) {
|
||||||
|
node = widget.node as ComfyMarkdownNode
|
||||||
|
nodeValue = node.value;
|
||||||
|
attrsChanged = widget.attrsChanged;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="wrapper prose">
|
||||||
|
{#key $attrsChanged}
|
||||||
|
{#if widget !== null && node !== null}
|
||||||
|
<Block>
|
||||||
|
<SvelteMarkdown source={$nodeValue} {renderers} />
|
||||||
|
</Block>
|
||||||
|
{/if}
|
||||||
|
{/key}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.wrapper {
|
||||||
|
padding: 2px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
:global(> button) {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(> .block) {
|
||||||
|
border-radius: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose {
|
||||||
|
font-weight: var(--prose-text-weight);
|
||||||
|
font-size: var(--text-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose * {
|
||||||
|
color: var(--body-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose p {
|
||||||
|
margin-bottom: var(--spacing-sm);
|
||||||
|
line-height: var(--line-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* headings
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
|
||||||
|
.prose h1,
|
||||||
|
.prose h2,
|
||||||
|
.prose h3,
|
||||||
|
.prose h4,
|
||||||
|
.prose h5 {
|
||||||
|
margin: var(--spacing-xxl) 0 var(--spacing-lg);
|
||||||
|
font-weight: var(--prose-header-text-weight);
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose > *:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose h1 {
|
||||||
|
margin-top: 0;
|
||||||
|
font-size: var(--text-xxl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose h2 {
|
||||||
|
font-size: var(--text-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose h3 {
|
||||||
|
font-size: var(--text-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose h4 {
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose h5 {
|
||||||
|
font-size: 1.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* lists
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
.prose ul {
|
||||||
|
list-style: circle inside;
|
||||||
|
}
|
||||||
|
.prose ol {
|
||||||
|
list-style: decimal inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose ul > p,
|
||||||
|
.prose li > p {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.prose ol,
|
||||||
|
.prose ul {
|
||||||
|
margin-top: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
.prose ul ul,
|
||||||
|
.prose ul ol,
|
||||||
|
.prose ol ol,
|
||||||
|
.prose ol ul {
|
||||||
|
margin: 0.5em 0 0.5em 3em;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
.prose li {
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* code
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
.prose code {
|
||||||
|
border: 1px solid var(--border-color-primary);
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
background: var(--background-fill-secondary);
|
||||||
|
padding: 1px 3px;
|
||||||
|
font-size: 85%;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.prose pre > code {
|
||||||
|
display: block;
|
||||||
|
padding: 0.5em 0.7em;
|
||||||
|
/* font-size: 100%; */
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tables
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
.prose th,
|
||||||
|
.prose td {
|
||||||
|
border-bottom: 1px solid #e1e1e1;
|
||||||
|
padding: 12px 15px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.prose th:first-child,
|
||||||
|
.prose td:first-child {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
.prose th:last-child,
|
||||||
|
.prose td:last-child {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* spacing
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
.prose button,
|
||||||
|
.prose .button {
|
||||||
|
margin-bottom: var(--spacing-sm);
|
||||||
|
}
|
||||||
|
.prose input,
|
||||||
|
.prose textarea,
|
||||||
|
.prose select,
|
||||||
|
.prose fieldset {
|
||||||
|
margin-bottom: var(--spacing-sm);
|
||||||
|
}
|
||||||
|
.prose pre,
|
||||||
|
.prose blockquote,
|
||||||
|
.prose dl,
|
||||||
|
.prose figure,
|
||||||
|
.prose table,
|
||||||
|
.prose p,
|
||||||
|
.prose ul,
|
||||||
|
.prose ol,
|
||||||
|
.prose form {
|
||||||
|
margin-bottom: var(--spacing-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* links
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
.prose a {
|
||||||
|
color: var(--link-text-color);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose a:visited {
|
||||||
|
color: var(--link-text-color-visited);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose a:hover {
|
||||||
|
color: var(--link-text-color-hover);
|
||||||
|
}
|
||||||
|
.prose a:active {
|
||||||
|
color: var(--link-text-color-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* misc
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
|
||||||
|
.prose hr {
|
||||||
|
margin-top: 3em;
|
||||||
|
margin-bottom: 3.5em;
|
||||||
|
border-width: 0;
|
||||||
|
border-top: 1px solid #e1e1e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose blockquote {
|
||||||
|
margin: var(--size-6) 0 !important;
|
||||||
|
border-left: 5px solid var(--border-color-primary);
|
||||||
|
padding-left: var(--size-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose :last-child {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
7
src/lib/widgets/markdown/NullMarkdownRenderer.svelte
Normal file
7
src/lib/widgets/markdown/NullMarkdownRenderer.svelte
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
export let href = "";
|
||||||
|
export let title = undefined;
|
||||||
|
export let text = "";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div/>
|
||||||
Reference in New Issue
Block a user