mirror of
https://github.com/open-webui/open-webui
synced 2025-03-03 10:52:09 +00:00
enh: rich text input
This commit is contained in:
parent
e30c5e628c
commit
aca06f92e8
58
package-lock.json
generated
58
package-lock.json
generated
@ -17,6 +17,7 @@
|
||||
"@pyscript/core": "^0.4.32",
|
||||
"@sveltejs/adapter-node": "^2.0.0",
|
||||
"@tiptap/core": "^2.10.0",
|
||||
"@tiptap/extension-code-block-lowlight": "^2.10.0",
|
||||
"@tiptap/extension-highlight": "^2.10.0",
|
||||
"@tiptap/extension-placeholder": "^2.10.0",
|
||||
"@tiptap/extension-typography": "^2.10.0",
|
||||
@ -2425,6 +2426,23 @@
|
||||
"@tiptap/pm": "^2.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tiptap/extension-code-block-lowlight": {
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.10.0.tgz",
|
||||
"integrity": "sha512-dAv03XIHT5h+sdFmJzvx2FfpfFOOK9SBKHflRUdqTa8eA+0VZNAcPRjvJWVEWqts1fKZDJj774mO28NlhFzk9Q==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ueberdosis"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tiptap/core": "^2.7.0",
|
||||
"@tiptap/extension-code-block": "^2.7.0",
|
||||
"@tiptap/pm": "^2.7.0",
|
||||
"highlight.js": "^11",
|
||||
"lowlight": "^2 || ^3"
|
||||
}
|
||||
},
|
||||
"node_modules/@tiptap/extension-document": {
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.10.0.tgz",
|
||||
@ -2793,6 +2811,16 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
|
||||
},
|
||||
"node_modules/@types/hast": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
|
||||
"integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/unist": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
@ -5162,6 +5190,20 @@
|
||||
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz",
|
||||
"integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw=="
|
||||
},
|
||||
"node_modules/devlop": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
|
||||
"integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"dequal": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/didyoumean": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
|
||||
@ -7390,6 +7432,22 @@
|
||||
"get-func-name": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/lowlight": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lowlight/-/lowlight-3.1.0.tgz",
|
||||
"integrity": "sha512-CEbNVoSikAxwDMDPjXlqlFYiZLkDJHwyGu/MfOsJnF3d7f3tds5J3z8s/l9TMXhzfsJCCJEAsD78842mwmg0PQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/hast": "^3.0.0",
|
||||
"devlop": "^1.0.0",
|
||||
"highlight.js": "~11.9.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.11",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz",
|
||||
|
@ -58,6 +58,7 @@
|
||||
"@pyscript/core": "^0.4.32",
|
||||
"@sveltejs/adapter-node": "^2.0.0",
|
||||
"@tiptap/core": "^2.10.0",
|
||||
"@tiptap/extension-code-block-lowlight": "^2.10.0",
|
||||
"@tiptap/extension-highlight": "^2.10.0",
|
||||
"@tiptap/extension-placeholder": "^2.10.0",
|
||||
"@tiptap/extension-typography": "^2.10.0",
|
||||
|
52
src/app.css
52
src/app.css
@ -230,3 +230,55 @@ input[type='number'] {
|
||||
|
||||
@apply dark:bg-gray-800 bg-gray-100;
|
||||
}
|
||||
|
||||
/* Code styling */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #616161;
|
||||
}
|
||||
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #f98181;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #fbbc88;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #b9f18d;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #faf594;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #70cff8;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
@ -11,13 +11,19 @@
|
||||
|
||||
import { Editor } from '@tiptap/core';
|
||||
|
||||
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight';
|
||||
import Placeholder from '@tiptap/extension-placeholder';
|
||||
import Highlight from '@tiptap/extension-highlight';
|
||||
import Typography from '@tiptap/extension-typography';
|
||||
import StarterKit from '@tiptap/starter-kit';
|
||||
|
||||
import { all, createLowlight } from 'lowlight';
|
||||
|
||||
import { PASTED_TEXT_CHARACTER_LIMIT } from '$lib/constants';
|
||||
|
||||
// create a lowlight instance with all languages loaded
|
||||
const lowlight = createLowlight(all);
|
||||
|
||||
export let className = 'input-prose';
|
||||
export let placeholder = 'Type here...';
|
||||
export let value = '';
|
||||
@ -109,7 +115,15 @@
|
||||
onMount(() => {
|
||||
editor = new Editor({
|
||||
element: element,
|
||||
extensions: [StarterKit, Highlight, Typography, Placeholder.configure({ placeholder })],
|
||||
extensions: [
|
||||
StarterKit,
|
||||
CodeBlockLowlight.configure({
|
||||
lowlight
|
||||
}),
|
||||
Highlight,
|
||||
Typography,
|
||||
Placeholder.configure({ placeholder })
|
||||
],
|
||||
content: marked.parse(value),
|
||||
autofocus: true,
|
||||
onTransaction: () => {
|
||||
@ -144,10 +158,22 @@
|
||||
}
|
||||
|
||||
if (messageInput) {
|
||||
if (event.key === 'Enter') {
|
||||
// Check if the current selection is inside a code block
|
||||
const { state } = view;
|
||||
const { $head } = state.selection;
|
||||
const isInCodeBlock = $head.parent.type.name === 'codeBlock';
|
||||
|
||||
if (isInCodeBlock) {
|
||||
return false; // Prevent Enter action inside a code block
|
||||
}
|
||||
}
|
||||
|
||||
// Handle shift + Enter for a line break
|
||||
if (shiftEnter) {
|
||||
if (event.key === 'Enter' && event.shiftKey) {
|
||||
editor.commands.setHardBreak(); // Insert a hard break
|
||||
view.dispatch(view.state.tr.scrollIntoView()); // Move viewport to the cursor
|
||||
event.preventDefault();
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user