Skip to content

Instantly share code, notes, and snippets.

@fubits1
Last active July 17, 2024 10:11
Show Gist options
  • Select an option

  • Save fubits1/f2e27c6fa8f5c2850689d8585a68c5e0 to your computer and use it in GitHub Desktop.

Select an option

Save fubits1/f2e27c6fa8f5c2850689d8585a68c5e0 to your computer and use it in GitHub Desktop.
Svelte 5 and tiptap editor default example (REPL backup just in case)
<script>
/** my REPL link:
* https://svelte-5-preview.vercel.app/#H4sIAAAAAAAACr1Z624buRV-lbNKYckLSaOLx2vLsra2YzdpN22xTtEfqwChZiiJMDWcJTl2FEFA3qAo0D_91X99sDxBH6GHnLsuGwuyLUiaGfJc-H08h-SQi8qYcaoqvV8WlYDMaKVXuQjDSr2i56F5UPeUa4rPSkTSMyV95UkW6sEwGGrneyA-CTX1YSzFDKZah6rnOBOmp9Go6YmZE9ERlb5QTDka1UjoaEmpMyMscHw6E8pR0nOuP5FZiO1wXtMxibh2bq1f-N4ZBgBsFgqpYQFXggsJy9hZ9feJQfpJ00AxETQ8U18tqPzElH6r6WyrBkeBBkOJotZ7rL_Vc063qmm8bSgjUtS71URqKv_EdKw4rKSaKq5p3DE9rJyVMF37TOegchVPSLoqK4J3Igp0Lhx3jxUzgpxqoJzOKMqcw-_Qq6a1w7OsKnZVqjF1idla7RDOB7AwRZALB_QhaWQtqYLUSS-9qWcVKUWqB7-khRB3HMZDMGaTSNLaAkx8GZmM66YJv3rWY_bxAywP67mVXHaTpd_SzHsmK_yQ3aExbcF8zBXMpz_tDMolAG8Y6CmVtL4i6qzJ9sM1ZT1lCvBLoE9ngxFRzOs7eIes2fAHMYa-0lIEk8F7GwV9J3lswi2ircfOgZgf53DHAt8oWVNgghJsUCqYi-jrl3_7EEoxIiM-Rxch9ZK4JLFo3MNNuIw0PBAMWowBxo0qKEqNKzDpoXqrWFeR9SO-hrXP2VoZ9uCUaGyXoWAUcROTxgM84HiBUUjh65f_rhlyNljabB21AUNWP4jYrMlr1XyEwb6zhmBD971VAbZdIzFEw0RSon-EC-wA0xPYCbYYe9fQipTTnNik2yzwGaZ1E36iMQ1azpEKT_gURlx4d9-mOpR00LcKHidKnQ8rnASTiExow1NqWBmMhD-Pc9hnKuRk3oMAqcVUX_YdozhAq2jk23DhLhAP9eyaRi-ORpIqxe4Rx9sYhggwwky84NgVU0GBeWbkn-C9iCbTJvwBFbBHTPAZ0Mibx5l3h8-caY3BPzKVEgcivwmvRUz1WMgJBokW4E0pChvDwpCZpgxSKETzm6xZcn-NhF7FDfD3GFsalzPymQUTbK4QPjwIeVeHkZh_B__7zz__sRZJIwnOmsGvX_4F78RstU1bmvAxG0lE8F6SQBFP4_DZg9JgbD6OY-jwKEjakDTwkQQl4GOSxUxdoOI9_WgbjUBUkvLUz01kY3p8c5bWLJNGLOO5wl5w6Mkm-mDxio0TpaWZ-Ps-u88C0IyfUvDGBDsvxAg0Aisio0hrnDbLEigTl6ePQ7y3QXG-iNGjZSUwk7iYwMFBOmB5U1w81A6bY-FFCq9aTCacXgru44OMsGqZW8QkMMnony--S9WJUd7JSAxjsUJ1DXGh_LByCD_iXMxUg9jyYQV6-DysZBYGuSnjIYPvxPgfzcdvEvBWE5Tdm4KtZraSwKzGbjTEXp6HiFst2R3dm4itZrYSoazGbkTEXp6HiCsc7femYYuRrSSYKWY3CoyHbxEAj8MdBYrqC87fERwDs1YPrjglEmamcE8HnrH0Z2zwmvXAFD5V_yGKvxJJJpKE013ID1Ol3Xog8_U8cfiGEh8nVVyrc4ovLD1o4xTzeFDTWH1YqUPJwg4A37RfCFlnb2SdHZF1XghZd29k3R2RdV8I2dHeyI52RHb0QsjcvZG5OyJzXwjZ8d7IjndEdvw8yC7ta7DZu9hp3Zlp7bj6zF-6nwfOXyS-l1B_VzwiV9sNUOLvGRGZ1cmleXfbdRFklXZfCcUbAc8UbNk76E7BlmntGGy53tOs7nBV9EZI9hnfNwn_OeI5imKiZhIgUeQJXRPpX0pK8kAYmCIYmbKn6qco8MUeS_aN6gVy_ob1Tx1amH77NHmjeqHJP9OnbzL2pt2RrlVfnbonr2_a1UenQ1Wnm9BVM5nYE4ceZHbiSaWaJUgV86Na3bjmjmS4NTz7js_u7X16t3DYGM3YXZURC_ye2Y7D5sX778tBphH07RZwej5zabeGk42fZHPYnKr0JlyMCF-AkWvGZw5mt2moARqNhynTtAevbm5u7I5QozHixLvDks5157JzWixs2P0fojTWttutm9Z1UotvFPNGuwdyMiK143Yduj_UodOqQ6vZcg-LQp3NQicloe5GoXanJHSUCLldFDpBoRMj1G2VhNxEyFR2XPx1jdBxQYjSwGDtXLluiia0_YWlxxet1o1bKi1S4J60WldX5WrOJlOdOD1Bp8an65aJmFPOxUPR0s3F1VXbLVWnDXdbBv8R_rWNlaMVI4k_030X16kFTDRb5F51u3lRQfb6MpNVU-Ibb63wE7Q7-Nft4p95sv4N8_G32To-rNuKbvO4fYLX0-bp0ek2YdtQDHB0cgC9MZNKN7wp43660Ynv6BMWNLQI0Xm8GTm0Z1QYymZ1UAxhYyPidbBHWDy1EBLfrPVQHdqSzs6KdvG9sdlxsdRWZQ9IYC4Z_x_gigLCfPu11C5Uy8SzqpHA_J2t1C7LCJJl7CqIaTsGMe0k125yPUqubnI9ThvEWUAbUxp3XbvZPltnr9N0c1D2vPIB3_B7EEqq9bxIbbEBm_qhW7S0grad1xWswSKhcYzR3FDsMzWSlmQoi3Y2i3Y2iHY3i7Y3iG7gbYPqqiJ2kF2AmbMJZGks5Ixoc7ZdPFhL-8wewSRkjXAUnNiTi0YyH9wTWStn_2HC38gudRsSAyFSvXLolZTLY2uqXmh_q3lS6Jc87G38mUFvtV8Q03qLS-62NtLd0kg7T5TaNiYzxuc46f2R6kuJ0656JwKBc-UMLyokHl3LyDgH13H8kGVqck69ynsZR3LKFVckrWTBlEqms-IyfbKQxbnfDal7APkaOKMw5ojTMaagGR2V4MxPeIknrMNHQU1MtNfzSJZ9lSAm7m2Ctjd576x67-S-0UX8NefLZrFQqVdmwmdjRv1KT8uILj8s_w8G-ms8GyIAAA==
*/
/**
* Svelte 5 with the tiptap editor default editor example
* GitHub gist backup: https://gist.github.com/fubits1/f2e27c6fa8f5c2850689d8585a68c5e0
* runed version of: https://svelte.dev/repl/c5cae550c2f4418e95c4dbecf832e6f5?version=4.2.18
* adapted from: https://github.com/ueberdosis/tiptap/tree/main/demos/src/Examples/Default/Svelte
*/
import { Color } from '@tiptap/extension-color'
import ListItem from '@tiptap/extension-list-item'
import TextStyle from '@tiptap/extension-text-style'
import StarterKit from "@tiptap/starter-kit";
import { Editor } from "@tiptap/core";
import { onMount } from "svelte";
let element = $state();
let editor = $state();
onMount(() => {
editor = new Editor({
element: element,
extensions: [
Color.configure({ types: [TextStyle.name, ListItem.name] }),
TextStyle.configure({ types: [ListItem.name] }),
StarterKit,
],
content: `
<h2>
Hi there,
</h2>
<p>
this is a <em>basic</em> example of <strong>Tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
</p>
<ul>
<li>
That’s a bullet list with one …
</li>
<li>
… or two list items.
</li>
</ul>
<p>
Isn’t that great? And all of that is editable. But wait, there’s more. Let’s try a code block:
</p>
<pre><code class="language-css">body {
display: none;
}</code></pre>
<p>
I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too.
</p>
<blockquote>
Wow, that’s amazing. Good work, boy! 👏
<br />
— Mom
</blockquote>
`,
onTransaction: () => {
// force re-render so `editor.isActive` works as expected
editor = editor;
},
});
});
</script>
{#if editor}
<div class="control-group">
<div class="button-group">
<button
onclick={() => console.log && editor.chain().focus().toggleBold().run()}
disabled={!editor.can().chain().focus().toggleBold().run()}
class={editor.isActive("bold") ? "is-active" : ""}
>
Bold
</button>
<button
onclick={() => editor.chain().focus().toggleItalic().run()}
disabled={!editor.can().chain().focus().toggleItalic().run()}
class={editor.isActive("italic") ? "is-active" : ""}
>
Italic
</button>
<button
onclick={() => editor.chain().focus().toggleStrike().run()}
disabled={!editor.can().chain().focus().toggleStrike().run()}
class={editor.isActive("strike") ? "is-active" : ""}
>
Strike
</button>
<button
onclick={() => editor.chain().focus().toggleCode().run()}
disabled={!editor.can().chain().focus().toggleCode().run()}
class={editor.isActive("code") ? "is-active" : ""}
>
Code
</button>
<button onclick={() => editor.chain().focus().unsetAllMarks().run()}>Clear marks</button>
<button onclick={() => editor.chain().focus().clearNodes().run()}>Clear nodes</button>
<button
onclick={() => editor.chain().focus().setParagraph().run()}
class={editor.isActive("paragraph") ? "is-active" : ""}
>
Paragraph
</button>
<button
onclick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
class={editor.isActive("heading", { level: 1 }) ? "is-active" : ""}
>
H1
</button>
<button
onclick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
class={editor.isActive("heading", { level: 2 }) ? "is-active" : ""}
>
H2
</button>
<button
onclick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
class={editor.isActive("heading", { level: 3 }) ? "is-active" : ""}
>
H3
</button>
<button
onclick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
class={editor.isActive("heading", { level: 4 }) ? "is-active" : ""}
>
H4
</button>
<button
onclick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
class={editor.isActive("heading", { level: 5 }) ? "is-active" : ""}
>
H5
</button>
<button
onclick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
class={editor.isActive("heading", { level: 6 }) ? "is-active" : ""}
>
H6
</button>
<button
onclick={() => editor.chain().focus().toggleBulletList().run()}
class={editor.isActive("bulletList") ? "is-active" : ""}
>
Bullet list
</button>
<button
onclick={() => editor.chain().focus().toggleOrderedList().run()}
class={editor.isActive("orderedList") ? "is-active" : ""}
>
Ordered list
</button>
<button
onclick={() => editor.chain().focus().toggleCodeBlock().run()}
class={editor.isActive("codeBlock") ? "is-active" : ""}
>
Code block
</button>
<button
onclick={() => editor.chain().focus().toggleBlockquote().run()}
class={editor.isActive("blockquote") ? "is-active" : ""}
>
Blockquote
</button>
<button onclick={() => editor.chain().focus().setHorizontalRule().run()}>
Horizontal rule
</button>
<button onclick={() => editor.chain().focus().setHardBreak().run()}>Hard break</button>
<button
onclick={() => editor.chain().focus().undo().run()}
disabled={!editor.can().chain().focus().undo().run()}
>
Undo
</button>
<button
onclick={() => editor.chain().focus().redo().run()}
disabled={!editor.can().chain().focus().redo().run()}
>
Redo
</button>
<button
onclick={() => editor.chain().focus().setColor('#958DF1').run()}
class={editor.isActive('textStyle', { color: '#958DF1' }) ? 'is-active' : ''}
>
Purple
</button>
</div>
</div>
{/if}
<div bind:this={element}></div>
<style>
/* Basic editor styles */
:global{
.tiptap {
--white: #FFF;
--black: #2E2B29;
--black-contrast: #110F0E;
--gray-1: rgba(61, 37, 20, 0.05);
--gray-2: rgba(61, 37, 20, 0.08);
--gray-3: rgba(61, 37, 20, 0.12);
--gray-4: rgba(53, 38, 28, 0.30);
--gray-5: rgba(28, 25, 23, 0.60);
--green: #22C55E;
--purple: #6A00F5;
--purple-contrast: #5800CC;
--purple-light: rgba(88, 5, 255, 0.05);
--yellow-contrast: #FACC15;
--yellow: rgba(250, 204, 21, 0.4);
--yellow-light: #FFFAE5;
--red: #FF5C33;
--red-light: #FFEBE5;
--shadow: 0px 12px 33px 0px rgba(0, 0, 0, 0.06), 0px 3.618px 9.949px 0px rgba(0, 0, 0, 0.04);
& :first-child {
margin-top: 0;
}
/* List styles */
& ul,
ol {
padding: 0 1rem;
margin: 1.25rem 1rem 1.25rem 0.4rem;
& li p {
margin-top: 0.25em;
margin-bottom: 0.25em;
}
}
/* Heading styles */
& h1,
h2,
h3,
h4,
h5,
h6 {
line-height: 1.1;
margin-top: 2.5rem;
text-wrap: pretty;
}
& h1,
h2 {
margin-top: 3.5rem;
margin-bottom: 1.5rem;
}
& h1 {
font-size: 1.4rem;
}
& h2 {
font-size: 1.2rem;
}
& h3 {
font-size: 1.1rem;
}
& h4,
h5,
h6 {
font-size: 1rem;
}
/* Code and preformatted text styles */
& code {
background-color: var(--purple-light);
border-radius: 0.4rem;
color: var(--black-contrast);
font-size: 0.85rem;
padding: 0.25em 0.3em;
}
& pre {
background: var(--black);
border-radius: 0.5rem;
color: var(--white);
font-family: 'JetBrainsMono', monospace;
margin: 1.5rem 0;
padding: 0.75rem 1rem;
& code {
background: none;
color: inherit;
font-size: 0.8rem;
padding: 0;
}
}
& blockquote {
border-left: 3px solid var(--gray-3);
margin: 1.5rem 0;
padding-left: 1rem;
}
& hr {
border: none;
border-top: 1px solid var(--gray-2);
margin: 2rem 0;
}
}
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment