This commit is contained in:
Classic298 2025-06-21 15:56:11 +00:00 committed by GitHub
commit 51fb136845
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 80 additions and 34 deletions

View File

@ -754,6 +754,7 @@
bind:this={chatInputElement}
bind:value={prompt}
id="chat-input"
preserveBreaks={true}
messageInput={true}
shiftEnter={!($settings?.ctrlEnterToSend ?? false) &&
(!$mobile ||

View File

@ -22,9 +22,18 @@
let selectedPromptIdx = 0;
let filteredPrompts = [];
$: filteredPrompts = $prompts
.filter((p) => p.command.toLowerCase().includes(command.toLowerCase()))
.sort((a, b) => a.title.localeCompare(b.title));
$: {
if (command && command.length > 0) {
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) {
selectedPromptIdx = 0;
@ -120,23 +129,42 @@
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) {
lastLineWords.push(
`${text.replace(/</g, '&lt;').replace(/>/g, '&gt;').replaceAll('\n', '<br/>')}`
);
const allPromptLines = prompt.split('\n');
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 {
lastLineWords.push(text);
lines.push(lastLineWords.join(' '));
prompt = lines.join('\n');
const currentInputLines = prompt.split('\n');
const lastCurrentInputLine = currentInputLines.pop() || '';
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');

View File

@ -163,25 +163,34 @@
}
if (!raw) {
async function tryParse(value, attempts = 3, interval = 100) {
async function tryParse(value, attempts = 3, interval = 100, useMarkdownBreaks = false) {
try {
// Normalize all types of newlines to \n
const normalizedTextValue = (value || '').replace(/\r\n|\r/g, '\n');
// Try parsing the value
return marked.parse(value.replaceAll(`\n<br/>`, `<br/>`), {
breaks: false
return marked.parse(normalizedTextValue, {
breaks: useMarkdownBreaks,
gfm: true // Ensure GFM is active for paragraph handling
});
} catch (error) {
// If no attempts remain, fallback to plain text
if (attempts <= 1) {
return value;
return (value || '').replace(/\r\n|\r/g, '\n');
}
// Wait for the interval, then retry
await new Promise((resolve) => setTimeout(resolve, interval));
return tryParse(value, attempts - 1, interval); // Recursive call
return tryParse(value, attempts - 1, interval, useMarkdownBreaks);
}
}
// 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 &nbsp;
// so they are visually represented and can be saved back correctly.
content = content.replace(/<p>(?:&nbsp;|<br\s*\/?>)?<\/p>/gi, '<p>&#8203;</p>');
}
}
} else {
if (html && !content) {
@ -244,9 +253,7 @@
if (!raw) {
let newValue = turndownService
.turndown(
editor
.getHTML()
.replace(/<p><\/p>/g, '<br/>')
html
.replace(/ {2,}/g, (m) => m.replace(/ /g, '\u00a0'))
)
.replace(/\u00a0/g, ' ');
@ -438,14 +445,23 @@
)
.replace(/\u00a0/g, ' ')
) {
preserveBreaks
? editor.commands.setContent(value)
: editor.commands.setContent(
marked.parse(value.replaceAll(`\n<br/>`, `<br/>`), {
breaks: false
})
); // Update editor content
if (preserveBreaks) {
const normalizedValue = (value || '').replace(/\r\n|\r/g, '\n');
// Parse Markdown with breaks:true to convert \n to <br> for Tiptap
let htmlToSet = marked.parse(normalizedValue, { breaks: true, gfm: true });
if (htmlToSet) {
// htmlToSet = htmlToSet.replace(/<p><\/p>/g, '<p>&nbsp;</p>'); // Old way
htmlToSet = htmlToSet.replace(/<p>(?:&nbsp;|<br\s*\/?>)?<\/p>/gi, '<p>&#8203;</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();
}
}

View File

@ -156,6 +156,7 @@
bind:value={content}
rows={6}
required
preserveBreaks={true}
/>
</div>