Nuxt TipTap Editor

repository·main·Indexed 41 days ago

https://github.com/modbender/nuxt-tiptap-editor

A Nuxt 3 module for integrating the TipTap editor into Nuxt applications. It provides auto-imports for Tiptap extensions, components, and core classes, along with the useEditor composable and TiptapEditorContent component. Version 3.4.0 includes custom extensions like TiptapImageUpload for handling image uploads via paste, drag-and-drop, or remote URLs.

Tokens
14.1K
Snippets
51
Records
59
Agent score
99%

What's inside Nuxt TipTap Editor

  1. Overview of Nuxt Tiptap Editor

    main

    Nuxt Tiptap Editor is a Nuxt module designed to simplify the integration of the Tiptap rich-text editor into Nuxt applications. Instead of manually installing and wiring up a long list of Tiptap packages, this module automates the process by providing Nuxt auto-imports for:

    • The useEditor composable.
    • The EditorContent component.
    • StarterKit nodes, marks, and extensions.
    • A custom image-upload extension.

    It provides a headless, fully customizable WYSIWYG editor experience with automatic SSR handling and no need for manual transpile configuration or global registration.

  2. What is Nuxt Tiptap Editor?

    main

    Nuxt Tiptap Editor is a Nuxt module designed to simplify the integration of the Tiptap Editor into Nuxt 3 and Nuxt 4 projects. Its primary purpose is to handle the complex installation and configuration processes required for Tiptap and, most importantly, to provide auto-imports for Tiptap features within your Nuxt application.

    Current Status: The module currently focuses on providing minimal and essential imports to allow for quick integration. Future updates may expand its feature set.

  3. How SSR and ESM compatibility is handled

    main

    Because Tiptap packages are ESM-only, they can cause issues during Nuxt's Server-Side Rendering (SSR). This module automatically resolves these issues by:

    1. Adding all registered Tiptap packages to build.transpile to ensure they work under SSR.
    2. Hoisting @tiptap/vue-3 types via typescript.hoist for correct type resolution.

    No manual configuration is required for these features.

  4. Understand default Tiptap extensions and Lowlight opt-in

    main

    The nuxt-tiptap-editor module automatically registers a curated set of extensions.

    Always included:

    • StarterKit (includes all its nodes, marks, and extensions)
    • Link mark
    • Image node

    Opt-in (Lowlight): Syntax highlighting via Code Block Lowlight and its associated composables (createLowlight, commonLanguages, allLanguages) are not enabled by default. To use them, you must set the tiptap.lowlight option to something other than false in your configuration. This keeps your bundle size smaller for users who do not require syntax highlighting.

    Note on Naming: A default prefix Tiptap is applied to all auto-imported extensions, but not to composables. For example, StarterKit is available as TiptapStarterKit, but useEditor remains useEditor.

  5. Understand Nuxt auto-imports and the prefix rule

    main

    The nuxt-tiptap-editor module registers its exports as Nuxt auto-imports, allowing you to use them in components without manual import statements.

    There is a specific naming convention applied to these auto-imports:

    1. Composables: These keep their original names and are not prefixed. Examples include useEditor and lowlight helpers.
    2. Everything else: Components, core classes, nodes, marks, and extensions are prefixed with a configurable string. The default prefix is Tiptap.

    For example, with the default settings, StarterKit is available as TiptapStarterKit and EditorContent as TiptapEditorContent.

    export default defineNuxtConfig({
      modules: ['nuxt-tiptap-editor'],
      tiptap: {
        prefix: 'Tiptap',
      },
    })
  6. Configure nuxt-tiptap-editor in Nuxt

    main

    To use the module, add nuxt-tiptap-editor to your modules array in nuxt.config.js. You can also configure the tiptap key to set a custom prefix for the auto-imported Tiptap components.

    export default defineNuxtConfig({
      modules: ['nuxt-tiptap-editor'],
      tiptap: {
        prefix: 'Tiptap', //prefix for Tiptap components
      },
    });
  7. Managing editor lifecycle and destruction

    main

    When using the useEditor composable, the editor instance is automatically destroyed when the component unmounts. You do not need to manually call .destroy().

    However, if you instantiate the editor manually using new TiptapEditor(...) (or new Editor(...) from Tiptap) outside of the provided composable, you are responsible for its lifecycle and must manually call destroy() during the onBeforeUnmount hook to prevent memory leaks.

    const editor = new TiptapEditor({
      extensions: [TiptapStarterKit],
    })
    
    onBeforeUnmount(() => {
      editor.destroy()
    })
  8. Install external Tiptap extensions

    main

    To use Tiptap extensions that are not part of the module's default set, you must install them manually. It is recommended to install these as devDependencies.

    # Using pnpm
    pnpm add -D @tiptap/extension-placeholder
    
    # Using npm
    npm install --save-dev @tiptap/extension-placeholder
    
    # Using yarn
    yarn add -D @tiptap/extension-placeholder
  9. Implement image uploading with TiptapImageUpload

    main

    The TiptapImageUpload extension is a custom plugin provided by this module that handles image uploads via paste, drag-and-drop, or remote URL pasting. It works by inserting a TiptapImagePlaceholder node, executing your provided upload handler, and then replacing the placeholder with a standard TiptapImage node once the upload completes.

    To use it, include TiptapImageUpload and TiptapImagePlaceholder in your editor extensions. You must provide an async upload function in the configuration.

    <script setup>
    async function uploadImage(file, id) {
      const formData = new FormData()
      formData.append(id, file)
    
      const urls = await $fetch('/api/upload', {
        method: 'POST',
        body: formData,
      })
    
      return urls[0]
    }
    
    const editor = useEditor({
      extensions: [
        TiptapStarterKit,
        TiptapImage,
        TiptapImageUpload.configure({
          upload: uploadImage,
        }),
        TiptapImagePlaceholder.configure({
          inline: false,
        }),
      ],
    })
    </script>
  10. Set up the local development environment

    main

    This project uses pnpm as its package manager. To set up the environment, install dependencies and generate the necessary type stubs.

    Important: You must run pnpm dev:prepare at least once after installation or after making structural changes to the src/ directory. Failure to do so may cause pnpm dev or pnpm test to fail with type or import errors.

    # Install dependencies
    pnpm install
    
    # Generate type stubs (required before dev or test)
    pnpm dev:prepare
  11. Enable syntax highlighting with lowlight

    main

    To use syntax-highlighted code blocks, you must enable the lowlight option in your nuxt.config.ts. By default, lowlight is set to false to minimize bundle size. When enabled, the module registers CodeBlockLowlight and provides lowlight composables.

    Configure the tiptap.lowlight object to specify the theme and version. The module will automatically inject a highlight.js theme CSS <link> into your application's <head> using unpkg.

    export default defineNuxtConfig({
      modules: ['nuxt-tiptap-editor'],
      tiptap: {
        prefix: 'Tiptap',
        lowlight: {
          theme: 'github-dark', // default
          highlightJSVersion: '11.10.0', // default
          // integrity: 'sha384-...', // optional Subresource Integrity hash
        },
      },
    })