Getting the new new new rich text editor working. I think it is working... Yay Shad Editor that uses TipTap and Shadcn.

This commit is contained in:
Scott Idem
2024-12-02 18:56:45 -05:00
parent 940a7e9a21
commit 44907bc01f
42 changed files with 2095 additions and 572 deletions

View File

@@ -121,112 +121,112 @@ export let new_html: string = '';
onMount(() => {
editor = new Editor({
element: element,
extensions: [
// StarterKit,
Bold, // part of StarterKit
Code, // part of StarterKit
CodeBlock, // part of StarterKit
Italic, // part of StarterKit
Strike, // part of StarterKit
Underline, // part of StarterKit
BulletList, // part of StarterKit
// Color.configure({ types: [TextStyle.name, ListItem.name] }),
// TextStyle.configure({ types: [ListItem.name] }),
// Heading.configure({ levels: [1, 2, 3, 4, 5, 6] }),
Highlight,
History.configure({
depth: 100,
newGroupDelay: 500
}),
Link.configure({
openOnClick: false,
autolink: true,
defaultProtocol: 'https',
protocols: ['http', 'https'],
isAllowedUri: (url, ctx) => {
try {
// construct URL
const parsedUrl = url.includes(':') ? new URL(url) : new URL(`${ctx.defaultProtocol}://${url}`)
// element: element,
// extensions: [
// // StarterKit,
// Bold, // part of StarterKit
// Code, // part of StarterKit
// CodeBlock, // part of StarterKit
// Italic, // part of StarterKit
// Strike, // part of StarterKit
// Underline, // part of StarterKit
// BulletList, // part of StarterKit
// // Color.configure({ types: [TextStyle.name, ListItem.name] }),
// // TextStyle.configure({ types: [ListItem.name] }),
// // Heading.configure({ levels: [1, 2, 3, 4, 5, 6] }),
// Highlight,
// History.configure({
// depth: 100,
// newGroupDelay: 500
// }),
// Link.configure({
// openOnClick: false,
// autolink: true,
// defaultProtocol: 'https',
// protocols: ['http', 'https'],
// isAllowedUri: (url, ctx) => {
// try {
// // construct URL
// const parsedUrl = url.includes(':') ? new URL(url) : new URL(`${ctx.defaultProtocol}://${url}`)
// use default validation
if (!ctx.defaultValidate(parsedUrl.href)) {
return false
}
// // use default validation
// if (!ctx.defaultValidate(parsedUrl.href)) {
// return false
// }
// disallowed protocols
const disallowedProtocols = ['ftp', 'file', 'mailto']
const protocol = parsedUrl.protocol.replace(':', '')
// // disallowed protocols
// const disallowedProtocols = ['ftp', 'file', 'mailto']
// const protocol = parsedUrl.protocol.replace(':', '')
if (disallowedProtocols.includes(protocol)) {
return false
}
// if (disallowedProtocols.includes(protocol)) {
// return false
// }
// only allow protocols specified in ctx.protocols
const allowedProtocols = ctx.protocols.map(p => (typeof p === 'string' ? p : p.scheme))
// // only allow protocols specified in ctx.protocols
// const allowedProtocols = ctx.protocols.map(p => (typeof p === 'string' ? p : p.scheme))
if (!allowedProtocols.includes(protocol)) {
return false
}
// if (!allowedProtocols.includes(protocol)) {
// return false
// }
// disallowed domains
const disallowedDomains = ['example-phishing.com', 'malicious-site.net']
const domain = parsedUrl.hostname
// // disallowed domains
// const disallowedDomains = ['example-phishing.com', 'malicious-site.net']
// const domain = parsedUrl.hostname
if (disallowedDomains.includes(domain)) {
return false
}
// if (disallowedDomains.includes(domain)) {
// return false
// }
// all checks have passed
return true
} catch (error) {
return false
}
},
shouldAutoLink: url => {
try {
// construct URL
const parsedUrl = url.includes(':') ? new URL(url) : new URL(`https://${url}`)
// // all checks have passed
// return true
// } catch (error) {
// return false
// }
// },
// shouldAutoLink: url => {
// try {
// // construct URL
// const parsedUrl = url.includes(':') ? new URL(url) : new URL(`https://${url}`)
// only auto-link if the domain is not in the disallowed list
const disallowedDomains = ['example-no-autolink.com', 'another-no-autolink.com']
const domain = parsedUrl.hostname
// // only auto-link if the domain is not in the disallowed list
// const disallowedDomains = ['example-no-autolink.com', 'another-no-autolink.com']
// const domain = parsedUrl.hostname
return !disallowedDomains.includes(domain)
} catch (error) {
return false
}
},
}),
ListItem,
Document,
OrderedList, // part of StarterKit
Paragraph,
Text,
Typography,
],
content: html_text,
onTransaction: ({ editor, transaction }) => {
// console.log('onTransaction');
// force re-render so `editor.isActive` works as expected
// editor = editor;
// return !disallowedDomains.includes(domain)
// } catch (error) {
// return false
// }
// },
// }),
// ListItem,
// Document,
// OrderedList, // part of StarterKit
// Paragraph,
// Text,
// Typography,
// ],
// content: html_text,
// onTransaction: ({ editor, transaction }) => {
// // console.log('onTransaction');
// // force re-render so `editor.isActive` works as expected
// // editor = editor;
// let updated_html = editor.getHTML();
// if (updated_html == '<p></p>') {
// new_html = '';
// } else {
// new_html = updated_html;
// }
},
onUpdate: ({ editor }) => {
console.log('onUpdate', editor.getHTML());
let updated_html = editor.getHTML();
if (updated_html == '<p></p>') {
new_html = '';
} else {
new_html = updated_html;
}
}
// // let updated_html = editor.getHTML();
// // if (updated_html == '<p></p>') {
// // new_html = '';
// // } else {
// // new_html = updated_html;
// // }
// },
// onUpdate: ({ editor }) => {
// // console.log('onUpdate', editor.getHTML());
// // let updated_html = editor.getHTML();
// // if (updated_html == '<p></p>') {
// // new_html = '';
// // } else {
// // new_html = updated_html;
// // }
// }
});
});
@@ -248,9 +248,11 @@ let mouse_enter_wait: number = 500;
let mouse_leave_wait: number = 2000;
</script>
<!-- svelte-ignore a11y-no-static-element-interactions -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- class:py-1={show_menu} -->
{#if 1==3}
<div
on:click={() => {
if (default_minimal) {
@@ -285,6 +287,7 @@ let mouse_leave_wait: number = 2000;
// }
}}
class="editor textarea p-1 transition-all duration-1000"
class:hidden={true}
>
<!-- && show_menu -->
@@ -619,8 +622,16 @@ let mouse_leave_wait: number = 2000;
>{placeholder}</span>
</div>
</div>
{/if}
<main class="my-10 flex w-full flex-col items-center justify-center">
<ShadEditor
class="editor textarea p-1 transition-all duration-1000"
bind:content={html_text}
bind:new_html={new_html}
/>
</main>
<style lang="scss">
// :global(.ProseMirror) {