mirror of
https://github.com/open-webui/open-webui
synced 2025-06-22 18:07:17 +00:00
Merge b4025a1ffc
into aef0ad2d10
This commit is contained in:
commit
51fb136845
@ -754,6 +754,7 @@
|
|||||||
bind:this={chatInputElement}
|
bind:this={chatInputElement}
|
||||||
bind:value={prompt}
|
bind:value={prompt}
|
||||||
id="chat-input"
|
id="chat-input"
|
||||||
|
preserveBreaks={true}
|
||||||
messageInput={true}
|
messageInput={true}
|
||||||
shiftEnter={!($settings?.ctrlEnterToSend ?? false) &&
|
shiftEnter={!($settings?.ctrlEnterToSend ?? false) &&
|
||||||
(!$mobile ||
|
(!$mobile ||
|
||||||
|
@ -22,9 +22,18 @@
|
|||||||
let selectedPromptIdx = 0;
|
let selectedPromptIdx = 0;
|
||||||
let filteredPrompts = [];
|
let filteredPrompts = [];
|
||||||
|
|
||||||
$: filteredPrompts = $prompts
|
$: {
|
||||||
.filter((p) => p.command.toLowerCase().includes(command.toLowerCase()))
|
if (command && command.length > 0) {
|
||||||
.sort((a, b) => a.title.localeCompare(b.title));
|
const commandName = command.substring(1).toLowerCase();
|
||||||
|
const cleanedCommandName = commandName.replace(/<\/?p>/gi, '').trim();
|
||||||
|
|
||||||
|
filteredPrompts = $prompts
|
||||||
|
.filter((p) => p.command.toLowerCase().includes(cleanedCommandName))
|
||||||
|
.sort((a, b) => a.title.localeCompare(b.title));
|
||||||
|
} else {
|
||||||
|
filteredPrompts = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$: if (command) {
|
$: if (command) {
|
||||||
selectedPromptIdx = 0;
|
selectedPromptIdx = 0;
|
||||||
@ -120,23 +129,42 @@
|
|||||||
text = text.replaceAll('{{CURRENT_WEEKDAY}}', weekday);
|
text = text.replaceAll('{{CURRENT_WEEKDAY}}', weekday);
|
||||||
}
|
}
|
||||||
|
|
||||||
const lines = prompt.split('\n');
|
|
||||||
const lastLine = lines.pop();
|
|
||||||
|
|
||||||
const lastLineWords = lastLine.split(' ');
|
|
||||||
const lastWord = lastLineWords.pop();
|
|
||||||
|
|
||||||
if ($settings?.richTextInput ?? true) {
|
if ($settings?.richTextInput ?? true) {
|
||||||
lastLineWords.push(
|
const allPromptLines = prompt.split('\n');
|
||||||
`${text.replace(/</g, '<').replace(/>/g, '>').replaceAll('\n', '<br/>')}`
|
const lastLineWithTrigger = allPromptLines.pop() || ''; // Line where command was typed
|
||||||
);
|
const wordsInLastLine = lastLineWithTrigger.split(' ');
|
||||||
|
wordsInLastLine.pop(); // Remove the command trigger itself (e.g., /mycommand)
|
||||||
|
|
||||||
|
let fullPromptPrefix = '';
|
||||||
|
if (allPromptLines.length > 0) {
|
||||||
|
fullPromptPrefix = allPromptLines.join('\n');
|
||||||
|
}
|
||||||
|
if (wordsInLastLine.length > 0) {
|
||||||
|
if (fullPromptPrefix.length > 0) {
|
||||||
|
fullPromptPrefix += '\n';
|
||||||
|
}
|
||||||
|
fullPromptPrefix += wordsInLastLine.join(' ');
|
||||||
|
}
|
||||||
|
fullPromptPrefix = fullPromptPrefix.trimEnd();
|
||||||
|
|
||||||
|
if (text && text.trim().length > 0) { // If 'text' (the command's content) is not empty
|
||||||
|
if (fullPromptPrefix.length > 0) {
|
||||||
|
prompt = fullPromptPrefix + '\n\n' + text;
|
||||||
|
} else {
|
||||||
|
prompt = text;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
prompt = fullPromptPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
lines.push(lastLineWords.join(' '));
|
|
||||||
prompt = lines.join('<br/>');
|
|
||||||
} else {
|
} else {
|
||||||
lastLineWords.push(text);
|
const currentInputLines = prompt.split('\n');
|
||||||
lines.push(lastLineWords.join(' '));
|
const lastCurrentInputLine = currentInputLines.pop() || '';
|
||||||
prompt = lines.join('\n');
|
const lastCurrentInputLineWords = lastCurrentInputLine.split(' ');
|
||||||
|
lastCurrentInputLineWords.pop();
|
||||||
|
lastCurrentInputLineWords.push(command.content);
|
||||||
|
currentInputLines.push(lastCurrentInputLineWords.join(' '));
|
||||||
|
prompt = currentInputLines.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
const chatInputContainerElement = document.getElementById('chat-input-container');
|
const chatInputContainerElement = document.getElementById('chat-input-container');
|
||||||
|
@ -163,25 +163,34 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!raw) {
|
if (!raw) {
|
||||||
async function tryParse(value, attempts = 3, interval = 100) {
|
async function tryParse(value, attempts = 3, interval = 100, useMarkdownBreaks = false) {
|
||||||
try {
|
try {
|
||||||
|
// Normalize all types of newlines to \n
|
||||||
|
const normalizedTextValue = (value || '').replace(/\r\n|\r/g, '\n');
|
||||||
// Try parsing the value
|
// Try parsing the value
|
||||||
return marked.parse(value.replaceAll(`\n<br/>`, `<br/>`), {
|
return marked.parse(normalizedTextValue, {
|
||||||
breaks: false
|
breaks: useMarkdownBreaks,
|
||||||
|
gfm: true // Ensure GFM is active for paragraph handling
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// If no attempts remain, fallback to plain text
|
// If no attempts remain, fallback to plain text
|
||||||
if (attempts <= 1) {
|
if (attempts <= 1) {
|
||||||
return value;
|
return (value || '').replace(/\r\n|\r/g, '\n');
|
||||||
}
|
}
|
||||||
// Wait for the interval, then retry
|
// Wait for the interval, then retry
|
||||||
await new Promise((resolve) => setTimeout(resolve, interval));
|
await new Promise((resolve) => setTimeout(resolve, interval));
|
||||||
return tryParse(value, attempts - 1, interval); // Recursive call
|
return tryParse(value, attempts - 1, interval, useMarkdownBreaks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Usage example
|
// Usage example
|
||||||
content = await tryParse(value);
|
content = await tryParse(value, 3, 100, preserveBreaks);
|
||||||
|
|
||||||
|
if (preserveBreaks && content) {
|
||||||
|
// Ensure truly empty paragraphs generated by marked get an
|
||||||
|
// so they are visually represented and can be saved back correctly.
|
||||||
|
content = content.replace(/<p>(?: |<br\s*\/?>)?<\/p>/gi, '<p>​</p>');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (html && !content) {
|
if (html && !content) {
|
||||||
@ -244,9 +253,7 @@
|
|||||||
if (!raw) {
|
if (!raw) {
|
||||||
let newValue = turndownService
|
let newValue = turndownService
|
||||||
.turndown(
|
.turndown(
|
||||||
editor
|
html
|
||||||
.getHTML()
|
|
||||||
.replace(/<p><\/p>/g, '<br/>')
|
|
||||||
.replace(/ {2,}/g, (m) => m.replace(/ /g, '\u00a0'))
|
.replace(/ {2,}/g, (m) => m.replace(/ /g, '\u00a0'))
|
||||||
)
|
)
|
||||||
.replace(/\u00a0/g, ' ');
|
.replace(/\u00a0/g, ' ');
|
||||||
@ -438,14 +445,23 @@
|
|||||||
)
|
)
|
||||||
.replace(/\u00a0/g, ' ')
|
.replace(/\u00a0/g, ' ')
|
||||||
) {
|
) {
|
||||||
preserveBreaks
|
if (preserveBreaks) {
|
||||||
? editor.commands.setContent(value)
|
const normalizedValue = (value || '').replace(/\r\n|\r/g, '\n');
|
||||||
: editor.commands.setContent(
|
// Parse Markdown with breaks:true to convert \n to <br> for Tiptap
|
||||||
marked.parse(value.replaceAll(`\n<br/>`, `<br/>`), {
|
let htmlToSet = marked.parse(normalizedValue, { breaks: true, gfm: true });
|
||||||
breaks: false
|
if (htmlToSet) {
|
||||||
})
|
// htmlToSet = htmlToSet.replace(/<p><\/p>/g, '<p> </p>'); // Old way
|
||||||
); // Update editor content
|
htmlToSet = htmlToSet.replace(/<p>(?: |<br\s*\/?>)?<\/p>/gi, '<p>​</p>');
|
||||||
|
}
|
||||||
|
editor.commands.setContent(
|
||||||
|
marked.parse(normalizedValue, { breaks: true, gfm: true })
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const normalizedValue = (value || '').replace(/\r\n|\r/g, '\n');
|
||||||
|
editor.commands.setContent(
|
||||||
|
marked.parse(normalizedValue, { breaks: false, gfm: true })
|
||||||
|
);
|
||||||
|
}
|
||||||
selectTemplate();
|
selectTemplate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,6 +156,7 @@
|
|||||||
bind:value={content}
|
bind:value={content}
|
||||||
rows={6}
|
rows={6}
|
||||||
required
|
required
|
||||||
|
preserveBreaks={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user