enh: rich text input preserve breaks

This commit is contained in:
Timothy Jaeryang Baek 2024-11-30 15:05:08 -08:00
parent d3778b0bda
commit acb61d3c42
3 changed files with 35 additions and 13 deletions

View File

@ -35,6 +35,7 @@
export let value = ''; export let value = '';
export let id = ''; export let id = '';
export let preserveBreaks = false;
export let generateAutoCompletion: Function = async () => null; export let generateAutoCompletion: Function = async () => null;
export let autocomplete = false; export let autocomplete = false;
export let messageInput = false; export let messageInput = false;
@ -126,10 +127,22 @@
onMount(async () => { onMount(async () => {
console.log(value); console.log(value);
if (preserveBreaks) {
turndownService.addRule('preserveBreaks', {
filter: 'br', // Target <br> elements
replacement: function (content) {
return '<br/>';
}
});
}
async function tryParse(value, attempts = 3, interval = 100) { async function tryParse(value, attempts = 3, interval = 100) {
try { try {
// Try parsing the value // Try parsing the value
return marked.parse(value); return marked.parse(value.replaceAll(`\n<br/>`, `<br/>`), {
breaks: false
});
} 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) {
@ -178,8 +191,10 @@
onTransaction: () => { onTransaction: () => {
// force re-render so `editor.isActive` works as expected // force re-render so `editor.isActive` works as expected
editor = editor; editor = editor;
const newValue = turndownService.turndown(
preserveBreaks ? editor.getHTML().replace(/<p><\/p>/g, '<br/>') : editor.getHTML()
);
const newValue = turndownService.turndown(editor.getHTML());
if (value !== newValue) { if (value !== newValue) {
value = newValue; value = newValue;
@ -312,18 +327,20 @@
}); });
// Update the editor content if the external `value` changes // Update the editor content if the external `value` changes
$: if (editor && value !== turndownService.turndown(editor.getHTML())) { $: if (
editor.commands.setContent(marked.parse(value)); // Update editor content editor &&
value !==
turndownService.turndown(
preserveBreaks ? editor.getHTML().replace(/<p><\/p>/g, '<br/>') : editor.getHTML()
)
) {
editor.commands.setContent(
marked.parse(value.replaceAll(`\n<br/>`, `<br/>`), {
breaks: false
})
); // Update editor content
selectTemplate(); selectTemplate();
} }
</script> </script>
<div bind:this={element} class="relative w-full min-w-full h-full min-h-fit {className}" /> <div bind:this={element} class="relative w-full min-w-full h-full min-h-fit {className}" />
<style>
.ai-autocompletion::after {
content: attr(data-suggestion);
color: var(--gray-5);
pointer-events: none;
}
</style>

View File

@ -817,6 +817,7 @@
className="input-prose-sm" 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')}
preserveBreaks={true}
/> />
{/key} {/key}
</div> </div>

View File

@ -67,7 +67,11 @@
</div> </div>
<div class=" flex-1 w-full h-full"> <div class=" flex-1 w-full h-full">
<RichTextInput bind:value={content} placeholder={$i18n.t('Write something...')} /> <RichTextInput
bind:value={content}
placeholder={$i18n.t('Write something...')}
preserveBreaks={true}
/>
</div> </div>
</div> </div>
</div> </div>