npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@datadayrepos/ddrt

v2.5.51-re.1

Published

rich text editor

Readme

Vuetify Pro Tiptap

A WYSIWYG rich-text editor using tiptap and vuetify for Vue.js

see original https://github.com/yikoyu/vuetify-pro-tiptap for a better experience

Features

  • Use vuetify components
  • Many out of box extension (welcome to submit an issue for feature request)
  • Markdown support
  • TypeScript support
  • I18n support(en, zhHans, nl)
  • Vuetify 3.x and Vue 3.x support

Installation

NPM

pnpm add @datadayrepos/ddrt
# or
yarn add @datadayrepos/ddrt
# or
npm i @datadayrepos/ddrt -S

Install plugin

import { markRaw } from 'vue'
import { EditorTiptap, Viewer, createTipTap } from '@datadayrepos/ddrt'
import { BaseKit, Bold, Italic, Underline, Strike, Color, Highlight, Heading, TextAlign, FontFamily, FontSize, SubAndSuperScript, BulletList, OrderedList, TaskList, Indent, Link, Image, Video, Table, Blockquote, HorizontalRule, Code, CodeBlock, Clear, Fullscreen, History } from '@datadayrepos/ddrt'
import '@datadayrepos/ddrt/style.css'
import SelectImage from './components/SelectImage.vue'

export const vuetifyProTipTap = createTipTap({
  lang: 'en',
  components: {
    EditorTiptap,
    Viewer
  },
  extensions: [
    BaseKit.configure({
      placeholder: {
        placeholder: 'Enter some text...'
      }
    }),
    Bold,
    Italic,
    Underline,
    Strike,
    Code.configure({ divider: true }),
    Heading,
    TextAlign,
    FontFamily,
    FontSize,
    Color,
    Highlight.configure({ divider: true }),
    SubAndSuperScript.configure({ divider: true }),
    Clear.configure({ divider: true }),
    BulletList,
    OrderedList,
    TaskList,
    Indent.configure({ divider: true }),
    Link,
    Image.configure({
      imageTabs: [{ name: 'SELECT', component: markRaw(SelectImage) }],
      // hiddenTabs: ['upload'],
      upload(file: File) {
        const url = URL.createObjectURL(file)
        console.log('mock upload api :>> ', url)
        return Promise.resolve(url)
      }
    }),
    Video,
    Table.configure({ divider: true }),
    Blockquote,
    HorizontalRule,
    CodeBlock.configure({ divider: true }),
    History.configure({ divider: true }),
    Fullscreen
  ]
})
import { createApp } from 'vue'
import { createVuetify } from 'vuetify'
import App from './App.vue'
import { vuetifyProTipTap } from './tiptap'

import 'vuetify/styles'

const vuetify = createVuetify()

const app = createApp(App)
app.use(vuetify)
app.use(vuetifyProTipTap)

// fix warning injected property "decorationClasses" is a ref and will be auto-unwrapped
// https://github.com/ueberdosis/tiptap/issues/1719
app.config.unwrapInjectedRef = true

app.mount('#app')

Global Settings

import { markRaw } from 'vue'
import { EditorTiptap, Viewer, createTipTap, defaultBubbleList } from '@datadayrepos/ddrt'
import { BaseKit, Image, Fullscreen } from '@datadayrepos/ddrt'
import '@datadayrepos/ddrt/style.css'
import SelectImage from './components/SelectImage.vue'

export const vuetifyProTipTap = createTipTap({
  // Set default lang
  lang: 'en',
  // Set markdown theme
  markdownTheme: 'github',
  // Global registration app.component
  components: {
    EditorTiptap,
    Viewer
  },
  // Global registration extensions
  extensions: [
    BaseKit.configure({
      placeholder: {
        placeholder: 'Enter some text...'
      },
      bubble: {
        // default config
        list: {
          image: [ 'float-left', 'float-none', 'float-right', 'divider', 'size-small', 'size-medium', 'size-large', 'divider', 'textAlign', 'divider', 'image', 'image-aspect-ratio', 'remove'],
          text: ['bold', 'italic', 'underline', 'strike', 'divider', 'color', 'highlight', 'textAlign', 'divider', 'link'],
          video: ['video', 'remove']
        },
        defaultBubbleList: editor => {
          // You can customize the bubble menu here
          return defaultBubbleList(editor) // default customize bubble list
        }
      }
    }),
    Image.configure({
      // Generate a VDivider after the button
      divider: true,
      // Custom image tabs
      imageTabs: [{ name: 'SELECT', component: markRaw(SelectImage) }],
      // hidden default tab
      hiddenTabs: ['upload'],
      // custom upload function
      upload(file) {
        const url = URL.createObjectURL(file)
        console.log('mock upload api :>> ', url)
        return Promise.resolve(url)
      }
    }),
    Fullscreen.configure({
      // Generate a VSpacer after the button
      spacer: true
    })
  ]
})

Extensions

You can use the necessary extensions. The corresponding command-buttons will be added by declaring the order of the extension.

All available extensions:

Custom theme

Create github.scss

$value: 'github';

.ddrt-editor__content.markdown-theme-#{$value} {
  // your custom styles
  &.__dark {
    // your dark mode custom styles
  }
}

Import github.scss in ts

// import '@datadayrepos/ddrt/style.css' // import all(editor and markdown) styles
import '@datadayrepos/ddrt/styles/editor.css' // only use editor style, not using markdown style
import './styles/markdown/github.scss'

In the component using

<template>
  <EditorTiptap v-model="content" markdown-theme="github" />
  <Viewer :value="content" markdown-theme="github" />
</template>

Custom extensions

<template>
  <ActionButton tooltip="Full screen" :disabled="disabled">
    <VIcon>{{ `svg:${mdiFileCodeOutline}` }}</VIcon>
    <VDialog v-model="dialog" fullscreen hide-overlay activator="parent">
      <VCard>
        <VToolbar dark color="primary">
          <VBtn icon dark @click="dialog = false">
            <VIcon>{{ `svg:${mdiClose}` }}</VIcon>
          </VBtn>
        </VToolbar>

        <VContainer>
          <VSheet class="mx-auto" :max-width="maxWidth">
            <Viewer :value="editor.getHTML()" />
          </VSheet>
        </VContainer>
      </VCard>
    </VDialog>
  </ActionButton>
</template>

<script setup lang="ts">
import type { Editor } from '@tiptap/vue-3'
import { ActionButton } from '@datadayrepos/ddrt'
import { mdiClose, mdiFileCodeOutline } from '@mdi/js'
import { ref } from 'vue'

interface Props {
  editor: Editor
  tooltip?: string
  disabled?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  tooltip: undefined,
  disabled: false
})

const dialog = ref(false)
const maxWidth = ref<number>(900)
</script>
import type { ButtonView, GeneralOptions } from '@datadayrepos/ddrt'

import { Extension } from '@tiptap/core'
import PreviewActionButton from '../components/PreviewActionButton.vue'

export interface PreviewOptions extends GeneralOptions {
  button: ButtonView
}

export default Extension.create<PreviewOptions>({
  name: 'preview',
  addOptions() {
    return {
      divider: false,
      spacer: false,
      button: () => ({
        component: PreviewActionButton,
        componentProps: {}
      })
    }
  }
})

I18n

Setting language

You can declare when you install the plugin.

import { createTipTap } from '@datadayrepos/ddrt'

const VuetifyProTipTap = createTipTap({
  lang: 'en'
})

Or use setLang dynamic change

import { locale } from '@datadayrepos/ddrt'

locale.setLang('en')

Available languages:

  • en (default)
  • zhHans
  • nl
  • de

Use unavailable language

Loading unavailable language, use setMessage for Settings

import { locale } from '@datadayrepos/ddrt'

locale.setMessage('en', {
  // i18n text
})
locale.setLang('en')

Usage

<template>
  <VApp id="app">
    <VContainer>
      <EditorTiptap v-model="content" label="Title" rounded :min-height="200" :max-height="465" :max-width="900" :extensions="extensions" />
      <Viewer :value="content" />
    </VContainer>
  </VApp>
</template>

<script setup lang="ts">
import { BaseKit, Bold, Color, EditorTiptap, Fullscreen, Heading, Highlight, History, Image, Italic, Link, Strike, Table, Underline, Video, Viewer } from '@datadayrepos/ddrt'
import { ref } from 'vue'
import '@datadayrepos/ddrt/style.css'

const extensions = [
  BaseKit.configure({
    placeholder: {
      placeholder: 'Enter some text...'
    }
  }),
  Bold,
  Italic,
  Underline,
  Strike,
  Color,
  Highlight,
  Heading,
  Link,
  Image,
  Video,
  Table,
  Fullscreen,
  History
]

const content = ref('')
</script>

Props

EditorTiptap

Props

| Name | Type | Default | Description | | ---- | ---- | ---- | ---- | | modelValue | string | JSONContent | '' | The input’s value | | markdownTheme | string | false | 'default' | Markdown theme | | output | 'html' | 'json' | 'text' | 'html' | Output format | | dark | boolean | false | Applies the dark theme variant to the component. | | dense | boolean | false | Reduces the input height | | outlined | boolean | true | Applies the outlined style to the input | | flat | boolean | true | Removes the card’s elevation | | disabled | boolean | false | Disable the input | | label | string | undefined | Sets input label | | hideToolbar | boolean | false | Hidden the toolbar | | disableToolbar | boolean | false | Disable the toolbar | | hideBubble | boolean | false | Hidden the bubble menu | | removeDefaultWrapper | boolean | false | Default wrapper when the delete editor is empty | | maxWidth | string | number | undefined | Sets the maximum width for the component. | | minHeight | string | number | undefined | Sets the minimum height for the component. | | maxHeight | string | number | undefined | Sets the maximum height for the component. | | extensions | AnyExtension[] | [] | Tiptap the extensions | | editorClass | string | string[] | Record<string, any> | undefined | Editor class |

Slots

| Name | Description | | ---- | ---- | | editor | Slot to customize editor | | bottom | Slot to customize editor bottom |

Event

| Name | Type | Description | | ---- | ---- | ---- | | update:modelValue | string | JSONContent | Emitted when editor onUpdate | | update:markdownTheme | string | Emitted when change theme | | change | { editor: Editor, output: string | JSONContent } | Emitted when editor onUpdate | | enter | | Keyboard enter return |

Viewer

Props

| Name | Type | Default | Description | | ---- | ---- | ---- | ---- | | value | string | JSONContent | '' | The preview’s value | | dark | boolean | false | Applies the dark theme variant to the component. | | dense | boolean | false | Reduces the input height | | markdownTheme | string | false | 'default' | Markdown theme | | xss | boolean | true | Enable xss filter | | xssOptions | xss.IWhiteList | Default rule | Xss filter rule config | | maxWidth | string | number | undefined | Sets the maximum width for the component. | | extensions | AnyExtension[] | [] | Tiptap the extensions |

Slots

| Name | Description | | ---- | ---- | | before | Add content at the before | | after | Add content at the after |

🏗 Contributing

  1. 🍴Fork it
  2. 🔀Create your branch: git checkout -b your-branch
  3. 🎨Make your changes
  4. 📝Commit your changes with Semantic Commit Messages (recommended)
  5. 🚀Push to the branch: git push origin your-branch
  6. 🎉Submit a PR to develop branch

📄 License

MIT

Thanks