mirror of
https://git.mirrors.martin98.com/https://github.com/open-webui/open-webui
synced 2025-08-13 14:09:00 +08:00
feat: rich text input
This commit is contained in:
parent
988a5e2b8d
commit
670441f548
236
package-lock.json
generated
236
package-lock.json
generated
@ -35,6 +35,16 @@
|
|||||||
"mermaid": "^10.9.1",
|
"mermaid": "^10.9.1",
|
||||||
"paneforge": "^0.0.6",
|
"paneforge": "^0.0.6",
|
||||||
"panzoom": "^9.4.3",
|
"panzoom": "^9.4.3",
|
||||||
|
"prosemirror-commands": "^1.6.0",
|
||||||
|
"prosemirror-example-setup": "^1.2.3",
|
||||||
|
"prosemirror-history": "^1.4.1",
|
||||||
|
"prosemirror-keymap": "^1.2.2",
|
||||||
|
"prosemirror-markdown": "^1.13.1",
|
||||||
|
"prosemirror-model": "^1.23.0",
|
||||||
|
"prosemirror-schema-basic": "^1.2.3",
|
||||||
|
"prosemirror-schema-list": "^1.4.1",
|
||||||
|
"prosemirror-state": "^1.4.3",
|
||||||
|
"prosemirror-view": "^1.34.3",
|
||||||
"pyodide": "^0.26.1",
|
"pyodide": "^0.26.1",
|
||||||
"socket.io-client": "^4.2.0",
|
"socket.io-client": "^4.2.0",
|
||||||
"sortablejs": "^1.15.2",
|
"sortablejs": "^1.15.2",
|
||||||
@ -1963,6 +1973,20 @@
|
|||||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/linkify-it": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q=="
|
||||||
|
},
|
||||||
|
"node_modules/@types/markdown-it": {
|
||||||
|
"version": "14.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz",
|
||||||
|
"integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/linkify-it": "^5",
|
||||||
|
"@types/mdurl": "^2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/mdast": {
|
"node_modules/@types/mdast": {
|
||||||
"version": "3.0.15",
|
"version": "3.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz",
|
||||||
@ -1971,6 +1995,11 @@
|
|||||||
"@types/unist": "^2"
|
"@types/unist": "^2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/mdurl": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="
|
||||||
|
},
|
||||||
"node_modules/@types/minimatch": {
|
"node_modules/@types/minimatch": {
|
||||||
"version": "3.0.5",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
|
||||||
@ -2552,8 +2581,7 @@
|
|||||||
"node_modules/argparse": {
|
"node_modules/argparse": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/aria-query": {
|
"node_modules/aria-query": {
|
||||||
"version": "5.3.0",
|
"version": "5.3.0",
|
||||||
@ -4460,7 +4488,6 @@
|
|||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.12"
|
"node": ">=0.12"
|
||||||
},
|
},
|
||||||
@ -6233,6 +6260,14 @@
|
|||||||
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/linkify-it": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"uc.micro": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/listr2": {
|
"node_modules/listr2": {
|
||||||
"version": "3.14.0",
|
"version": "3.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz",
|
||||||
@ -6470,6 +6505,22 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.5.0"
|
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/markdown-it": {
|
||||||
|
"version": "14.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
|
||||||
|
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
|
||||||
|
"dependencies": {
|
||||||
|
"argparse": "^2.0.1",
|
||||||
|
"entities": "^4.4.0",
|
||||||
|
"linkify-it": "^5.0.0",
|
||||||
|
"mdurl": "^2.0.0",
|
||||||
|
"punycode.js": "^2.3.1",
|
||||||
|
"uc.micro": "^2.1.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"markdown-it": "bin/markdown-it.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/marked": {
|
"node_modules/marked": {
|
||||||
"version": "9.1.6",
|
"version": "9.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz",
|
||||||
@ -6556,6 +6607,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||||
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
|
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/mdurl": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="
|
||||||
|
},
|
||||||
"node_modules/merge-stream": {
|
"node_modules/merge-stream": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||||
@ -7332,6 +7388,11 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/orderedmap": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g=="
|
||||||
|
},
|
||||||
"node_modules/ospath": {
|
"node_modules/ospath": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz",
|
||||||
@ -7941,6 +8002,157 @@
|
|||||||
"node": "10.* || >= 12.*"
|
"node": "10.* || >= 12.*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prosemirror-commands": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-xn1U/g36OqXn2tn5nGmvnnimAj/g1pUx2ypJJIe8WkVX83WyJVC5LTARaxZa2AtQRwntu9Jc5zXs9gL9svp/mg==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.0.0",
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"prosemirror-transform": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-dropcursor": {
|
||||||
|
"version": "1.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.1.tgz",
|
||||||
|
"integrity": "sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"prosemirror-transform": "^1.1.0",
|
||||||
|
"prosemirror-view": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-example-setup": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-example-setup/-/prosemirror-example-setup-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-+hXZi8+xbFvYM465zZH3rdZ9w7EguVKmUYwYLZjIJIjPK+I0nPTwn8j0ByW2avchVczRwZmOJGNvehblyIerSQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-commands": "^1.0.0",
|
||||||
|
"prosemirror-dropcursor": "^1.0.0",
|
||||||
|
"prosemirror-gapcursor": "^1.0.0",
|
||||||
|
"prosemirror-history": "^1.0.0",
|
||||||
|
"prosemirror-inputrules": "^1.0.0",
|
||||||
|
"prosemirror-keymap": "^1.0.0",
|
||||||
|
"prosemirror-menu": "^1.0.0",
|
||||||
|
"prosemirror-schema-list": "^1.0.0",
|
||||||
|
"prosemirror-state": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-gapcursor": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-keymap": "^1.0.0",
|
||||||
|
"prosemirror-model": "^1.0.0",
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"prosemirror-view": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-history": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-state": "^1.2.2",
|
||||||
|
"prosemirror-transform": "^1.0.0",
|
||||||
|
"prosemirror-view": "^1.31.0",
|
||||||
|
"rope-sequence": "^1.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-inputrules": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-6ygpPRuTJ2lcOXs9JkefieMst63wVJBgHZGl5QOytN7oSZs3Co/BYbc3Yx9zm9H37Bxw8kVzCnDsihsVsL4yEg==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"prosemirror-transform": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-keymap": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"w3c-keyname": "^2.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-markdown": {
|
||||||
|
"version": "1.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.1.tgz",
|
||||||
|
"integrity": "sha512-Sl+oMfMtAjWtlcZoj/5L/Q39MpEnVZ840Xo330WJWUvgyhNmLBLN7MsHn07s53nG/KImevWHSE6fEj4q/GihHw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/markdown-it": "^14.0.0",
|
||||||
|
"markdown-it": "^14.0.0",
|
||||||
|
"prosemirror-model": "^1.20.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-menu": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==",
|
||||||
|
"dependencies": {
|
||||||
|
"crelt": "^1.0.0",
|
||||||
|
"prosemirror-commands": "^1.0.0",
|
||||||
|
"prosemirror-history": "^1.0.0",
|
||||||
|
"prosemirror-state": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-model": {
|
||||||
|
"version": "1.23.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.23.0.tgz",
|
||||||
|
"integrity": "sha512-Q/fgsgl/dlOAW9ILu4OOhYWQbc7TQd4BwKH/RwmUjyVf8682Be4zj3rOYdLnYEcGzyg8LL9Q5IWYKD8tdToreQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"orderedmap": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-schema-basic": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-h+H0OQwZVqMon1PNn0AG9cTfx513zgIG2DY00eJ00Yvgb3UD+GQ/VlWW5rcaxacpCGT1Yx8nuhwXk4+QbXUfJA==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.19.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-schema-list": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-jbDyaP/6AFfDfu70VzySsD75Om2t3sXTOdl5+31Wlxlg62td1haUpty/ybajSfJ1pkGadlOfwQq9kgW5IMo1Rg==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.0.0",
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"prosemirror-transform": "^1.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-state": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz",
|
||||||
|
"integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.0.0",
|
||||||
|
"prosemirror-transform": "^1.0.0",
|
||||||
|
"prosemirror-view": "^1.27.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-transform": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-9UOgFSgN6Gj2ekQH5CTDJ8Rp/fnKR2IkYfGdzzp5zQMFsS4zDllLVx/+jGcX86YlACpG7UR5fwAXiWzxqWtBTg==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.21.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-view": {
|
||||||
|
"version": "1.34.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.34.3.tgz",
|
||||||
|
"integrity": "sha512-mKZ54PrX19sSaQye+sef+YjBbNu2voNwLS1ivb6aD2IRmxRGW64HU9B644+7OfJStGLyxvOreKqEgfvXa91WIA==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.20.0",
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"prosemirror-transform": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/proxy-from-env": {
|
"node_modules/proxy-from-env": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
|
||||||
@ -7977,6 +8189,14 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/punycode.js": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pyodide": {
|
"node_modules/pyodide": {
|
||||||
"version": "0.26.1",
|
"version": "0.26.1",
|
||||||
"resolved": "https://registry.npmjs.org/pyodide/-/pyodide-0.26.1.tgz",
|
"resolved": "https://registry.npmjs.org/pyodide/-/pyodide-0.26.1.tgz",
|
||||||
@ -8345,6 +8565,11 @@
|
|||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rope-sequence": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ=="
|
||||||
|
},
|
||||||
"node_modules/rsvp": {
|
"node_modules/rsvp": {
|
||||||
"version": "4.8.5",
|
"version": "4.8.5",
|
||||||
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
|
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
|
||||||
@ -9562,6 +9787,11 @@
|
|||||||
"node": ">=14.17"
|
"node": ">=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/uc.micro": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="
|
||||||
|
},
|
||||||
"node_modules/ufo": {
|
"node_modules/ufo": {
|
||||||
"version": "1.5.3",
|
"version": "1.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz",
|
||||||
|
10
package.json
10
package.json
@ -75,6 +75,16 @@
|
|||||||
"mermaid": "^10.9.1",
|
"mermaid": "^10.9.1",
|
||||||
"paneforge": "^0.0.6",
|
"paneforge": "^0.0.6",
|
||||||
"panzoom": "^9.4.3",
|
"panzoom": "^9.4.3",
|
||||||
|
"prosemirror-commands": "^1.6.0",
|
||||||
|
"prosemirror-example-setup": "^1.2.3",
|
||||||
|
"prosemirror-history": "^1.4.1",
|
||||||
|
"prosemirror-keymap": "^1.2.2",
|
||||||
|
"prosemirror-markdown": "^1.13.1",
|
||||||
|
"prosemirror-model": "^1.23.0",
|
||||||
|
"prosemirror-schema-basic": "^1.2.3",
|
||||||
|
"prosemirror-schema-list": "^1.4.1",
|
||||||
|
"prosemirror-state": "^1.4.3",
|
||||||
|
"prosemirror-view": "^1.34.3",
|
||||||
"pyodide": "^0.26.1",
|
"pyodide": "^0.26.1",
|
||||||
"socket.io-client": "^4.2.0",
|
"socket.io-client": "^4.2.0",
|
||||||
"sortablejs": "^1.15.2",
|
"sortablejs": "^1.15.2",
|
||||||
|
26
src/app.css
26
src/app.css
@ -34,6 +34,14 @@ math {
|
|||||||
@apply rounded-lg;
|
@apply rounded-lg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input-prose {
|
||||||
|
@apply prose dark:prose-invert prose-p:my-0 prose-img:my-1 prose-headings:my-1 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-ul:-my-0 prose-ol:-my-0 prose-li:-my-0 whitespace-pre-line;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-prose-sm {
|
||||||
|
@apply prose dark:prose-invert prose-p:my-0 prose-img:my-1 prose-headings:my-1 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-ul:-my-0 prose-ol:-my-0 prose-li:-my-0 whitespace-pre-line text-sm;
|
||||||
|
}
|
||||||
|
|
||||||
.markdown-prose {
|
.markdown-prose {
|
||||||
@apply prose dark:prose-invert prose-p:my-0 prose-img:my-1 prose-headings:my-1 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-ul:-my-0 prose-ol:-my-0 prose-li:-my-0 whitespace-pre-line;
|
@apply prose dark:prose-invert prose-p:my-0 prose-img:my-1 prose-headings:my-1 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-ul:-my-0 prose-ol:-my-0 prose-li:-my-0 whitespace-pre-line;
|
||||||
}
|
}
|
||||||
@ -179,3 +187,21 @@ input[type='number'] {
|
|||||||
.bg-gray-950-90 {
|
.bg-gray-950-90 {
|
||||||
background-color: rgba(var(--color-gray-950, #0d0d0d), 0.9);
|
background-color: rgba(var(--color-gray-950, #0d0d0d), 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ProseMirror {
|
||||||
|
@apply h-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder::after {
|
||||||
|
content: attr(data-placeholder);
|
||||||
|
cursor: text;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
float: left;
|
||||||
|
|
||||||
|
@apply absolute inset-0 z-0 text-gray-700 dark:text-gray-500;
|
||||||
|
}
|
||||||
|
211
src/lib/components/common/RichTextInput.svelte
Normal file
211
src/lib/components/common/RichTextInput.svelte
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { onDestroy, onMount } from 'svelte';
|
||||||
|
|
||||||
|
import { EditorState, Plugin } from 'prosemirror-state';
|
||||||
|
import { EditorView, Decoration, DecorationSet } from 'prosemirror-view';
|
||||||
|
import { undo, redo, history } from 'prosemirror-history';
|
||||||
|
import { schema, defaultMarkdownParser, defaultMarkdownSerializer } from 'prosemirror-markdown';
|
||||||
|
|
||||||
|
import {
|
||||||
|
inputRules,
|
||||||
|
wrappingInputRule,
|
||||||
|
textblockTypeInputRule,
|
||||||
|
InputRule
|
||||||
|
} from 'prosemirror-inputrules'; // Import input rules
|
||||||
|
import { splitListItem, liftListItem, sinkListItem } from 'prosemirror-schema-list'; // Import from prosemirror-schema-list
|
||||||
|
|
||||||
|
import { keymap } from 'prosemirror-keymap';
|
||||||
|
import { baseKeymap, chainCommands } from 'prosemirror-commands';
|
||||||
|
import { DOMParser, DOMSerializer, Schema } from 'prosemirror-model';
|
||||||
|
|
||||||
|
import { marked } from 'marked'; // Import marked for markdown parsing
|
||||||
|
|
||||||
|
export let className = 'input-prose';
|
||||||
|
|
||||||
|
export let value = '';
|
||||||
|
export let placeholder = 'Type here...';
|
||||||
|
|
||||||
|
let element: HTMLElement; // Element where ProseMirror will attach
|
||||||
|
let state;
|
||||||
|
let view;
|
||||||
|
|
||||||
|
// Plugin to add placeholder when the content is empty
|
||||||
|
function placeholderPlugin(placeholder: string) {
|
||||||
|
return new Plugin({
|
||||||
|
props: {
|
||||||
|
decorations(state) {
|
||||||
|
const doc = state.doc;
|
||||||
|
if (
|
||||||
|
doc.childCount === 1 &&
|
||||||
|
doc.firstChild.isTextblock &&
|
||||||
|
doc.firstChild?.textContent === ''
|
||||||
|
) {
|
||||||
|
// If there's nothing in the editor, show the placeholder decoration
|
||||||
|
const decoration = Decoration.node(0, doc.content.size, {
|
||||||
|
'data-placeholder': placeholder,
|
||||||
|
class: 'placeholder'
|
||||||
|
});
|
||||||
|
return DecorationSet.create(doc, [decoration]);
|
||||||
|
}
|
||||||
|
return DecorationSet.empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to convert markdown content to ProseMirror-compatible document
|
||||||
|
function markdownToProseMirrorDoc(markdown: string) {
|
||||||
|
return defaultMarkdownParser.parse(value || '');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility function to convert ProseMirror content back to markdown text
|
||||||
|
function serializeEditorContent(doc) {
|
||||||
|
return defaultMarkdownSerializer.serialize(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Input Rules ----
|
||||||
|
// Input rule for heading (e.g., # Headings)
|
||||||
|
function headingRule(schema) {
|
||||||
|
return textblockTypeInputRule(/^(#{1,6})\s$/, schema.nodes.heading, (match) => ({
|
||||||
|
level: match[1].length
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input rule for bullet list (e.g., `- item`)
|
||||||
|
function bulletListRule(schema) {
|
||||||
|
return wrappingInputRule(/^\s*([-+*])\s$/, schema.nodes.bullet_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input rule for ordered list (e.g., `1. item`)
|
||||||
|
function orderedListRule(schema) {
|
||||||
|
return wrappingInputRule(/^(\d+)\.\s$/, schema.nodes.ordered_list, (match) => ({
|
||||||
|
order: +match[1]
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom input rules for Bold/Italic (using * or _)
|
||||||
|
function markInputRule(regexp: RegExp, markType: any) {
|
||||||
|
return new InputRule(regexp, (state, match, start, end) => {
|
||||||
|
const { tr } = state;
|
||||||
|
if (match) {
|
||||||
|
tr.replaceWith(start, end, schema.text(match[1], [markType.create()]));
|
||||||
|
}
|
||||||
|
return tr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function boldRule(schema) {
|
||||||
|
return markInputRule(/\*([^*]+)\*/, schema.marks.strong);
|
||||||
|
}
|
||||||
|
|
||||||
|
function italicRule(schema) {
|
||||||
|
return markInputRule(/\_([^*]+)\_/, schema.marks.em);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize Editor State and View
|
||||||
|
|
||||||
|
function isInList(state) {
|
||||||
|
const { $from } = state.selection;
|
||||||
|
return (
|
||||||
|
$from.parent.type === schema.nodes.paragraph && $from.node(-1).type === schema.nodes.list_item
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isEmptyListItem(state) {
|
||||||
|
const { $from } = state.selection;
|
||||||
|
return isInList(state) && $from.parent.content.size === 0 && $from.node(-1).childCount === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function exitList(state, dispatch) {
|
||||||
|
return liftListItem(schema.nodes.list_item)(state, dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const initialDoc = markdownToProseMirrorDoc(value || ''); // Convert the initial content
|
||||||
|
// const initialDoc =
|
||||||
|
|
||||||
|
state = EditorState.create({
|
||||||
|
doc: initialDoc,
|
||||||
|
schema,
|
||||||
|
plugins: [
|
||||||
|
history(),
|
||||||
|
placeholderPlugin(placeholder),
|
||||||
|
inputRules({
|
||||||
|
rules: [
|
||||||
|
headingRule(schema), // Handle markdown-style headings (# H1, ## H2, etc.)
|
||||||
|
bulletListRule(schema), // Handle `-` or `*` input to start bullet list
|
||||||
|
orderedListRule(schema), // Handle `1.` input to start ordered list
|
||||||
|
boldRule(schema), // Bold input rule
|
||||||
|
italicRule(schema) // Italic input rule
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
keymap({
|
||||||
|
...baseKeymap,
|
||||||
|
'Mod-z': undo,
|
||||||
|
'Mod-y': redo,
|
||||||
|
Enter: chainCommands(
|
||||||
|
(state, dispatch, view) => {
|
||||||
|
if (isEmptyListItem(state)) {
|
||||||
|
return exitList(state, dispatch);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
(state, dispatch, view) => {
|
||||||
|
if (isInList(state)) {
|
||||||
|
return splitListItem(schema.nodes.list_item)(state, dispatch);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
baseKeymap.Enter
|
||||||
|
),
|
||||||
|
// Prevent default tab navigation and provide indent/outdent behavior inside lists:
|
||||||
|
Tab: (state, dispatch, view) => {
|
||||||
|
const { $from } = state.selection;
|
||||||
|
console.log('Tab key pressed', $from.parent, $from.parent.type);
|
||||||
|
if (isInList(state)) {
|
||||||
|
return sinkListItem(schema.nodes.list_item)(state, dispatch);
|
||||||
|
}
|
||||||
|
return true; // Prevent Tab from moving the focus
|
||||||
|
},
|
||||||
|
'Shift-Tab': (state, dispatch, view) => {
|
||||||
|
const { $from } = state.selection;
|
||||||
|
console.log('Shift-Tab key pressed', $from.parent, $from.parent.type);
|
||||||
|
if (isInList(state)) {
|
||||||
|
return liftListItem(schema.nodes.list_item)(state, dispatch);
|
||||||
|
}
|
||||||
|
return true; // Prevent Shift-Tab from moving the focus
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
view = new EditorView(element, {
|
||||||
|
state,
|
||||||
|
dispatchTransaction(transaction) {
|
||||||
|
// Update editor state
|
||||||
|
let newState = view.state.apply(transaction);
|
||||||
|
view.updateState(newState);
|
||||||
|
|
||||||
|
value = serializeEditorContent(newState.doc); // Convert ProseMirror content to markdown text
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reinitialize the editor if the value is externally changed (i.e. when `value` is updated)
|
||||||
|
$: if (view && value !== serializeEditorContent(view.state.doc)) {
|
||||||
|
const newDoc = markdownToProseMirrorDoc(value || '');
|
||||||
|
const newState = EditorState.create({
|
||||||
|
doc: newDoc,
|
||||||
|
schema,
|
||||||
|
plugins: view.state.plugins
|
||||||
|
});
|
||||||
|
view.updateState(newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy ProseMirror instance on unmount
|
||||||
|
onDestroy(() => {
|
||||||
|
view?.destroy();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div bind:this={element} class="relative w-full h-full {className}"></div>
|
@ -21,20 +21,19 @@
|
|||||||
updateKnowledgeById
|
updateKnowledgeById
|
||||||
} from '$lib/apis/knowledge';
|
} from '$lib/apis/knowledge';
|
||||||
|
|
||||||
import Spinner from '$lib/components/common/Spinner.svelte';
|
|
||||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
|
||||||
import Badge from '$lib/components/common/Badge.svelte';
|
|
||||||
import Files from './Collection/Files.svelte';
|
|
||||||
import AddFilesPlaceholder from '$lib/components/AddFilesPlaceholder.svelte';
|
|
||||||
import AddContentModal from './Collection/AddTextContentModal.svelte';
|
|
||||||
import { transcribeAudio } from '$lib/apis/audio';
|
import { transcribeAudio } from '$lib/apis/audio';
|
||||||
import { blobToFile } from '$lib/utils';
|
import { blobToFile } from '$lib/utils';
|
||||||
import { processFile } from '$lib/apis/retrieval';
|
import { processFile } from '$lib/apis/retrieval';
|
||||||
|
|
||||||
|
import Spinner from '$lib/components/common/Spinner.svelte';
|
||||||
|
import Files from './Collection/Files.svelte';
|
||||||
|
import AddFilesPlaceholder from '$lib/components/AddFilesPlaceholder.svelte';
|
||||||
|
|
||||||
import AddContentMenu from './Collection/AddContentMenu.svelte';
|
import AddContentMenu from './Collection/AddContentMenu.svelte';
|
||||||
import AddTextContentModal from './Collection/AddTextContentModal.svelte';
|
import AddTextContentModal from './Collection/AddTextContentModal.svelte';
|
||||||
|
|
||||||
import SyncConfirmDialog from '../../common/ConfirmDialog.svelte';
|
import SyncConfirmDialog from '../../common/ConfirmDialog.svelte';
|
||||||
|
import RichTextInput from '$lib/components/common/RichTextInput.svelte';
|
||||||
let largeScreen = true;
|
let largeScreen = true;
|
||||||
|
|
||||||
type Knowledge = {
|
type Knowledge = {
|
||||||
@ -552,157 +551,159 @@
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="flex flex-col w-full max-h-[100dvh] h-full">
|
<div class="flex flex-col w-full h-full max-h-[100dvh]">
|
||||||
<div class="flex flex-col mb-2 flex-1 overflow-auto h-0">
|
{#if id && knowledge}
|
||||||
{#if id && knowledge}
|
<div class="flex flex-row flex-1 h-full max-h-full pb-2.5">
|
||||||
<div class="flex flex-row h-0 flex-1 overflow-auto">
|
<div
|
||||||
<div
|
class=" {largeScreen
|
||||||
class=" {largeScreen
|
? 'flex-shrink-0'
|
||||||
? 'flex-shrink-0'
|
: 'flex-1'} flex py-2.5 w-80 rounded-2xl border border-gray-50 dark:border-gray-850"
|
||||||
: 'flex-1'} flex py-2.5 w-80 rounded-2xl border border-gray-50 dark:border-gray-850"
|
>
|
||||||
>
|
<div class=" flex flex-col w-full space-x-2 rounded-lg h-full">
|
||||||
<div class=" flex flex-col w-full space-x-2 rounded-lg h-full">
|
<div class="w-full h-full flex flex-col">
|
||||||
<div class="w-full h-full flex flex-col">
|
<div class=" px-3">
|
||||||
<div class=" px-3">
|
<div class="flex">
|
||||||
<div class="flex">
|
<div class=" self-center ml-1 mr-3">
|
||||||
<div class=" self-center ml-1 mr-3">
|
<svg
|
||||||
<svg
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
viewBox="0 0 20 20"
|
||||||
viewBox="0 0 20 20"
|
fill="currentColor"
|
||||||
fill="currentColor"
|
class="w-4 h-4"
|
||||||
class="w-4 h-4"
|
>
|
||||||
>
|
<path
|
||||||
<path
|
fill-rule="evenodd"
|
||||||
fill-rule="evenodd"
|
d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z"
|
||||||
d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z"
|
clip-rule="evenodd"
|
||||||
clip-rule="evenodd"
|
/>
|
||||||
/>
|
</svg>
|
||||||
</svg>
|
</div>
|
||||||
</div>
|
<input
|
||||||
<input
|
class=" w-full text-sm pr-4 py-1 rounded-r-xl outline-none bg-transparent"
|
||||||
class=" w-full text-sm pr-4 py-1 rounded-r-xl outline-none bg-transparent"
|
bind:value={query}
|
||||||
bind:value={query}
|
placeholder={$i18n.t('Search Collection')}
|
||||||
placeholder={$i18n.t('Search Collection')}
|
on:focus={() => {
|
||||||
on:focus={() => {
|
selectedFileId = null;
|
||||||
selectedFileId = null;
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<AddContentMenu
|
||||||
|
on:upload={(e) => {
|
||||||
|
if (e.detail.type === 'directory') {
|
||||||
|
uploadDirectoryHandler();
|
||||||
|
} else if (e.detail.type === 'text') {
|
||||||
|
showAddTextContentModal = true;
|
||||||
|
} else {
|
||||||
|
document.getElementById('files-input').click();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
on:sync={(e) => {
|
||||||
|
showSyncConfirmModal = true;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div>
|
|
||||||
<AddContentMenu
|
|
||||||
on:upload={(e) => {
|
|
||||||
if (e.detail.type === 'directory') {
|
|
||||||
uploadDirectoryHandler();
|
|
||||||
} else if (e.detail.type === 'text') {
|
|
||||||
showAddTextContentModal = true;
|
|
||||||
} else {
|
|
||||||
document.getElementById('files-input').click();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
on:sync={(e) => {
|
|
||||||
showSyncConfirmModal = true;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class=" mt-2 mb-1 border-gray-50 dark:border-gray-850" />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if filteredItems.length > 0}
|
<hr class=" mt-2 mb-1 border-gray-50 dark:border-gray-850" />
|
||||||
<div class=" flex overflow-y-auto h-full w-full scrollbar-hidden text-xs">
|
|
||||||
<Files
|
|
||||||
files={filteredItems}
|
|
||||||
{selectedFileId}
|
|
||||||
on:click={(e) => {
|
|
||||||
selectedFileId = selectedFileId === e.detail ? null : e.detail;
|
|
||||||
}}
|
|
||||||
on:delete={(e) => {
|
|
||||||
console.log(e.detail);
|
|
||||||
|
|
||||||
selectedFileId = null;
|
|
||||||
deleteFileHandler(e.detail);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<div class="m-auto text-gray-500 text-xs">{$i18n.t('No content found')}</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{#if filteredItems.length > 0}
|
||||||
|
<div class=" flex overflow-y-auto h-full w-full scrollbar-hidden text-xs">
|
||||||
|
<Files
|
||||||
|
files={filteredItems}
|
||||||
|
{selectedFileId}
|
||||||
|
on:click={(e) => {
|
||||||
|
selectedFileId = selectedFileId === e.detail ? null : e.detail;
|
||||||
|
}}
|
||||||
|
on:delete={(e) => {
|
||||||
|
console.log(e.detail);
|
||||||
|
|
||||||
|
selectedFileId = null;
|
||||||
|
deleteFileHandler(e.detail);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="m-auto text-gray-500 text-xs">{$i18n.t('No content found')}</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{#if largeScreen}
|
{#if largeScreen}
|
||||||
<div class="flex-1 flex justify-start max-h-full overflow-hidden pl-3">
|
<div class="flex-1 flex justify-start h-full max-h-full pl-3">
|
||||||
{#if selectedFile}
|
{#if selectedFile}
|
||||||
<div class=" flex flex-col w-full h-full">
|
<div class=" flex flex-col w-full h-full max-h-full">
|
||||||
<div class=" flex-shrink-0 mb-2 flex items-center">
|
<div class="flex-shrink-0 mb-2 flex items-center">
|
||||||
<div class=" flex-1 text-xl line-clamp-1">
|
<div class=" flex-1 text-xl line-clamp-1">
|
||||||
{selectedFile?.meta?.name}
|
{selectedFile?.meta?.name}
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
class="self-center w-fit text-sm py-1 px-2.5 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-lg"
|
|
||||||
on:click={() => {
|
|
||||||
updateFileContentHandler();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{$i18n.t('Save')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class=" flex-grow">
|
<div>
|
||||||
<textarea
|
<button
|
||||||
class=" w-full h-full resize-none rounded-xl py-4 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-none"
|
class="self-center w-fit text-sm py-1 px-2.5 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-lg"
|
||||||
|
on:click={() => {
|
||||||
|
updateFileContentHandler();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{$i18n.t('Save')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class=" flex-1 w-full h-full max-h-full py-2.5 px-3.5 rounded-xl text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-none overflow-y-auto scrollbar-hidden"
|
||||||
|
>
|
||||||
|
{#key selectedFile.id}
|
||||||
|
<RichTextInput
|
||||||
|
className="input-prose-sm"
|
||||||
bind:value={selectedFile.data.content}
|
bind:value={selectedFile.data.content}
|
||||||
placeholder={$i18n.t('Add content here')}
|
placeholder={$i18n.t('Add content here')}
|
||||||
/>
|
/>
|
||||||
</div>
|
{/key}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
</div>
|
||||||
<div class="m-auto pb-32">
|
{:else}
|
||||||
<div>
|
<div class="m-auto pb-32">
|
||||||
<div class=" flex w-full mt-1 mb-3.5">
|
<div>
|
||||||
<div class="flex-1">
|
<div class=" flex w-full mt-1 mb-3.5">
|
||||||
<div class="flex items-center justify-between w-full px-0.5 mb-1">
|
<div class="flex-1">
|
||||||
<div class="w-full">
|
<div class="flex items-center justify-between w-full px-0.5 mb-1">
|
||||||
<input
|
<div class="w-full">
|
||||||
type="text"
|
|
||||||
class="text-center w-full font-medium text-3xl font-primary bg-transparent outline-none"
|
|
||||||
bind:value={knowledge.name}
|
|
||||||
on:input={() => {
|
|
||||||
changeDebounceHandler();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex w-full px-1">
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class="text-center w-full text-gray-500 bg-transparent outline-none"
|
class="text-center w-full font-medium text-3xl font-primary bg-transparent outline-none"
|
||||||
bind:value={knowledge.description}
|
bind:value={knowledge.name}
|
||||||
on:input={() => {
|
on:input={() => {
|
||||||
changeDebounceHandler();
|
changeDebounceHandler();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex w-full px-1">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="text-center w-full text-gray-500 bg-transparent outline-none"
|
||||||
|
bind:value={knowledge.description}
|
||||||
|
on:input={() => {
|
||||||
|
changeDebounceHandler();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class=" mt-2 text-center text-sm text-gray-200 dark:text-gray-700 w-full">
|
|
||||||
{$i18n.t('Select a file to view or drag and drop a file to upload')}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
</div>
|
<div class=" mt-2 text-center text-sm text-gray-200 dark:text-gray-700 w-full">
|
||||||
{/if}
|
{$i18n.t('Select a file to view or drag and drop a file to upload')}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
</div>
|
||||||
<Spinner />
|
{/if}
|
||||||
{/if}
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<Spinner />
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user