codemirror option for text widgets & danbooru tag autocomplete
This commit is contained in:
14
package.json
14
package.json
@@ -42,6 +42,13 @@
|
|||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@codemirror/autocomplete": "^6.3.0",
|
||||||
|
"@codemirror/commands": "^6.1.2",
|
||||||
|
"@codemirror/language": "^6.6.0",
|
||||||
|
"@codemirror/lint": "^6.0.0",
|
||||||
|
"@codemirror/search": "^6.2.2",
|
||||||
|
"@codemirror/state": "^6.1.2",
|
||||||
|
"@codemirror/view": "^6.4.1",
|
||||||
"@gradio/accordion": "workspace:*",
|
"@gradio/accordion": "workspace:*",
|
||||||
"@gradio/atoms": "workspace:*",
|
"@gradio/atoms": "workspace:*",
|
||||||
"@gradio/button": "workspace:*",
|
"@gradio/button": "workspace:*",
|
||||||
@@ -67,6 +74,11 @@
|
|||||||
"@tsconfig/svelte": "^4.0.1",
|
"@tsconfig/svelte": "^4.0.1",
|
||||||
"@zerodevx/svelte-json-view": "^1.0.5",
|
"@zerodevx/svelte-json-view": "^1.0.5",
|
||||||
"canvas-to-svg": "^1.0.3",
|
"canvas-to-svg": "^1.0.3",
|
||||||
|
"cm6-theme-basic-dark": "^0.2.0",
|
||||||
|
"cm6-theme-basic-light": "^0.2.0",
|
||||||
|
"codemirror": "^6.0.1",
|
||||||
|
"csv": "^6.3.0",
|
||||||
|
"csv-parse": "^5.3.10",
|
||||||
"events": "^3.3.0",
|
"events": "^3.3.0",
|
||||||
"framework7": "^8.0.3",
|
"framework7": "^8.0.3",
|
||||||
"framework7-svelte": "^8.0.3",
|
"framework7-svelte": "^8.0.3",
|
||||||
@@ -74,7 +86,9 @@
|
|||||||
"klecks": "workspace:*",
|
"klecks": "workspace:*",
|
||||||
"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",
|
||||||
"svelte-bootstrap-icons": "^2.3.1",
|
"svelte-bootstrap-icons": "^2.3.1",
|
||||||
|
"svelte-codemirror-editor": "^1.1.0",
|
||||||
"svelte-feather-icons": "^4.0.0",
|
"svelte-feather-icons": "^4.0.0",
|
||||||
"svelte-preprocess": "^5.0.3",
|
"svelte-preprocess": "^5.0.3",
|
||||||
"svelte-select": "^5.5.3",
|
"svelte-select": "^5.5.3",
|
||||||
|
|||||||
127
pnpm-lock.yaml
generated
127
pnpm-lock.yaml
generated
@@ -4,6 +4,27 @@ importers:
|
|||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@codemirror/autocomplete':
|
||||||
|
specifier: ^6.3.0
|
||||||
|
version: 6.6.1(@codemirror/language@6.6.0)(@codemirror/state@6.2.0)(@codemirror/view@6.11.0)
|
||||||
|
'@codemirror/commands':
|
||||||
|
specifier: ^6.1.2
|
||||||
|
version: 6.2.4
|
||||||
|
'@codemirror/language':
|
||||||
|
specifier: ^6.6.0
|
||||||
|
version: 6.6.0
|
||||||
|
'@codemirror/lint':
|
||||||
|
specifier: ^6.0.0
|
||||||
|
version: 6.2.1
|
||||||
|
'@codemirror/search':
|
||||||
|
specifier: ^6.2.2
|
||||||
|
version: 6.4.0
|
||||||
|
'@codemirror/state':
|
||||||
|
specifier: ^6.1.2
|
||||||
|
version: 6.2.0
|
||||||
|
'@codemirror/view':
|
||||||
|
specifier: ^6.4.1
|
||||||
|
version: 6.11.0
|
||||||
'@gradio/accordion':
|
'@gradio/accordion':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:gradio/js/accordion
|
version: link:gradio/js/accordion
|
||||||
@@ -79,6 +100,21 @@ importers:
|
|||||||
canvas-to-svg:
|
canvas-to-svg:
|
||||||
specifier: ^1.0.3
|
specifier: ^1.0.3
|
||||||
version: 1.0.3
|
version: 1.0.3
|
||||||
|
cm6-theme-basic-dark:
|
||||||
|
specifier: ^0.2.0
|
||||||
|
version: 0.2.0(@codemirror/language@6.6.0)(@codemirror/state@6.2.0)(@codemirror/view@6.11.0)
|
||||||
|
cm6-theme-basic-light:
|
||||||
|
specifier: ^0.2.0
|
||||||
|
version: 0.2.0(@codemirror/language@6.6.0)(@codemirror/state@6.2.0)(@codemirror/view@6.11.0)
|
||||||
|
codemirror:
|
||||||
|
specifier: ^6.0.1
|
||||||
|
version: 6.0.1
|
||||||
|
csv:
|
||||||
|
specifier: ^6.3.0
|
||||||
|
version: 6.3.0
|
||||||
|
csv-parse:
|
||||||
|
specifier: ^5.3.10
|
||||||
|
version: 5.3.10
|
||||||
events:
|
events:
|
||||||
specifier: ^3.3.0
|
specifier: ^3.3.0
|
||||||
version: 3.3.0
|
version: 3.3.0
|
||||||
@@ -100,9 +136,15 @@ importers:
|
|||||||
radix-icons-svelte:
|
radix-icons-svelte:
|
||||||
specifier: ^1.2.1
|
specifier: ^1.2.1
|
||||||
version: 1.2.1
|
version: 1.2.1
|
||||||
|
style-mod:
|
||||||
|
specifier: ^4.0.3
|
||||||
|
version: 4.0.3
|
||||||
svelte-bootstrap-icons:
|
svelte-bootstrap-icons:
|
||||||
specifier: ^2.3.1
|
specifier: ^2.3.1
|
||||||
version: 2.3.1
|
version: 2.3.1
|
||||||
|
svelte-codemirror-editor:
|
||||||
|
specifier: ^1.1.0
|
||||||
|
version: 1.1.0(codemirror@6.0.1)
|
||||||
svelte-feather-icons:
|
svelte-feather-icons:
|
||||||
specifier: ^4.0.0
|
specifier: ^4.0.0
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
@@ -1341,6 +1383,19 @@ packages:
|
|||||||
commander: 2.20.3
|
commander: 2.20.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@codemirror/autocomplete@6.6.1(@codemirror/language@6.6.0)(@codemirror/state@6.2.0)(@codemirror/view@6.11.0):
|
||||||
|
resolution: {integrity: sha512-RpsvnYOopnyNbZg487qoRD5bKg63KMMUVP5d8MQ4Luc7Mb6JBWTORovLi6cTvWaKlbmLW8Zd2dAJkIdrhBsXug==}
|
||||||
|
peerDependencies:
|
||||||
|
'@codemirror/language': ^6.0.0
|
||||||
|
'@codemirror/state': ^6.0.0
|
||||||
|
'@codemirror/view': ^6.0.0
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.6.0
|
||||||
|
'@codemirror/state': 6.2.0
|
||||||
|
'@codemirror/view': 6.11.0
|
||||||
|
'@lezer/common': 1.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@codemirror/autocomplete@6.6.1(@codemirror/language@6.6.0)(@codemirror/state@6.2.0)(@codemirror/view@6.11.0)(@lezer/common@1.0.2):
|
/@codemirror/autocomplete@6.6.1(@codemirror/language@6.6.0)(@codemirror/state@6.2.0)(@codemirror/view@6.11.0)(@lezer/common@1.0.2):
|
||||||
resolution: {integrity: sha512-RpsvnYOopnyNbZg487qoRD5bKg63KMMUVP5d8MQ4Luc7Mb6JBWTORovLi6cTvWaKlbmLW8Zd2dAJkIdrhBsXug==}
|
resolution: {integrity: sha512-RpsvnYOopnyNbZg487qoRD5bKg63KMMUVP5d8MQ4Luc7Mb6JBWTORovLi6cTvWaKlbmLW8Zd2dAJkIdrhBsXug==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3872,6 +3927,19 @@ packages:
|
|||||||
engines: {node: '>=0.8'}
|
engines: {node: '>=0.8'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/cm6-theme-basic-dark@0.2.0(@codemirror/language@6.6.0)(@codemirror/state@6.2.0)(@codemirror/view@6.11.0):
|
||||||
|
resolution: {integrity: sha512-+mNNJecRtxS/KkloMDCQF0oTrT6aFGRZTjnBcdT5UG1pcDO4Brq8l1+0KR/8dZ7hub2gOGOzoi3rGFD8GzlH7Q==}
|
||||||
|
peerDependencies:
|
||||||
|
'@codemirror/language': ^6.0.0
|
||||||
|
'@codemirror/state': ^6.0.0
|
||||||
|
'@codemirror/view': ^6.0.0
|
||||||
|
'@lezer/highlight': ^1.0.0
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.6.0
|
||||||
|
'@codemirror/state': 6.2.0
|
||||||
|
'@codemirror/view': 6.11.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/cm6-theme-basic-dark@0.2.0(@codemirror/language@6.6.0)(@codemirror/state@6.2.0)(@codemirror/view@6.11.0)(@lezer/highlight@1.1.4):
|
/cm6-theme-basic-dark@0.2.0(@codemirror/language@6.6.0)(@codemirror/state@6.2.0)(@codemirror/view@6.11.0)(@lezer/highlight@1.1.4):
|
||||||
resolution: {integrity: sha512-+mNNJecRtxS/KkloMDCQF0oTrT6aFGRZTjnBcdT5UG1pcDO4Brq8l1+0KR/8dZ7hub2gOGOzoi3rGFD8GzlH7Q==}
|
resolution: {integrity: sha512-+mNNJecRtxS/KkloMDCQF0oTrT6aFGRZTjnBcdT5UG1pcDO4Brq8l1+0KR/8dZ7hub2gOGOzoi3rGFD8GzlH7Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3886,6 +3954,19 @@ packages:
|
|||||||
'@lezer/highlight': 1.1.4
|
'@lezer/highlight': 1.1.4
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/cm6-theme-basic-light@0.2.0(@codemirror/language@6.6.0)(@codemirror/state@6.2.0)(@codemirror/view@6.11.0):
|
||||||
|
resolution: {integrity: sha512-1prg2gv44sYfpHscP26uLT/ePrh0mlmVwMSoSd3zYKQ92Ab3jPRLzyCnpyOCQLJbK+YdNs4HvMRqMNYdy4pMhA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@codemirror/language': ^6.0.0
|
||||||
|
'@codemirror/state': ^6.0.0
|
||||||
|
'@codemirror/view': ^6.0.0
|
||||||
|
'@lezer/highlight': ^1.0.0
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.6.0
|
||||||
|
'@codemirror/state': 6.2.0
|
||||||
|
'@codemirror/view': 6.11.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/cm6-theme-basic-light@0.2.0(@codemirror/language@6.6.0)(@codemirror/state@6.2.0)(@codemirror/view@6.11.0)(@lezer/highlight@1.1.4):
|
/cm6-theme-basic-light@0.2.0(@codemirror/language@6.6.0)(@codemirror/state@6.2.0)(@codemirror/view@6.11.0)(@lezer/highlight@1.1.4):
|
||||||
resolution: {integrity: sha512-1prg2gv44sYfpHscP26uLT/ePrh0mlmVwMSoSd3zYKQ92Ab3jPRLzyCnpyOCQLJbK+YdNs4HvMRqMNYdy4pMhA==}
|
resolution: {integrity: sha512-1prg2gv44sYfpHscP26uLT/ePrh0mlmVwMSoSd3zYKQ92Ab3jPRLzyCnpyOCQLJbK+YdNs4HvMRqMNYdy4pMhA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3909,6 +3990,18 @@ packages:
|
|||||||
resolution: {integrity: sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw==}
|
resolution: {integrity: sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/codemirror@6.0.1:
|
||||||
|
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/autocomplete': 6.6.1(@codemirror/language@6.6.0)(@codemirror/state@6.2.0)(@codemirror/view@6.11.0)
|
||||||
|
'@codemirror/commands': 6.2.4
|
||||||
|
'@codemirror/language': 6.6.0
|
||||||
|
'@codemirror/lint': 6.2.1
|
||||||
|
'@codemirror/search': 6.4.0
|
||||||
|
'@codemirror/state': 6.2.0
|
||||||
|
'@codemirror/view': 6.11.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/codemirror@6.0.1(@lezer/common@1.0.2):
|
/codemirror@6.0.1(@lezer/common@1.0.2):
|
||||||
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
|
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4133,6 +4226,28 @@ packages:
|
|||||||
rrweb-cssom: 0.6.0
|
rrweb-cssom: 0.6.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/csv-generate@4.2.6:
|
||||||
|
resolution: {integrity: sha512-VtnYqhWLcsUocA346ewFOk+rrqcoT663j11vXzD2uelXq9WguQ3QzDeVD8ISso7hhVtkDSHcWl9psdemeiEHDA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/csv-parse@5.3.10:
|
||||||
|
resolution: {integrity: sha512-cTXY6iy0gN5Ha/cGILeDgQE+nKiKDU2m0DjSRdJhr86BN3cM7oefBsTk2aH0LQeaYtL7Z7HvW+jYoadmdhzeDA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/csv-stringify@6.4.0:
|
||||||
|
resolution: {integrity: sha512-HQsw0QXiN5fdlO+R8/JzCZnR3Fqp8E87YVnhHlaPtNGJjt6ffbV0LpOkieIb1x6V1+xt878IYq77SpXHWAqKkA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/csv@6.3.0:
|
||||||
|
resolution: {integrity: sha512-wXakaMNIz6qe/a15AXQ6JA9urN2lEx08J/3xpxv7Ke3GOrio300Ikbqzrlg1ML0fuEOULHhswvSxtN5h/72sHg==}
|
||||||
|
engines: {node: '>= 0.1.90'}
|
||||||
|
dependencies:
|
||||||
|
csv-generate: 4.2.6
|
||||||
|
csv-parse: 5.3.10
|
||||||
|
csv-stringify: 6.4.0
|
||||||
|
stream-transform: 3.2.6
|
||||||
|
dev: false
|
||||||
|
|
||||||
/d3-array@3.2.2:
|
/d3-array@3.2.2:
|
||||||
resolution: {integrity: sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ==}
|
resolution: {integrity: sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -7801,6 +7916,10 @@ packages:
|
|||||||
/std-env@3.3.3:
|
/std-env@3.3.3:
|
||||||
resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==}
|
resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==}
|
||||||
|
|
||||||
|
/stream-transform@3.2.6:
|
||||||
|
resolution: {integrity: sha512-/pyOvaCQFqYTmrFhmMbnAEVo3SsTx1H39eUVPOtYeAgbEUc+rDo7GoP8LbHJgU83mKtzJe/7Nq/ipaAnUOHgJQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/streamsearch@1.1.0:
|
/streamsearch@1.1.0:
|
||||||
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
@@ -7978,6 +8097,14 @@ packages:
|
|||||||
- sugarss
|
- sugarss
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/svelte-codemirror-editor@1.1.0(codemirror@6.0.1):
|
||||||
|
resolution: {integrity: sha512-wFdMIsZds5qzn3x2NbFUxDVU6Cn3rwFdq0035ypaFVgzTjJ90bnPm6IbrFA4OJz1ngIyfbIuPAPDjm7rJIr0gg==}
|
||||||
|
peerDependencies:
|
||||||
|
codemirror: ^6.0.0
|
||||||
|
dependencies:
|
||||||
|
codemirror: 6.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/svelte-dnd-action@0.9.22(svelte@3.58.0):
|
/svelte-dnd-action@0.9.22(svelte@3.58.0):
|
||||||
resolution: {integrity: sha512-lOQJsNLM1QWv5mdxIkCVtk6k4lHCtLgfE59y8rs7iOM6erchbLC9hMEFYSveZz7biJV0mpg7yDSs4bj/RT/YkA==}
|
resolution: {integrity: sha512-lOQJsNLM1QWv5mdxIkCVtk6k4lHCtLgfE59y8rs7iOM6erchbLC9hMEFYSveZz7biJV0mpg7yDSs4bj/RT/YkA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|||||||
100000
public/extra/danbooru.csv
Normal file
100000
public/extra/danbooru.csv
Normal file
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@ import { download } from "./utils";
|
|||||||
* components they represent in the UI.
|
* components they represent in the UI.
|
||||||
*/
|
*/
|
||||||
export type ComfyBoxTemplate = {
|
export type ComfyBoxTemplate = {
|
||||||
|
version: 1,
|
||||||
nodes: LGraphNode[],
|
nodes: LGraphNode[],
|
||||||
links: LLink[],
|
links: LLink[],
|
||||||
container?: DragItemEntry
|
container?: DragItemEntry
|
||||||
@@ -20,6 +21,8 @@ export type ComfyBoxTemplate = {
|
|||||||
* components they represent in the UI.
|
* components they represent in the UI.
|
||||||
*/
|
*/
|
||||||
export type SerializedComfyBoxTemplate = {
|
export type SerializedComfyBoxTemplate = {
|
||||||
|
version: 1,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Serialized nodes
|
* Serialized nodes
|
||||||
*/
|
*/
|
||||||
@@ -270,6 +273,7 @@ export function serializeTemplate(canvas: ComfyGraphCanvas, template: ComfyBoxTe
|
|||||||
[nodes, links] = pruneDetachedLinks(nodes, links);
|
[nodes, links] = pruneDetachedLinks(nodes, links);
|
||||||
|
|
||||||
let comfyBoxTemplate: SerializedComfyBoxTemplate = {
|
let comfyBoxTemplate: SerializedComfyBoxTemplate = {
|
||||||
|
version: 1,
|
||||||
nodes: nodes,
|
nodes: nodes,
|
||||||
links: links,
|
links: links,
|
||||||
layout: layout
|
layout: layout
|
||||||
@@ -320,6 +324,7 @@ export function createTemplate(nodes: LGraphNode[]): ComfyBoxTemplateResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
version: 1,
|
||||||
nodes: nodes,
|
nodes: nodes,
|
||||||
links: links,
|
links: links,
|
||||||
container: container
|
container: container
|
||||||
@@ -328,6 +333,7 @@ export function createTemplate(nodes: LGraphNode[]): ComfyBoxTemplateResult {
|
|||||||
else {
|
else {
|
||||||
// No UI to serialize.
|
// No UI to serialize.
|
||||||
return {
|
return {
|
||||||
|
version: 1,
|
||||||
nodes: nodes,
|
nodes: nodes,
|
||||||
links: links,
|
links: links,
|
||||||
}
|
}
|
||||||
|
|||||||
198
src/lib/DanbooruTags.ts
Normal file
198
src/lib/DanbooruTags.ts
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
import { parse } from 'csv-parse/browser/esm/sync';
|
||||||
|
import { timeExecutionMs } from './utils';
|
||||||
|
import { insertCompletionText, type Completion, type CompletionContext, type CompletionResult, type CompletionSource, type CompletionConfig, autocompletion } from '@codemirror/autocomplete';
|
||||||
|
import { syntaxTree } from '@codemirror/language';
|
||||||
|
import type { Extension, TransactionSpec } from '@codemirror/state';
|
||||||
|
import type { EditorView } from '@codemirror/view';
|
||||||
|
import type { StyleSpec } from "style-mod"
|
||||||
|
|
||||||
|
export enum DanbooruTagCategory {
|
||||||
|
General = 0,
|
||||||
|
Artist = 1,
|
||||||
|
Copyright = 3,
|
||||||
|
Character = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DanbooruTagCategoryData = {
|
||||||
|
name: string,
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const TAG_CATEGORY_DATA: Record<DanbooruTagCategory, DanbooruTagCategoryData> = {
|
||||||
|
[DanbooruTagCategory.General]: {
|
||||||
|
name: "general",
|
||||||
|
color: "lightblue"
|
||||||
|
},
|
||||||
|
[DanbooruTagCategory.Artist]: {
|
||||||
|
name: "artist",
|
||||||
|
color: "red",
|
||||||
|
},
|
||||||
|
[DanbooruTagCategory.Copyright]: {
|
||||||
|
name: "copyright",
|
||||||
|
color: "lightpurple"
|
||||||
|
},
|
||||||
|
[DanbooruTagCategory.Character]: {
|
||||||
|
name: "character",
|
||||||
|
color: "green"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TAG_CATEGORY_COLORS: StyleSpec = Object.values(TAG_CATEGORY_DATA)
|
||||||
|
.flatMap(d => {
|
||||||
|
return [
|
||||||
|
[`.cm-autocompletion-${d.name}`, { color: d.color + " !important" }],
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.reduce((dict, el) => (dict[el[0]] = el[1], dict), {})
|
||||||
|
|
||||||
|
export type DanbooruTag = {
|
||||||
|
text: string,
|
||||||
|
category: DanbooruTagCategory,
|
||||||
|
count: number,
|
||||||
|
aliases: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeRegExp(s: string) {
|
||||||
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatPostCount(postCount: number): string {
|
||||||
|
if (!postCount || !isNaN(postCount))
|
||||||
|
return ""
|
||||||
|
|
||||||
|
let formatter: Intl.NumberFormat;
|
||||||
|
|
||||||
|
// Danbooru formats numbers with a padded fraction for 1M or 1k, but not for 10/100k
|
||||||
|
if (postCount >= 1000000 || (postCount >= 1000 && postCount < 10000))
|
||||||
|
formatter = Intl.NumberFormat("en", { notation: "compact", minimumFractionDigits: 1, maximumFractionDigits: 1 });
|
||||||
|
else
|
||||||
|
formatter = Intl.NumberFormat("en", { notation: "compact" });
|
||||||
|
|
||||||
|
return formatter.format(postCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class DanbooruTags {
|
||||||
|
private static _instance: DanbooruTags;
|
||||||
|
|
||||||
|
tags: DanbooruTag[] = [];
|
||||||
|
tagsByCategory: Record<string, DanbooruTag> = {}
|
||||||
|
aliases: Record<string, number> = {}
|
||||||
|
|
||||||
|
static get instance(): DanbooruTags {
|
||||||
|
if (!DanbooruTags._instance)
|
||||||
|
DanbooruTags._instance = new DanbooruTags()
|
||||||
|
return DanbooruTags._instance
|
||||||
|
}
|
||||||
|
|
||||||
|
async load(force: boolean = false) {
|
||||||
|
console.log("Parsing danbooru tags CSV...")
|
||||||
|
|
||||||
|
if (this.tags.length > 0 && !force) {
|
||||||
|
console.info("Danbooru tags already parsed")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tags = []
|
||||||
|
|
||||||
|
const transformTag = (data: string[]): DanbooruTag => {
|
||||||
|
return {
|
||||||
|
text: data[0],
|
||||||
|
category: parseInt(data[1]),
|
||||||
|
count: parseInt(data[2]),
|
||||||
|
aliases: data[3].split(",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const time = await timeExecutionMs(async () => {
|
||||||
|
const resp = await fetch("/extra/danbooru.csv");
|
||||||
|
const csv = await resp.text();
|
||||||
|
const raw: string[][] = parse(csv, {
|
||||||
|
delimiter: ','
|
||||||
|
});
|
||||||
|
|
||||||
|
const refined = raw.map(transformTag);
|
||||||
|
|
||||||
|
this.tags = refined
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(`Parsed ${this.tags.length} tags in ${time / 1000}ms.`)
|
||||||
|
console.error(this.tags[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
autocomplete(context: CompletionContext): CompletionResult {
|
||||||
|
let nodeBefore = syntaxTree(context.state).resolveInner(context.pos, -1)
|
||||||
|
let textBefore = context.state.sliceDoc(nodeBefore.from, context.pos)
|
||||||
|
|
||||||
|
let weightBefore = /:[0-9.]+$/.exec(textBefore)
|
||||||
|
if (weightBefore) return null
|
||||||
|
|
||||||
|
let tagBefore = /\b[a-zA-Z0-9_()-]+$/.exec(textBefore)
|
||||||
|
if (!tagBefore) return null
|
||||||
|
|
||||||
|
let tagword = tagBefore[0]
|
||||||
|
console.warn(tagword)
|
||||||
|
|
||||||
|
let searchRegex: RegExp;
|
||||||
|
if (tagword.startsWith("*")) {
|
||||||
|
tagword = tagword.slice(1);
|
||||||
|
searchRegex = new RegExp(`${escapeRegExp(tagword)}`, 'i');
|
||||||
|
} else {
|
||||||
|
searchRegex = new RegExp(`(^|[^a-zA-Z])${escapeRegExp(tagword)}`, 'i');
|
||||||
|
}
|
||||||
|
|
||||||
|
const sanitize = (rawTag: string): string => {
|
||||||
|
let sanitized = rawTag.replaceAll("_", " ");
|
||||||
|
|
||||||
|
// TODO config
|
||||||
|
const escapeParentheses = true;
|
||||||
|
const isTagType = true;
|
||||||
|
if (escapeParentheses && isTagType) {
|
||||||
|
sanitized = sanitized
|
||||||
|
.replaceAll("(", "\\(")
|
||||||
|
.replaceAll(")", "\\)")
|
||||||
|
.replaceAll("[", "\\[")
|
||||||
|
.replaceAll("]", "\\]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sanitized
|
||||||
|
}
|
||||||
|
|
||||||
|
const apply = (view: EditorView, completion: Completion, from: number, to: number) => {
|
||||||
|
const sanitized = sanitize(completion.label);
|
||||||
|
view.dispatch(insertCompletionText(view.state, sanitized, from, to));
|
||||||
|
}
|
||||||
|
|
||||||
|
const filter = (x: DanbooruTag) => x.text.toLowerCase().search(searchRegex) > -1;
|
||||||
|
|
||||||
|
const options: Completion[] = this.tags.filter(filter).map(t => {
|
||||||
|
const categoryName = TAG_CATEGORY_DATA[t.category]?.name || "unknown";
|
||||||
|
return {
|
||||||
|
label: t.text,
|
||||||
|
apply,
|
||||||
|
detail: formatPostCount(t.count),
|
||||||
|
type: categoryName,
|
||||||
|
section: "Tags"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
from: tagBefore ? nodeBefore.from + tagBefore.index : context.pos,
|
||||||
|
options,
|
||||||
|
validFor: /^\b([\w_()-]+)?$/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static getCompletionExt(): Extension {
|
||||||
|
const source: CompletionSource = DanbooruTags.instance.autocomplete.bind(DanbooruTags.instance)
|
||||||
|
|
||||||
|
const optionClass = (completion: Completion): string => {
|
||||||
|
return `cm-autocompletion-${completion.type}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return autocompletion({
|
||||||
|
override: [source],
|
||||||
|
interactionDelay: 250,
|
||||||
|
optionClass
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ export class ImageViewer {
|
|||||||
currentImages: string[] = []
|
currentImages: string[] = []
|
||||||
selectedIndex: number = -1;
|
selectedIndex: number = -1;
|
||||||
currentGallery: HTMLDivElement | null = null;
|
currentGallery: HTMLDivElement | null = null;
|
||||||
static _instance: ImageViewer;
|
private static _instance: ImageViewer;
|
||||||
|
|
||||||
static get instance(): ImageViewer {
|
static get instance(): ImageViewer {
|
||||||
if (!ImageViewer._instance)
|
if (!ImageViewer._instance)
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import { tick } from "svelte";
|
|||||||
import { type SvelteComponentDev } from "svelte/internal";
|
import { type SvelteComponentDev } from "svelte/internal";
|
||||||
import { get, writable, type Writable } from "svelte/store";
|
import { get, writable, type Writable } from "svelte/store";
|
||||||
import ComfyPromptSerializer, { isActiveBackendNode, UpstreamNodeLocator } from "./ComfyPromptSerializer";
|
import ComfyPromptSerializer, { isActiveBackendNode, UpstreamNodeLocator } from "./ComfyPromptSerializer";
|
||||||
|
import DanbooruTags from "$lib/DanbooruTags";
|
||||||
|
|
||||||
export const COMFYBOX_SERIAL_VERSION = 1;
|
export const COMFYBOX_SERIAL_VERSION = 1;
|
||||||
|
|
||||||
@@ -232,6 +233,8 @@ export default class ComfyApp {
|
|||||||
|
|
||||||
await this.updateHistoryAndQueue();
|
await this.updateHistoryAndQueue();
|
||||||
|
|
||||||
|
await this.initFrontendFeatures();
|
||||||
|
|
||||||
// await this.#invokeExtensionsAsync("setup");
|
// await this.#invokeExtensionsAsync("setup");
|
||||||
|
|
||||||
// Ensure the canvas fills the window
|
// Ensure the canvas fills the window
|
||||||
@@ -586,6 +589,10 @@ export default class ComfyApp {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async initFrontendFeatures() {
|
||||||
|
await DanbooruTags.instance.load();
|
||||||
|
}
|
||||||
|
|
||||||
private async updateHistoryAndQueue() {
|
private async updateHistoryAndQueue() {
|
||||||
const queue = await this.api.getQueue();
|
const queue = await this.api.getQueue();
|
||||||
const history = await this.api.getHistory();
|
const history = await this.api.getHistory();
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ import { LGraphCanvas, LiteGraph, Subgraph } from '@litegraph-ts/core';
|
|||||||
import layoutStates from './stores/layoutStates';
|
import layoutStates from './stores/layoutStates';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
import workflowState from './stores/workflowState';
|
import workflowState from './stores/workflowState';
|
||||||
|
import DanbooruTags from './DanbooruTags';
|
||||||
|
|
||||||
export function configureLitegraph(isMobile: boolean = false) {
|
function configureLitegraph(isMobile: boolean = false) {
|
||||||
LiteGraph.catch_exceptions = false;
|
LiteGraph.catch_exceptions = false;
|
||||||
|
|
||||||
// Must be enabled, otherwise subgraphs won't work (because of non-unique node/link IDs)
|
// Must be enabled, otherwise subgraphs won't work (because of non-unique node/link IDs)
|
||||||
@@ -26,10 +27,18 @@ export function configureLitegraph(isMobile: boolean = false) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Subgraph.default_lgraph_factory = () => new ComfyGraph;
|
Subgraph.default_lgraph_factory = () => new ComfyGraph;
|
||||||
|
}
|
||||||
(window as any).LiteGraph = LiteGraph;
|
|
||||||
(window as any).LGraphCanvas = LGraphCanvas;
|
function configureGlobals() {
|
||||||
(window as any).layoutStates = layoutStates;
|
const win = window as any
|
||||||
(window as any).workflowState = workflowState;
|
win.LiteGraph = LiteGraph;
|
||||||
(window as any).svelteGet = get;
|
win.LGraphCanvas = LGraphCanvas;
|
||||||
|
win.layoutStates = layoutStates;
|
||||||
|
win.workflowState = workflowState;
|
||||||
|
win.svelteGet = get;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function init(isMobile: boolean = false) {
|
||||||
|
configureLitegraph(isMobile);
|
||||||
|
configureGlobals();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -405,7 +405,7 @@ const ALL_ATTRIBUTES: AttributesSpecList = [
|
|||||||
defaultValue: ""
|
defaultValue: ""
|
||||||
},
|
},
|
||||||
|
|
||||||
// Editor
|
// Image Editor
|
||||||
{
|
{
|
||||||
name: "variant",
|
name: "variant",
|
||||||
type: "enum",
|
type: "enum",
|
||||||
@@ -430,6 +430,16 @@ const ALL_ATTRIBUTES: AttributesSpecList = [
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Text
|
// Text
|
||||||
|
{
|
||||||
|
name: "variant",
|
||||||
|
type: "enum",
|
||||||
|
location: "widget",
|
||||||
|
editable: true,
|
||||||
|
validNodeTypes: ["ui/text"],
|
||||||
|
values: ["text", "code"],
|
||||||
|
defaultValue: "text",
|
||||||
|
refreshPanelOnChange: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "multiline",
|
name: "multiline",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
|
|||||||
@@ -52,6 +52,14 @@ export function* enumerate<T>(iterable: Iterable<T>): Iterable<[number, T]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function timeExecutionMs(fn: (...any) => Promise<any>, ...args: any[]): Promise<number> {
|
||||||
|
const start = new Date().getTime();
|
||||||
|
|
||||||
|
await fn.apply(null, args)
|
||||||
|
|
||||||
|
return new Date().getTime() - start;
|
||||||
|
}
|
||||||
|
|
||||||
export function download(filename: string, text: string, type: string = "text/plain") {
|
export function download(filename: string, text: string, type: string = "text/plain") {
|
||||||
const blob = new Blob([text], { type: type });
|
const blob = new Blob([text], { type: type });
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
import type { ComfyTextNode } from "$lib/nodes/widgets";
|
import type { ComfyTextNode } from "$lib/nodes/widgets";
|
||||||
export let widget: WidgetLayout | null = null;
|
export let widget: WidgetLayout | null = null;
|
||||||
export let isMobile: boolean = false;
|
export let isMobile: boolean = false;
|
||||||
|
import TextWidgetCodeVariant from "./TextWidgetCodeVariant.svelte"
|
||||||
|
|
||||||
let node: ComfyTextNode | null = null;
|
let node: ComfyTextNode | null = null;
|
||||||
let nodeValue: Writable<string> | null = null;
|
let nodeValue: Writable<string> | null = null;
|
||||||
@@ -31,6 +32,9 @@
|
|||||||
|
|
||||||
<div class="wrapper gradio-textbox">
|
<div class="wrapper gradio-textbox">
|
||||||
{#if node !== null && nodeValue !== null}
|
{#if node !== null && nodeValue !== null}
|
||||||
|
{#if widget.attrs.variant === "code"}
|
||||||
|
<TextWidgetCodeVariant {widget} {node} {nodeValue} />
|
||||||
|
{:else}
|
||||||
<TextBox
|
<TextBox
|
||||||
bind:value={$nodeValue}
|
bind:value={$nodeValue}
|
||||||
label={widget.attrs.title}
|
label={widget.attrs.title}
|
||||||
@@ -44,6 +48,7 @@
|
|||||||
on:select
|
on:select
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
233
src/lib/widgets/TextWidgetCodeVariant.svelte
Normal file
233
src/lib/widgets/TextWidgetCodeVariant.svelte
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { ComfyTextNode } from "$lib/nodes/widgets";
|
||||||
|
import { type WidgetLayout } from "$lib/stores/layoutStates";
|
||||||
|
import { writable, type Writable } from "svelte/store";
|
||||||
|
|
||||||
|
import type { ViewUpdate } from "@codemirror/view";
|
||||||
|
import { EditorView, keymap, placeholder as placeholderExt } from "@codemirror/view";
|
||||||
|
import { StateEffect, EditorState, type Extension } from "@codemirror/state";
|
||||||
|
import { basicDark } from "cm6-theme-basic-dark";
|
||||||
|
import { basicLight } from "cm6-theme-basic-light";
|
||||||
|
|
||||||
|
import { basicSetup } from "./TextWidgetCodeVariant";
|
||||||
|
import { createEventDispatcher, onMount } from "svelte";
|
||||||
|
import { TAG_CATEGORY_COLORS } from "$lib/DanbooruTags";
|
||||||
|
|
||||||
|
export let widget: WidgetLayout;
|
||||||
|
export let node: ComfyTextNode;
|
||||||
|
export let nodeValue: Writable<string> = writable("");
|
||||||
|
export let extraExtensions: Extension[] = [];
|
||||||
|
let lines = 5;
|
||||||
|
let classNames = ""
|
||||||
|
|
||||||
|
let element: HTMLDivElement;
|
||||||
|
let view: EditorView;
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher<{ change: string }>();
|
||||||
|
|
||||||
|
$: lines = node?.properties?.lines || 5;
|
||||||
|
|
||||||
|
let BaseTheme: Extension = EditorView.theme({
|
||||||
|
"&": {
|
||||||
|
width: "100%",
|
||||||
|
maxWidth: "100%",
|
||||||
|
height: "12rem",
|
||||||
|
fontSize: "var(--text-sm)",
|
||||||
|
backgroundColor: "var(--input-background-fill)"
|
||||||
|
},
|
||||||
|
".cm-content": {
|
||||||
|
paddingTop: "5px",
|
||||||
|
paddingBottom: "5px",
|
||||||
|
color: "var(--body-text-color)",
|
||||||
|
fontFamily: "var(--font-mono)",
|
||||||
|
minHeight: "100%"
|
||||||
|
},
|
||||||
|
".cm-gutters": {
|
||||||
|
marginRight: "1px",
|
||||||
|
borderRight: "1px solid var(--border-color-primary)",
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
color: "var(--body-text-color-subdued)"
|
||||||
|
},
|
||||||
|
".cm-focused": {
|
||||||
|
outline: "none"
|
||||||
|
},
|
||||||
|
".cm-scroller": {
|
||||||
|
height: "auto"
|
||||||
|
},
|
||||||
|
".cm-cursor": {
|
||||||
|
borderLeftColor: "var(--body-text-color)"
|
||||||
|
},
|
||||||
|
".cm-selectionBackground": {
|
||||||
|
backgroundColor: "var(--secondary-600) !important",
|
||||||
|
},
|
||||||
|
".cm-tooltip": {
|
||||||
|
backgroundColor: "var(--panel-background-fill) !important",
|
||||||
|
border: "1px solid var(--panel-border-color) !important",
|
||||||
|
},
|
||||||
|
".cm-tooltip-autocomplete": {
|
||||||
|
color: "var(--body-text-color) !important",
|
||||||
|
},
|
||||||
|
".cm-tooltip-autocomplete > ul > li[aria-selected]": {
|
||||||
|
color: "unset"
|
||||||
|
},
|
||||||
|
...TAG_CATEGORY_COLORS
|
||||||
|
})
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
view = createEditorView();
|
||||||
|
return () => view?.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
$: reconfigure()
|
||||||
|
$: setDoc($nodeValue);
|
||||||
|
$: updateLines(lines);
|
||||||
|
|
||||||
|
function reconfigure(): void {
|
||||||
|
view?.dispatch({
|
||||||
|
effects: StateEffect.reconfigure.of(getExtensions())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDoc(newDoc: string) {
|
||||||
|
if (view && newDoc !== view.state.doc.toString()) {
|
||||||
|
view.dispatch({
|
||||||
|
changes: {
|
||||||
|
from: 0,
|
||||||
|
to: view.state.doc.length,
|
||||||
|
insert: newDoc
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateLines(newLines: number) {
|
||||||
|
if (view) {
|
||||||
|
view.requestMeasure({ read: updateGutters });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGutterLineHeight(view: EditorView): string | null {
|
||||||
|
let elements = view.dom.querySelectorAll<HTMLElement>(".cm-gutterElement");
|
||||||
|
if (elements.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < elements.length; i++) {
|
||||||
|
let node = elements[i];
|
||||||
|
let height = getComputedStyle(node)?.height ?? "0px";
|
||||||
|
if (height != "0px") {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateGutters(view: EditorView): any {
|
||||||
|
let gutters = view.dom.querySelectorAll<HTMLElement>(".cm-gutter");
|
||||||
|
let _lines = lines + 1;
|
||||||
|
let lineHeight = getGutterLineHeight(view);
|
||||||
|
if (!lineHeight) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// for (var i = 0; i < gutters.length; i++) {
|
||||||
|
// let node = gutters[i];
|
||||||
|
// node.style.minHeight = `calc(${lineHeight} * ${_lines})`;
|
||||||
|
// }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleChange(vu: ViewUpdate): void {
|
||||||
|
if (vu.docChanged) {
|
||||||
|
const doc = vu.state.doc;
|
||||||
|
const text = doc.toString();
|
||||||
|
$nodeValue = text;
|
||||||
|
dispatch("change", text);
|
||||||
|
}
|
||||||
|
view.requestMeasure({ read: updateGutters });
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBaseExtensions(readonly: boolean, placeholder: string | null): Extension[] {
|
||||||
|
const extensions: Extension[] = [
|
||||||
|
EditorView.editable.of(!readonly),
|
||||||
|
EditorState.readOnly.of(readonly)
|
||||||
|
];
|
||||||
|
|
||||||
|
extensions.push(basicSetup);
|
||||||
|
|
||||||
|
if (placeholder) {
|
||||||
|
extensions.push(placeholderExt(placeholder));
|
||||||
|
}
|
||||||
|
|
||||||
|
extensions.push(EditorView.updateListener.of(handleChange));
|
||||||
|
|
||||||
|
return extensions
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTheme(dark_mode: boolean): Extension[] {
|
||||||
|
const extensions: Extension[] = [];
|
||||||
|
|
||||||
|
if (dark_mode) {
|
||||||
|
extensions.push(basicDark);
|
||||||
|
} else {
|
||||||
|
extensions.push(basicLight);
|
||||||
|
}
|
||||||
|
return extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getExtensions(): Extension[] {
|
||||||
|
// TODO
|
||||||
|
const readonly = false;
|
||||||
|
const placeholder = "Placeholder..."
|
||||||
|
const dark_mode = true;
|
||||||
|
|
||||||
|
const stateExtensions: Extension[] = [
|
||||||
|
...getBaseExtensions(
|
||||||
|
readonly,
|
||||||
|
placeholder,
|
||||||
|
),
|
||||||
|
BaseTheme,
|
||||||
|
...getTheme(dark_mode),
|
||||||
|
...extraExtensions
|
||||||
|
];
|
||||||
|
return stateExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createEditorState(value: string | null | undefined): EditorState {
|
||||||
|
return EditorState.create({
|
||||||
|
doc: value ?? undefined,
|
||||||
|
extensions: getExtensions()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createEditorView(): EditorView {
|
||||||
|
return new EditorView({
|
||||||
|
parent: element,
|
||||||
|
state: createEditorState($nodeValue)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="wrap">
|
||||||
|
<div class="codemirror-wrapper {classNames}" bind:this={element} />
|
||||||
|
</div>
|
||||||
|
<!-- <CodeMirror bind:value={$nodeValue} {styles} /> -->
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-flow: column;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
border: 1px solid var(--input-border-color);
|
||||||
|
|
||||||
|
.codemirror-wrapper {
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.cm-scroller) {
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
55
src/lib/widgets/TextWidgetCodeVariant.ts
Normal file
55
src/lib/widgets/TextWidgetCodeVariant.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import type { Extension } from "@codemirror/state";
|
||||||
|
import {
|
||||||
|
lineNumbers,
|
||||||
|
highlightSpecialChars,
|
||||||
|
drawSelection,
|
||||||
|
rectangularSelection,
|
||||||
|
crosshairCursor,
|
||||||
|
keymap
|
||||||
|
} from "@codemirror/view";
|
||||||
|
import { EditorView } from "@codemirror/view";
|
||||||
|
import { EditorState } from "@codemirror/state";
|
||||||
|
import {
|
||||||
|
foldGutter,
|
||||||
|
indentOnInput,
|
||||||
|
syntaxHighlighting,
|
||||||
|
defaultHighlightStyle,
|
||||||
|
foldKeymap
|
||||||
|
} from "@codemirror/language";
|
||||||
|
import { history, defaultKeymap, historyKeymap } from "@codemirror/commands";
|
||||||
|
import {
|
||||||
|
closeBrackets,
|
||||||
|
closeBracketsKeymap,
|
||||||
|
completionKeymap
|
||||||
|
} from "@codemirror/autocomplete";
|
||||||
|
import { lintKeymap } from "@codemirror/lint";
|
||||||
|
import {
|
||||||
|
type CompletionSource, autocompletion, CompletionContext, startCompletion,
|
||||||
|
currentCompletions, completionStatus, completeFromList, acceptCompletion
|
||||||
|
} from "@codemirror/autocomplete"
|
||||||
|
import DanbooruTags from "$lib/DanbooruTags";
|
||||||
|
|
||||||
|
export const basicSetup: Extension = /*@__PURE__*/ (() => [
|
||||||
|
lineNumbers(),
|
||||||
|
highlightSpecialChars(),
|
||||||
|
history(),
|
||||||
|
foldGutter(),
|
||||||
|
drawSelection(),
|
||||||
|
EditorState.allowMultipleSelections.of(true),
|
||||||
|
indentOnInput(),
|
||||||
|
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
||||||
|
closeBrackets(),
|
||||||
|
rectangularSelection(),
|
||||||
|
crosshairCursor(),
|
||||||
|
EditorView.lineWrapping,
|
||||||
|
DanbooruTags.getCompletionExt(),
|
||||||
|
|
||||||
|
keymap.of([
|
||||||
|
...closeBracketsKeymap,
|
||||||
|
...defaultKeymap,
|
||||||
|
...historyKeymap,
|
||||||
|
...foldKeymap,
|
||||||
|
...completionKeymap,
|
||||||
|
...lintKeymap
|
||||||
|
])
|
||||||
|
])();
|
||||||
@@ -2,10 +2,10 @@
|
|||||||
import "$lib/nodeImports";
|
import "$lib/nodeImports";
|
||||||
|
|
||||||
import ComfyApp from '$lib/components/ComfyApp';
|
import ComfyApp from '$lib/components/ComfyApp';
|
||||||
import { configureLitegraph } from '$lib/init';
|
import init from '$lib/init';
|
||||||
import App from './App.svelte';
|
import App from './App.svelte';
|
||||||
|
|
||||||
configureLitegraph()
|
await init();
|
||||||
|
|
||||||
const comfyApp = new ComfyApp();
|
const comfyApp = new ComfyApp();
|
||||||
(window as any).app = comfyApp;
|
(window as any).app = comfyApp;
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ import ComfyApp from '$lib/components/ComfyApp';
|
|||||||
import uiState from '$lib/stores/uiState';
|
import uiState from '$lib/stores/uiState';
|
||||||
import { LiteGraph } from '@litegraph-ts/core';
|
import { LiteGraph } from '@litegraph-ts/core';
|
||||||
import ComfyGraph from '$lib/ComfyGraph';
|
import ComfyGraph from '$lib/ComfyGraph';
|
||||||
import { configureLitegraph } from '$lib/init';
|
import init from '$lib/init';
|
||||||
|
|
||||||
Framework7.use(Framework7Svelte);
|
Framework7.use(Framework7Svelte);
|
||||||
|
|
||||||
configureLitegraph(true);
|
await init(true);
|
||||||
|
|
||||||
const comfyApp = new ComfyApp();
|
const comfyApp = new ComfyApp();
|
||||||
(window as any).app = comfyApp;
|
(window as any).app = comfyApp;
|
||||||
|
|||||||
Reference in New Issue
Block a user