├── .gitignore
├── .husky
├── commit-msg
└── pre-commit
├── .vscode
├── extensions.json
└── settings.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── docs
├── .vitepress
│ ├── config.ts
│ └── theme
│ │ ├── Layout.vue
│ │ ├── components
│ │ └── NodeEditor.vue
│ │ └── index.ts
├── changelog.md
├── extensions
│ ├── block-container.md
│ ├── code-block-shiki.md
│ ├── details.md
│ ├── emoji.md
│ └── unique-id.md
├── guide
│ └── vue.md
├── index.md
├── playground.md
└── zh-CN
│ ├── changelog.md
│ ├── extensions
│ ├── block-container.md
│ ├── code-block-shiki.md
│ ├── details.md
│ ├── emoji.md
│ └── unique-id.md
│ ├── guide
│ └── vue.md
│ ├── index.md
│ └── playground.md
├── eslint.config.js
├── migrations.json
├── nx.json
├── package.json
├── packages
├── tiptap-extension-block-container
│ ├── README.md
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── blockContainer.css
│ │ ├── blockContainer.ts
│ │ ├── extentDocument.ts
│ │ └── index.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── vite.config.ts
├── tiptap-extension-code-block-shiki
│ ├── README.md
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── codeBlockShiki.css
│ │ ├── codeBlockShiki.ts
│ │ └── index.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── vite.config.ts
├── tiptap-extension-details
│ ├── README.md
│ ├── eslint.config.js
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── details.ts
│ │ ├── detailsContent.ts
│ │ ├── detailsSummary.ts
│ │ └── index.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── vite.config.ts
├── tiptap-extension-emoji
│ ├── README.md
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── emoji.ts
│ │ └── index.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── vite.config.ts
├── tiptap-extension-unique-id
│ ├── README.md
│ ├── eslint.config.js
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── index.ts
│ │ └── uniqueId.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── vite.config.ts
├── vue-kit
│ ├── README.md
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── components
│ │ │ └── NoteEditor.vue
│ │ ├── composables
│ │ │ └── useNoteEditor.ts
│ │ ├── index.ts
│ │ ├── setupKit.ts
│ │ └── vue-shims.d.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── vite.config.ts
└── vue-play
│ ├── index.html
│ ├── package.json
│ ├── project.json
│ ├── src
│ ├── App.vue
│ └── main.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ └── vite.config.ts
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── tsconfig.base.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | dist
5 | tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 |
20 | # IDE - VSCode
21 | .vscode/*
22 | !.vscode/settings.json
23 | !.vscode/tasks.json
24 | !.vscode/launch.json
25 | !.vscode/extensions.json
26 |
27 | # misc
28 | /.sass-cache
29 | /connect.lock
30 | /coverage
31 | /libpeerconnection.log
32 | npm-debug.log
33 | yarn-error.log
34 | testem.log
35 | /typings
36 |
37 | # System Files
38 | .DS_Store
39 | Thumbs.db
40 |
41 | .nx/cache
42 | .nx/workspace-data
43 |
44 | # vitepress docs
45 | docs/.vitepress/cache
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | npx --no -- commitlint --edit $1
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | npx lint-staged
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "nrwl.angular-console",
4 | "dbaeumer.vscode-eslint",
5 | "esbenp.prettier-vscode"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.experimental.useFlatConfig": true,
3 | "prettier.enable": false,
4 | "editor.formatOnSave": true,
5 | "editor.codeActionsOnSave": {
6 | "source.fixAll.eslint": "explicit",
7 | "source.organizeImports": "never"
8 | },
9 | "eslint.rules.customizations": [
10 | { "rule": "style/*", "severity": "off" },
11 | { "rule": "format/*", "severity": "off" },
12 | { "rule": "*-indent", "severity": "off" },
13 | { "rule": "*-spacing", "severity": "off" },
14 | { "rule": "*-spaces", "severity": "off" },
15 | { "rule": "*-order", "severity": "off" },
16 | { "rule": "*-dangle", "severity": "off" },
17 | { "rule": "*-newline", "severity": "off" },
18 | { "rule": "*quotes", "severity": "off" },
19 | { "rule": "*semi", "severity": "off" }
20 | ],
21 | "eslint.validate": [
22 | "javascript",
23 | "javascriptreact",
24 | "typescript",
25 | "typescriptreact",
26 | "vue",
27 | "html",
28 | "markdown",
29 | "json",
30 | "jsonc",
31 | "yaml",
32 | "toml"
33 | ],
34 | "cSpell.words": [
35 | "blockquote",
36 | "dropcursor",
37 | "emojilib",
38 | "Gapcursor",
39 | "Prosemirror",
40 | "shiki",
41 | "unref"
42 | ],
43 | "typescript.tsdk": "node_modules/typescript/lib"
44 | }
45 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 0.3.1 (2024-04-20)
2 |
3 |
4 | ### 🚀 Features
5 |
6 | - **emoji:** remove ^ for input rules ([b4d8f7c](https://github.com/litingyes/note-editor/commit/b4d8f7c))
7 |
8 | ### 🩹 Fixes
9 |
10 | - **block-container:** split error ([d000839](https://github.com/litingyes/note-editor/commit/d000839))
11 |
12 | ### ❤️ Thank You
13 |
14 | - liting @litingyes
15 |
16 | ## 0.3.0 (2024-03-29)
17 |
18 |
19 | ### 🚀 Features
20 |
21 | - **emoji:** init ([cb7bfa8](https://github.com/liting-yes/note-editor/commit/cb7bfa8))
22 |
23 | ### 🩹 Fixes
24 |
25 | - **code-block-shiki:** type check error ([335afec](https://github.com/liting-yes/note-editor/commit/335afec))
26 | - **code-block-shiki:** decorations parse error ([3d36f20](https://github.com/liting-yes/note-editor/commit/3d36f20))
27 |
28 | ### ❤️ Thank You
29 |
30 | - liting @liting-yes
31 |
32 | ## 0.2.1 (2024-03-27)
33 |
34 |
35 | ### 🩹 Fixes
36 |
37 | - **code-block-shiki:** find code-block change and highlighter is valid ([c4ce39e](https://github.com/liting-yes/note-editor/commit/c4ce39e))
38 |
39 | ### ❤️ Thank You
40 |
41 | - liting @liting-yes
42 |
43 | ## 0.2.0 (2024-03-27)
44 |
45 |
46 | ### 🚀 Features
47 |
48 | - **details:** done ([681d497](https://github.com/liting-yes/note-editor/commit/681d497))
49 | - **unique id:** add types as default value ([5041e98](https://github.com/liting-yes/note-editor/commit/5041e98))
50 | - **vue-kit:** export vue sfc instance type ([c55e238](https://github.com/liting-yes/note-editor/commit/c55e238))
51 |
52 | ### 🩹 Fixes
53 |
54 | - **code-block-shiki:** handle highlighter is null ([2c35721](https://github.com/liting-yes/note-editor/commit/2c35721))
55 | - **unique-id:** traversal logic in create ([f0de32b](https://github.com/liting-yes/note-editor/commit/f0de32b))
56 |
57 | ### ❤️ Thank You
58 |
59 | - liting @liting-yes
60 |
61 | ## 0.1.0 (2024-03-24)
62 |
63 |
64 | ### 🚀 Features
65 |
66 | - **code-block-shiki:** support display and toggle lang ([9e60091](https://github.com/liting-yes/note-editor/commit/9e60091))
67 |
68 | ### 🩹 Fixes
69 |
70 | - **code-block-shiki:** calculate the length of ([9086c2a](https://github.com/liting-yes/note-editor/commit/9086c2a))
71 |
72 | ### ❤️ Thank You
73 |
74 | - liting @liting-yes
75 |
76 | ## 0.0.1-10 (2024-03-22)
77 |
78 |
79 | ### 🚀 Features
80 |
81 | - **block-container:** reader drag bar ([7ed9c3e](https://github.com/liting-yes/note-editor/commit/7ed9c3e))
82 | - **code-block-shiki:** init ([ac6393f](https://github.com/liting-yes/note-editor/commit/ac6393f))
83 | - **shiki:** support option theme ([86c7258](https://github.com/liting-yes/note-editor/commit/86c7258))
84 | - **unique id:** add blockContainer as default type ([db331a5](https://github.com/liting-yes/note-editor/commit/db331a5))
85 | - **unique id:** support inject node-name ([12bcd5f](https://github.com/liting-yes/note-editor/commit/12bcd5f))
86 | - **vue:** add code block ([0a4a99a](https://github.com/liting-yes/note-editor/commit/0a4a99a))
87 |
88 | ### 🩹 Fixes
89 |
90 | - **block container:** set attrs on dom ([9c34cc7](https://github.com/liting-yes/note-editor/commit/9c34cc7))
91 | - **block container:** handle enter ([25cb01e](https://github.com/liting-yes/note-editor/commit/25cb01e))
92 | - **shiki:** highlighter-generic type ([8089bac](https://github.com/liting-yes/note-editor/commit/8089bac))
93 |
94 | ### ❤️ Thank You
95 |
96 | - liting @liting-yes
97 |
98 | ## 0.0.1-9 (2024-03-07)
99 |
100 | This was a version bump only, there were no code changes.
101 |
102 | ## 0.0.1-8 (2024-03-07)
103 |
104 |
105 | ### 🚀 Features
106 |
107 | - **dragBar:** support split by enter ([363cb91](https://github.com/liting-yes/note-editor/commit/363cb91))
108 |
109 | ### ❤️ Thank You
110 |
111 | - liting @liting-yes
112 |
113 | ## 0.0.1-7 (2024-03-06)
114 |
115 | This was a version bump only, there were no code changes.
116 |
117 | ## 0.0.1-6 (2024-03-04)
118 |
119 |
120 | ### 🚀 Features
121 |
122 | - **vue-kit:** support pass editorOptions in useNoteEditor ([f06c5ff](https://github.com/liting-yes/note-editor/commit/f06c5ff))
123 |
124 | ### 🩹 Fixes
125 |
126 | - **tiptap-extension-unique-id:** generate id error ([94ec0b8](https://github.com/liting-yes/note-editor/commit/94ec0b8))
127 |
128 | ### ❤️ Thank You
129 |
130 | - liting @liting-yes
131 |
132 | ## 0.0.1-4 (2024-03-02)
133 |
134 |
135 | ### 🚀 Features
136 |
137 | - **vue-kit:** add focus and underline extensions ([a89188a](https://github.com/liting-yes/note-editor/commit/a89188a))
138 | - **vue-kit:** add useNoteEditor ([9ba3469](https://github.com/liting-yes/note-editor/commit/9ba3469))
139 | - **vue-kit:** add unique-id ([eb87840](https://github.com/liting-yes/note-editor/commit/eb87840))
140 |
141 | ### ❤️ Thank You
142 |
143 | - liting @liting-yes
144 |
145 | ## 0.0.1-3 (2024-03-02)
146 |
147 |
148 | ### 🩹 Fixes
149 |
150 | - dependencies ([7e32e0a](https://github.com/liting-yes/note-editor/commit/7e32e0a))
151 |
152 | ### ❤️ Thank You
153 |
154 | - liting @liting-yes
155 |
156 | ## 0.0.1-2 (2024-03-02)
157 |
158 |
159 | ### 🚀 Features
160 |
161 | - init @note-editor/vue-kit ([b8666fa](https://github.com/liting-yes/note-editor/commit/b8666fa))
162 |
163 | ### ❤️ Thank You
164 |
165 | - liting @liting-yes
166 |
167 | ## 0.0.1-1 (2024-03-01)
168 |
169 |
170 | ### 🚀 Features
171 |
172 | - init tiptap-extension-unique-id ([418406d](https://github.com/liting-yes/note-editor/commit/418406d))
173 |
174 | ### ❤️ Thank You
175 |
176 | - liting @liting-yes
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Liting
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Note Editor
2 |
3 | Tiptap-based text editor
4 |
5 | > [!IMPORTANT]
6 | > Trying out best practice: [Rich text editor with Vue.js & Tiptap](https://github.com/vueditor/rich-text-editor.git)
7 |
--------------------------------------------------------------------------------
/docs/.vitepress/config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitepress'
2 |
3 | export default defineConfig({
4 | title: 'Note Editor',
5 | description: 'Tiptap-based text editor',
6 | lastUpdated: true,
7 | themeConfig: {
8 | socialLinks: [
9 | {
10 | icon: 'npm',
11 | link: 'https://www.npmjs.com/settings/note-editor/packages',
12 | },
13 | {
14 | icon: 'github',
15 | link: 'https://github.com/liting-yes/note-editor.git',
16 | },
17 | ],
18 | footer: {
19 | message: 'Released under the MIT License.',
20 | copyright: 'Copyright © 2024-present Liting',
21 | },
22 | search: {
23 | provider: 'local',
24 | },
25 | },
26 | locales: {
27 | 'root': {
28 | label: 'English',
29 | lang: 'en-US',
30 | themeConfig: {
31 | nav: [
32 | { text: 'Guide', link: '/guide/vue' },
33 | { text: 'Extensions', link: '/extensions/block-container' },
34 | { text: 'Playground', link: '/playground' },
35 | { text: 'CHANGELOG', link: '/changelog' },
36 | ],
37 | sidebar: [
38 | {
39 | text: 'Guide',
40 | items: [
41 | { text: 'Vue', link: '/guide/vue' },
42 | ],
43 | },
44 | {
45 | text: 'Extensions',
46 | items: [
47 | { text: 'Block container', link: '/extensions/block-container' },
48 | { text: 'Code block shiki', link: '/extensions/code-block-shiki' },
49 | { text: 'Details', link: '/extensions/details' },
50 | { text: 'Emoji', link: '/extensions/emoji' },
51 | { text: 'Unique ID', link: '/extensions/unique-id' },
52 | ],
53 | },
54 | {
55 | text: 'Playground',
56 | link: '/playground',
57 | },
58 | ],
59 | },
60 | },
61 | 'zh-CN': {
62 | label: '简体中文',
63 | lang: 'zh-CN',
64 | themeConfig: {
65 | nav: [
66 | { text: '指南', link: '/zh-CN/guide/vue' },
67 | { text: '插件', link: '/zh-CN/extensions/block-container' },
68 | { text: '演练场', link: '/zh-CN/playground' },
69 | { text: 'CHANGELOG', link: '/zh-CN/changelog' },
70 |
71 | ],
72 | sidebar: [
73 | {
74 | text: '指南',
75 | items: [
76 | { text: 'Vue', link: '/zh-CN/guide/vue' },
77 | ],
78 | },
79 | {
80 | text: '插件',
81 | items: [
82 | { text: 'Block container (块容器)', link: '/zh-CN/extensions/block-container' },
83 | { text: 'Code block shiki (shiki代码块)', link: '/zh-CN/extensions/code-block-shiki' },
84 | { text: 'Details (详情块)', link: '/zh-CN/extensions/details' },
85 | { text: 'Emoji (表情)', link: '/zh-CN/extensions/emoji' },
86 | { text: 'Unique ID (唯一ID)', link: '/zh-CN/extensions/unique-id' },
87 | ],
88 | },
89 | {
90 | text: 'Playground (演练场)',
91 | link: '/zh-CN/playground',
92 | },
93 | ],
94 | },
95 | },
96 | },
97 | })
98 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/Layout.vue:
--------------------------------------------------------------------------------
1 |
43 |
44 |
45 |
46 |
47 |
48 |
73 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/components/NodeEditor.vue:
--------------------------------------------------------------------------------
1 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/index.ts:
--------------------------------------------------------------------------------
1 | import type { Theme } from 'vitepress'
2 | import DefaultTheme from 'vitepress/theme'
3 | import Layout from './Layout.vue'
4 | import NodeEditor from './components/NodeEditor.vue'
5 |
6 | export default {
7 | extends: DefaultTheme,
8 | Layout,
9 | enhanceApp({ app }) {
10 | app.component('NoteEditor', NodeEditor)
11 | },
12 | } satisfies Theme
13 |
--------------------------------------------------------------------------------
/docs/changelog.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 |
4 |
--------------------------------------------------------------------------------
/docs/extensions/block-container.md:
--------------------------------------------------------------------------------
1 | # Block Container
2 |
3 | bloc container extension for tiptap
4 |
5 | ## Installation
6 |
7 | ::: code-group
8 |
9 | ```bash [npm]
10 | npm install @note-editor/tiptap-extension-block-container
11 | ```
12 |
13 | ```bash [pnpm]
14 | pnpm add @note-editor/tiptap-extension-block-container
15 | ```
16 |
17 | :::
18 |
19 | ## Usage
20 |
21 | ::: tip
22 | `@note-editor/tiptap-extension-block-container` is already included by [`@note-editor/vue-kit`](/guide/vue), so usually you don’t need to repeat the installation
23 | :::
24 |
25 | ::: danger
26 | The `@tiptap/extension-document` has been extended to implement a top-level block container, so please pay attention to the compatibility processing of old and new data structures. If you want to see more, please see the [source code](https://github.com/liting-yes/note-editor/blob/main/packages/tiptap-extension-block-container/src/extentDocument.ts).
27 | :::
28 |
29 | ```ts
30 | import { Editor } from '@tiptap/core'
31 | import { blockContainer } from '@note-editor/tiptap-extension-block-container'
32 |
33 | const editor = new Editor({
34 | content: '
@note-editor/tiptap-extension-unique-id
',
35 | extensions: [
36 | blockContainer
37 | ]
38 | })
39 | ```
40 |
--------------------------------------------------------------------------------
/docs/extensions/code-block-shiki.md:
--------------------------------------------------------------------------------
1 | # Code Block Shiki
2 |
3 | Code block extension with shiki for tiptap
4 |
5 | ::: warning
6 | The extension will override [Code block](https://tiptap.dev/docs/editor/api/nodes/code-block).
7 | :::
8 |
9 | ## Installation
10 |
11 | ::: code-group
12 |
13 | ```bash [npm]
14 | npm install @note-editor/tiptap-extension-code-block-shiki
15 | ```
16 |
17 | ```bash [pnpm]
18 | pnpm add @note-editor/tiptap-extension-code-block-shiki
19 | ```
20 |
21 | :::
22 |
23 | ## Usage
24 |
25 | ```ts
26 | import { Editor } from '@tiptap/core'
27 | import { codeBlockShiki } from '@note-editor/tiptap-extension-code-block-shiki'
28 |
29 | const editor = new Editor({
30 | content: '@note-editor/tiptap-extension-code-block-shiki
',
31 | extensions: [
32 | codeBlockShiki
33 | ]
34 | })
35 | ```
36 |
37 | ## Settings
38 |
39 | ### theme
40 |
41 | Theme for highlight, want to see more please check [shiki themes](https://shiki.style/themes)
42 |
43 | ```ts
44 | codeBlockShiki.configure({
45 | theme: 'vitesse-light' // default
46 | })
47 | ```
48 |
--------------------------------------------------------------------------------
/docs/extensions/details.md:
--------------------------------------------------------------------------------
1 | # Details
2 |
3 | Details extension for tiptap
4 |
5 | ## Installation
6 |
7 | ::: code-group
8 |
9 | ```bash [npm]
10 | npm install @note-editor/tiptap-extension-details
11 | ```
12 |
13 | ```bash [pnpm]
14 | pnpm add @note-editor/tiptap-extension-details
15 | ```
16 |
17 | :::
18 |
19 | ## Usage
20 |
21 | ```ts
22 | import { Editor } from '@tiptap/core'
23 | import { details } from '@note-editor/tiptap-extension-details'
24 |
25 | const editor = new Editor({
26 | content: '@note-editor/tiptap-extension-details
',
27 | extensions: [
28 | details
29 | ]
30 | })
31 | ```
32 |
33 | ## Settings
34 |
35 | ### HTMLAttributes
36 |
37 | Custom HTML attributes that should be added to the rendered HTML tag.
38 |
39 | ### detailSummaryOptions
40 |
41 | Options for detail summary extension.
42 |
43 | ### detailContentOptions
44 |
45 | Options for detail content extension.
46 |
47 | ## Commands
48 |
49 | ### insertDetails
50 |
51 | Insert a details in current pos.
52 |
--------------------------------------------------------------------------------
/docs/extensions/emoji.md:
--------------------------------------------------------------------------------
1 | # Emoji
2 |
3 | Emoji extension for tiptap
4 |
5 | ## Installation
6 |
7 | ::: code-group
8 |
9 | ```bash [npm]
10 | npm install @note-editor/tiptap-extension-emoji
11 | ```
12 |
13 | ```bash [pnpm]
14 | pnpm add @note-editor/tiptap-extension-emoji
15 | ```
16 |
17 | :::
18 |
19 | ## Usage
20 |
21 | ```ts
22 | import { Editor } from '@tiptap/core'
23 | import { emoji } from '@note-editor/tiptap-extension-emoji'
24 |
25 | const editor = new Editor({
26 | content: '@note-editor/tiptap-extension-emoji
',
27 | extensions: [
28 | emoji
29 | ]
30 | })
31 | ```
32 |
--------------------------------------------------------------------------------
/docs/extensions/unique-id.md:
--------------------------------------------------------------------------------
1 | # @note-editor/tiptap-extension-unique-id
2 |
3 | unique id extension for tiptap
4 |
5 | ## Installation
6 |
7 | ::: code-group
8 |
9 | ```bash [npm]
10 | npm install @note-editor/tiptap-extension-unique-id
11 | ```
12 |
13 | ```bash [pnpm]
14 | pnpm add @note-editor/tiptap-extension-unique-id
15 | ```
16 |
17 | :::
18 |
19 | ## Usage
20 |
21 | ```ts
22 | import { Editor } from '@tiptap/core'
23 | import { uniqueId } from '@note-editor/tiptap-extension-unique-id'
24 |
25 | const editor = new Editor({
26 | content: '@note-editor/tiptap-extension-unique-id
',
27 | extensions: [
28 | uniqueId
29 | ]
30 | })
31 | ```
32 |
33 | ## Settings
34 |
35 | ### attributeName
36 |
37 | Name of the attribute that is attached to the HTML tag (will be prefixed with **data-**).
38 |
39 | ```ts
40 | uniqueID.configure({
41 | attributeName: 'id' // default
42 | })
43 | ```
44 |
45 | ### types
46 |
47 | All types that should get a unique ID, for example ['paragraph']
48 |
49 | ```ts
50 | uniqueID.configure({
51 | types: ['blockContainer', 'paragraph', 'details', 'detailsSummary', 'detailsContent'] // default
52 | })
53 | ```
54 |
55 | ### generateID
56 |
57 | A function that generates and returns a unique ID.
58 |
59 | ```ts
60 | import { nanoid } from 'nanoid'
61 |
62 | uniqueID.configure({
63 | generateID: () => nanoid() // default
64 | })
65 | ```
66 |
--------------------------------------------------------------------------------
/docs/guide/vue.md:
--------------------------------------------------------------------------------
1 | # Starter for Vue
2 |
3 | The **VueKit** is a collection of [Tiptap](https://tiptap.dev/docs/editor/introduction) extensions with vue. If you’re just getting started, this extension is for you.
4 |
5 | ## Installation
6 |
7 | ::: code-group
8 |
9 | ```bash [npm]
10 | npm install @tiptap/vue-3 @note-editor/vue-kit
11 | ```
12 |
13 | ```bash [pnpm]
14 | pnpm add @tiptap/vue-3 @note-editor/vue-kit
15 | ```
16 |
17 | :::
18 |
19 | ## Export
20 |
21 | ### setupKit
22 |
23 | a collection of Tiptap extensions, similar to [StarterKit](https://tiptap.dev/docs/editor/api/extensions/starter-kit)
24 |
25 | ```ts
26 | import { Editor } from '@tiptap/core'
27 | import { setupKit } from '@note-editor/vue-kit'
28 |
29 | const editor = new Editor({
30 | extensions: [
31 | setupKit
32 | ]
33 | })
34 | ```
35 |
36 | ### useNoteEditor
37 |
38 | a vue composable for tiptap
39 |
40 | ```ts
41 | import { useNoteEditor } from '@note-editor/vue-kit'
42 | ```
43 |
44 | ## Usage
45 |
46 | ```vue
47 |
53 |
54 |
55 |
56 |
57 | ```
58 |
59 | You can configure the included extensions, or even disable a few of them, like shown below.
60 |
61 | ```vue
62 |
79 |
80 |
81 |
82 |
83 | ```
84 |
85 | ## Included extensions
86 |
87 | ### Nodes
88 |
89 | - [Blockquote](https://tiptap.dev/docs/editor/api/nodes/blockquote)
90 | - [BulletList](https://tiptap.dev/docs/editor/api/nodes/bullet-list)
91 | - [Document](https://tiptap.dev/docs/editor/api/nodes/document)
92 | - [HardBreak](https://tiptap.dev/docs/editor/api/nodes/hard-break)
93 | - [Heading](https://tiptap.dev/docs/editor/api/nodes/heading)
94 | - [HorizontalRule](https://tiptap.dev/docs/editor/api/nodes/horizontal-rule)
95 | - [ListItem](https://tiptap.dev/docs/editor/api/nodes/list-item)
96 | - [OrderedList](https://tiptap.dev/docs/editor/api/nodes/ordered-list)
97 | - [Paragraph](https://tiptap.dev/docs/editor/api/nodes/paragraph)
98 | - [Table](https://tiptap.dev/docs/editor/api/nodes/table)
99 | - [TableCell](https://tiptap.dev/docs/editor/api/nodes/table-cell)
100 | - [TableHeader](https://tiptap.dev/docs/editor/api/nodes/table-header)
101 | - [TableRow](https://tiptap.dev/docs/editor/api/nodes/table-row)
102 | - [TaskItem](https://tiptap.dev/docs/editor/api/nodes/task-item)
103 | - [TaskList](https://tiptap.dev/docs/editor/api/nodes/task-list)
104 | - [Text](https://tiptap.dev/docs/editor/api/nodes/text)
105 | - [Block Container](/extensions/block-container)
106 | - [Code Block Shiki](/extensions/code-block-shiki)
107 | - [Details](/extensions/details)
108 |
109 | ### Marks
110 |
111 | - [Bold](https://tiptap.dev/docs/editor/api/marks/bold)
112 | - [Code](https://tiptap.dev/docs/editor/api/marks/code)
113 | - [Highlight](https://tiptap.dev/docs/editor/api/marks/highlight)
114 | - [Italic](https://tiptap.dev/docs/editor/api/marks/italic)
115 | - [Strike](https://tiptap.dev/docs/editor/api/marks/strike)
116 | - [Subscript](https://tiptap.dev/docs/editor/api/marks/subscript)
117 | - [Superscript](https://tiptap.dev/docs/editor/api/marks/superscript)
118 | - [TextStyle](https://tiptap.dev/docs/editor/api/marks/text-style)
119 | - [Underline](https://tiptap.dev/docs/editor/api/marks/underline)
120 |
121 | ### Extensions
122 |
123 | - [CharacterCount](https://tiptap.dev/docs/editor/api/extensions/character-count)
124 | - [Color](https://tiptap.dev/docs/editor/api/extensions/color)
125 | - [Focus](https://tiptap.dev/docs/editor/api/extensions/focus)
126 | - [FontFamily](https://tiptap.dev/docs/editor/api/extensions/font-family)
127 | - [Gapcursor](https://tiptap.dev/docs/editor/api/extensions/dropcursor)
128 | - [History](https://tiptap.dev/docs/editor/api/extensions/history)
129 | - [Placeholder](https://tiptap.dev/docs/editor/api/extensions/placeholder)
130 | - [TextAlign](https://tiptap.dev/docs/editor/api/extensions/text-align)
131 | - [Typography](https://tiptap.dev/docs/editor/api/extensions/typography)
132 | - [Unique ID](/extensions/unique-id)
133 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: home
3 |
4 | hero:
5 | name: Note Editor
6 | text: Tiptap-based text editor
7 | actions:
8 | - theme: brand
9 | text: Best practice
10 | link: https://github.com/vueditor/rich-text-editor.git
11 | - theme: alt
12 | text: Guide
13 | link: /guide/vue
14 | - theme: alt
15 | text: Extensions
16 | link: /extensions/unique-id
17 |
18 | features:
19 | - title: Easy to integrate
20 | details: Nanny tutorial + Complete packaging chain
21 | - title: Easy to customize
22 | details: Based on Tiptap packaging, easy to expand
23 | ---
24 |
--------------------------------------------------------------------------------
/docs/playground.md:
--------------------------------------------------------------------------------
1 | # Playground
2 |
3 | Note Editor Playground for Vue
4 |
5 |
6 |
--------------------------------------------------------------------------------
/docs/zh-CN/changelog.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 |
4 |
--------------------------------------------------------------------------------
/docs/zh-CN/extensions/block-container.md:
--------------------------------------------------------------------------------
1 | # Block Container(块容器)
2 |
3 | 用于 Tiptap 的块容器插件
4 |
5 | ## 安装
6 |
7 | ::: code-group
8 |
9 | ```bash [npm]
10 | npm install @note-editor/tiptap-extension-block-container
11 | ```
12 |
13 | ```bash [pnpm]
14 | pnpm add @note-editor/tiptap-extension-block-container
15 | ```
16 |
17 | :::
18 |
19 | ## 用法
20 |
21 | ::: tip
22 | `@note-editor/tiptap-extension-block-container` 已经被 [`@note-editor/vue-kit`](/guide/vue) 收集在内, 所以通常来说不需要单独安装
23 | :::
24 |
25 | ::: danger
26 | `@tiptap/extension-document` 被拓展以实现顶级的块容器,所以请注意新旧数据结构的兼容处理。 如果你想了解更多, 请查看 [源码](https://github.com/liting-yes/note-editor/blob/main/packages/tiptap-extension-block-container/src/extentDocument.ts).
27 | :::
28 |
29 | ```ts
30 | import { Editor } from '@tiptap/core'
31 | import { blockContainer } from '@note-editor/tiptap-extension-block-container'
32 |
33 | const editor = new Editor({
34 | content: '@note-editor/tiptap-extension-unique-id
',
35 | extensions: [
36 | blockContainer
37 | ]
38 | })
39 | ```
40 |
--------------------------------------------------------------------------------
/docs/zh-CN/extensions/code-block-shiki.md:
--------------------------------------------------------------------------------
1 | # Code Block Shiki
2 |
3 | 基于 Shiki 进行代码高亮的代码块插件
4 |
5 | ::: warning
6 | 此插件会覆盖掉 [Code block](https://tiptap.dev/docs/editor/api/nodes/code-block)
7 | :::
8 |
9 | ## 安装
10 |
11 | ::: code-group
12 |
13 | ```bash [npm]
14 | npm install @note-editor/tiptap-extension-code-block-shiki
15 | ```
16 |
17 | ```bash [pnpm]
18 | pnpm add @note-editor/tiptap-extension-code-block-shiki
19 | ```
20 |
21 | :::
22 |
23 | ## 用法
24 |
25 | ```ts
26 | import { Editor } from '@tiptap/core'
27 | import { codeBlockShiki } from '@note-editor/tiptap-extension-code-block-shiki'
28 |
29 | const editor = new Editor({
30 | content: '@note-editor/tiptap-extension-code-block-shiki
',
31 | extensions: [
32 | codeBlockShiki
33 | ]
34 | })
35 | ```
36 |
37 | ## 设置
38 |
39 | ### theme
40 |
41 | 高亮主题, 想查看更多请跳转 [shiki themes](https://shiki.style/themes)
42 |
43 | ```ts
44 | codeBlockShiki.configure({
45 | theme: 'vitesse-light' // default
46 | })
47 | ```
48 |
--------------------------------------------------------------------------------
/docs/zh-CN/extensions/details.md:
--------------------------------------------------------------------------------
1 | # Details
2 |
3 | 用于 Tiptap 的 details 插件
4 |
5 | ## 安装
6 |
7 | ::: code-group
8 |
9 | ```bash [npm]
10 | npm install @note-editor/tiptap-extension-details
11 | ```
12 |
13 | ```bash [pnpm]
14 | pnpm add @note-editor/tiptap-extension-details
15 | ```
16 |
17 | :::
18 |
19 | ## 用法
20 |
21 | ```ts
22 | import { Editor } from '@tiptap/core'
23 | import { details } from '@note-editor/tiptap-extension-details'
24 |
25 | const editor = new Editor({
26 | content: '@note-editor/tiptap-extension-details
',
27 | extensions: [
28 | details
29 | ]
30 | })
31 | ```
32 |
33 | ## 设置
34 |
35 | ### HTMLAttributes
36 |
37 | 将渲染到对应 HTMl 标签上的自定义属性
38 |
39 | ### detailSummaryOptions
40 |
41 | **detail summary extension** 的配置项
42 |
43 | ### detailContentOptions
44 |
45 | **detail content extension** 的配置项
46 |
47 | ## 命令行
48 |
49 | ### insertDetails
50 |
51 | 在当前位置插入一个 details
52 |
--------------------------------------------------------------------------------
/docs/zh-CN/extensions/emoji.md:
--------------------------------------------------------------------------------
1 | # Emoji
2 |
3 | 基于 tiptap 的 emoji 插件
4 |
5 | ## 安装
6 |
7 | ::: code-group
8 |
9 | ```bash [npm]
10 | npm install @note-editor/tiptap-extension-emoji
11 | ```
12 |
13 | ```bash [pnpm]
14 | pnpm add @note-editor/tiptap-extension-emoji
15 | ```
16 |
17 | :::
18 |
19 | ## 用法
20 |
21 | ```ts
22 | import { Editor } from '@tiptap/core'
23 | import { emoji } from '@note-editor/tiptap-extension-emoji'
24 |
25 | const editor = new Editor({
26 | content: '@note-editor/tiptap-extension-emoji
',
27 | extensions: [
28 | emoji
29 | ]
30 | })
31 | ```
32 |
--------------------------------------------------------------------------------
/docs/zh-CN/extensions/unique-id.md:
--------------------------------------------------------------------------------
1 | # @note-editor/tiptap-extension-unique-id
2 |
3 | 用于 Tiptap 的注入唯一 ID 的插件
4 |
5 | ## 安装
6 |
7 | ::: code-group
8 |
9 | ```bash [npm]
10 | npm install @note-editor/tiptap-extension-unique-id
11 | ```
12 |
13 | ```bash [pnpm]
14 | pnpm add @note-editor/tiptap-extension-unique-id
15 | ```
16 |
17 | :::
18 |
19 | ## 用法
20 |
21 | ```ts
22 | import { Editor } from '@tiptap/core'
23 | import { uniqueId } from '@note-editor/tiptap-extension-unique-id'
24 |
25 | const editor = new Editor({
26 | content: '@note-editor/tiptap-extension-unique-id
',
27 | extensions: [
28 | uniqueId
29 | ]
30 | })
31 | ```
32 |
33 | ## 设置
34 |
35 | ### attributeName
36 |
37 | 附加到 HTML 标签上的属性名 (自动添加 **data-** 前缀).
38 |
39 | ```ts
40 | uniqueID.configure({
41 | attributeName: 'id' // default
42 | })
43 | ```
44 |
45 | ### types
46 |
47 | 穷举需要注入 Unique ID 的节点类型, 比如 ['paragraph']
48 |
49 | ```ts
50 | uniqueID.configure({
51 | types: ['blockContainer', 'paragraph', 'details', 'detailsSummary', 'detailsContent'] // default
52 | })
53 | ```
54 |
55 | ### generateID
56 |
57 | 一个生成并返回唯一 ID 的函数
58 |
59 | ```ts
60 | import { nanoid } from 'nanoid'
61 |
62 | uniqueID.configure({
63 | generateID: () => nanoid() // default
64 | })
65 | ```
66 |
--------------------------------------------------------------------------------
/docs/zh-CN/guide/vue.md:
--------------------------------------------------------------------------------
1 | # Vue 指南
2 |
3 | **VueKit** 是一个 [Tiptap](https://tiptap.dev/docs/editor/introduction) 插件集。如果你是刚起步,这个插件正合适
4 |
5 | ## 安装
6 |
7 | ::: code-group
8 |
9 | ```bash [npm]
10 | npm install @tiptap/vue-3 @note-editor/vue-kit
11 | ```
12 |
13 | ```bash [pnpm]
14 | pnpm add @tiptap/vue-3 @note-editor/vue-kit
15 | ```
16 |
17 | :::
18 |
19 | ## 导出
20 |
21 | ### setupKit
22 |
23 | 一个 Tiptap 插件集,类似于 [StarterKit](https://tiptap.dev/docs/editor/api/extensions/starter-kit)
24 |
25 | ```ts
26 | import { Editor } from '@tiptap/core'
27 | import { setupKit } from '@note-editor/vue-kit'
28 |
29 | const editor = new Editor({
30 | extensions: [
31 | setupKit
32 | ]
33 | })
34 | ```
35 |
36 | ### useNoteEditor
37 |
38 | 一个用于 Tiptap 的 Vue 组合式函数
39 |
40 | ```ts
41 | import { useNoteEditor } from '@note-editor/vue-kit'
42 | ```
43 |
44 | ## 用法
45 |
46 | ```vue
47 |
53 |
54 |
55 |
56 |
57 | ```
58 |
59 | 对于涵盖的插件,你既可以设置其配置项,也可以禁用它。示例如下:
60 |
61 | ```vue
62 |
79 |
80 |
81 |
82 |
83 | ```
84 |
85 | ## 涵盖的插件列表
86 |
87 | ### Nodes
88 |
89 | - [Blockquote](https://tiptap.dev/docs/editor/api/nodes/blockquote)
90 | - [BulletList](https://tiptap.dev/docs/editor/api/nodes/bullet-list)
91 | - [Document](https://tiptap.dev/docs/editor/api/nodes/document)
92 | - [HardBreak](https://tiptap.dev/docs/editor/api/nodes/hard-break)
93 | - [Heading](https://tiptap.dev/docs/editor/api/nodes/heading)
94 | - [HorizontalRule](https://tiptap.dev/docs/editor/api/nodes/horizontal-rule)
95 | - [ListItem](https://tiptap.dev/docs/editor/api/nodes/list-item)
96 | - [OrderedList](https://tiptap.dev/docs/editor/api/nodes/ordered-list)
97 | - [Paragraph](https://tiptap.dev/docs/editor/api/nodes/paragraph)
98 | - [Table](https://tiptap.dev/docs/editor/api/nodes/table)
99 | - [TableCell](https://tiptap.dev/docs/editor/api/nodes/table-cell)
100 | - [TableHeader](https://tiptap.dev/docs/editor/api/nodes/table-header)
101 | - [TableRow](https://tiptap.dev/docs/editor/api/nodes/table-row)
102 | - [TaskItem](https://tiptap.dev/docs/editor/api/nodes/task-item)
103 | - [TaskList](https://tiptap.dev/docs/editor/api/nodes/task-list)
104 | - [Text](https://tiptap.dev/docs/editor/api/nodes/text)
105 | - [Block Container](/zh-CN/extensions/block-container)
106 | - [Code Block Shiki](/zh-CN/extensions/code-block-shiki)
107 | - [Details](/zh-CN/extensions/details)
108 |
109 | ### Marks
110 |
111 | - [Bold](https://tiptap.dev/docs/editor/api/marks/bold)
112 | - [Code](https://tiptap.dev/docs/editor/api/marks/code)
113 | - [Highlight](https://tiptap.dev/docs/editor/api/marks/highlight)
114 | - [Italic](https://tiptap.dev/docs/editor/api/marks/italic)
115 | - [Strike](https://tiptap.dev/docs/editor/api/marks/strike)
116 | - [Subscript](https://tiptap.dev/docs/editor/api/marks/subscript)
117 | - [Superscript](https://tiptap.dev/docs/editor/api/marks/superscript)
118 | - [TextStyle](https://tiptap.dev/docs/editor/api/marks/text-style)
119 | - [Underline](https://tiptap.dev/docs/editor/api/marks/underline)
120 |
121 | ### Extensions
122 |
123 | - [CharacterCount](https://tiptap.dev/docs/editor/api/extensions/character-count)
124 | - [Color](https://tiptap.dev/docs/editor/api/extensions/color)
125 | - [Focus](https://tiptap.dev/docs/editor/api/extensions/focus)
126 | - [FontFamily](https://tiptap.dev/docs/editor/api/extensions/font-family)
127 | - [Gapcursor](https://tiptap.dev/docs/editor/api/extensions/dropcursor)
128 | - [History](https://tiptap.dev/docs/editor/api/extensions/history)
129 | - [Placeholder](https://tiptap.dev/docs/editor/api/extensions/placeholder)
130 | - [TextAlign](https://tiptap.dev/docs/editor/api/extensions/text-align)
131 | - [Typography](https://tiptap.dev/docs/editor/api/extensions/typography)
132 | - [Unique ID](/zh-CN/extensions/unique-id)
133 |
--------------------------------------------------------------------------------
/docs/zh-CN/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: home
3 |
4 | hero:
5 | name: Note Editor
6 | text: 基于 Tiptap 的文本编辑器
7 | actions:
8 | - theme: brand
9 | text: 最佳实践
10 | link: https://github.com/vueditor/rich-text-editor.git
11 | - theme: alt
12 | text: 指南
13 | link: /zh-CN/guide/vue
14 | - theme: alt
15 | text: 插件
16 | link: /zh-CN/extensions/unique-id
17 |
18 | features:
19 | - title: 集成简单
20 | details: 保姆式教程 + 完整的封装链
21 | - title: 易于自定义
22 | details: 基于 Tiptap 封装,拓展难度低
23 | ---
24 |
--------------------------------------------------------------------------------
/docs/zh-CN/playground.md:
--------------------------------------------------------------------------------
1 | # 演练场
2 |
3 | Note Editor 在 Vue 中的演练
4 |
5 |
6 |
--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
1 | import antfu from '@antfu/eslint-config'
2 |
3 | export default antfu({
4 | vue: true,
5 | typescript: true,
6 | react: true,
7 | formatters: {
8 | css: true,
9 | html: true,
10 | markdown: true,
11 | },
12 | })
13 |
--------------------------------------------------------------------------------
/migrations.json:
--------------------------------------------------------------------------------
1 | {
2 | "migrations": [
3 | {
4 | "version": "18.1.0-beta.3",
5 | "description": "Moves affected.defaultBase to defaultBase in `nx.json`",
6 | "implementation": "./src/migrations/update-17-2-0/move-default-base",
7 | "package": "nx",
8 | "name": "move-default-base-to-nx-json-root"
9 | },
10 | {
11 | "cli": "nx",
12 | "version": "19.2.0-beta.2",
13 | "description": "Updates the default workspace data directory to .nx/workspace-data",
14 | "implementation": "./src/migrations/update-19-2-0/move-workspace-data-directory",
15 | "package": "nx",
16 | "name": "19-2-0-move-graph-cache-directory"
17 | },
18 | {
19 | "cli": "nx",
20 | "version": "19.2.2-beta.0",
21 | "description": "Updates the nx wrapper.",
22 | "implementation": "./src/migrations/update-17-3-0/update-nxw",
23 | "package": "nx",
24 | "name": "19-2-2-update-nx-wrapper"
25 | },
26 | {
27 | "version": "19.2.4-beta.0",
28 | "description": "Set project name in nx.json explicitly",
29 | "implementation": "./src/migrations/update-19-2-4/set-project-name",
30 | "x-repair-skip": true,
31 | "package": "nx",
32 | "name": "19-2-4-set-project-name"
33 | },
34 | {
35 | "version": "19.6.0-beta.0",
36 | "description": "Add dependsOn: [build] to preview targets using preview-server",
37 | "implementation": "./src/migrations/update-19-6-0/add-depends-on-for-preview",
38 | "package": "@nx/vite",
39 | "name": "update-19-6-0-add-depends-on-for-preview-server"
40 | }
41 | ]
42 | }
43 |
--------------------------------------------------------------------------------
/nx.json:
--------------------------------------------------------------------------------
1 | {
2 | "pluginsConfig": {
3 | "@nx/js": {
4 | "analyzeSourceFiles": true
5 | }
6 | },
7 | "extends": "nx/presets/npm.json",
8 | "$schema": "./node_modules/nx/schemas/nx-schema.json",
9 | "plugins": [
10 | {
11 | "plugin": "@nx/eslint/plugin",
12 | "options": {
13 | "targetName": "lint"
14 | }
15 | },
16 | {
17 | "plugin": "@nx/vite/plugin",
18 | "options": {
19 | "buildTargetName": "build",
20 | "previewTargetName": "preview",
21 | "testTargetName": "test",
22 | "serveTargetName": "serve",
23 | "serveStaticTargetName": "serve-static"
24 | }
25 | }
26 | ],
27 | "targetDefaults": {
28 | "@nx/rollup:rollup": {
29 | "cache": true,
30 | "dependsOn": ["^build"],
31 | "inputs": ["default", "^default"]
32 | },
33 | "@nx/vite:build": {
34 | "cache": true,
35 | "dependsOn": ["^build"],
36 | "inputs": ["default", "^default"]
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "note-editor",
3 | "type": "module",
4 | "private": true,
5 | "license": "MIT",
6 | "scripts": {
7 | "prepare": "husky",
8 | "lint": "eslint .",
9 | "lint:fix": "eslint . --fix",
10 | "docs:dev": "vitepress dev docs",
11 | "docs:build": "vitepress build docs",
12 | "docs:preview": "vitepress preview docs",
13 | "commit": "git-cz"
14 | },
15 | "dependencies": {
16 | "@note-editor/vue-kit": "workspace:*",
17 | "vue": "^3.4.21"
18 | },
19 | "devDependencies": {
20 | "@antfu/eslint-config": "^2.6.4",
21 | "@commitlint/cli": "^19.0.3",
22 | "@commitlint/config-conventional": "^19.0.3",
23 | "@commitlint/cz-commitlint": "^19.2.0",
24 | "@nx/eslint": "19.6.3",
25 | "@nx/js": "19.6.3",
26 | "@nx/rollup": "19.6.3",
27 | "@nx/vite": "19.6.3",
28 | "@nx/vue": "19.6.3",
29 | "@nx/web": "19.6.3",
30 | "@swc-node/register": "1.9.2",
31 | "@swc/cli": "0.3.14",
32 | "@swc/core": "1.5.7",
33 | "@swc/helpers": "0.5.12",
34 | "@types/node": "18.16.9",
35 | "@vitejs/plugin-vue": "^4.5.0",
36 | "@vitest/ui": "1.6.0",
37 | "@vue/test-utils": "^2.4.1",
38 | "commitizen": "^4.3.0",
39 | "eslint": "8.57.0",
40 | "eslint-plugin-format": "^0.1.0",
41 | "eslint-plugin-react": "^7.33.2",
42 | "eslint-plugin-react-hooks": "^4.6.0",
43 | "eslint-plugin-react-refresh": "^0.4.5",
44 | "husky": "^9.0.11",
45 | "inquirer": "9",
46 | "jsdom": "~22.1.0",
47 | "lint-staged": "^15.2.2",
48 | "nx": "19.6.3",
49 | "prettier": "^2.6.2",
50 | "sass": "1.62.1",
51 | "tslib": "^2.6.2",
52 | "typescript": "5.5.4",
53 | "vite": "~5.0.0",
54 | "vite-plugin-dts": "~2.3.0",
55 | "vitepress": "^1.0.1",
56 | "vitest": "1.6.0",
57 | "vue-tsc": "2.0.7"
58 | },
59 | "lint-staged": {
60 | "*": "eslint --fix"
61 | },
62 | "config": {
63 | "commitizen": {
64 | "path": "@commitlint/cz-commitlint"
65 | }
66 | },
67 | "commitlint": {
68 | "extends": [
69 | "@commitlint/config-conventional"
70 | ]
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-block-container/README.md:
--------------------------------------------------------------------------------
1 | # tiptap-extension-block-container
2 |
3 | block container extension for tiptap
4 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-block-container/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@note-editor/tiptap-extension-block-container",
3 | "type": "module",
4 | "version": "0.3.1",
5 | "description": "block container extension for tiptap",
6 | "license": "MIT",
7 | "homepage": "https://note-editor.liting.ink/",
8 | "repository": {
9 | "type": "git",
10 | "url": "https://github.com/liting-yes/note-editor.git",
11 | "directory": "packages/tiptap-extension-block-container"
12 | },
13 | "keywords": [
14 | "tiptap",
15 | "tiptap extension"
16 | ],
17 | "exports": {
18 | ".": {
19 | "types": "./dist/index.d.ts",
20 | "import": "./dist/index.js",
21 | "require": "./dist/index.cjs"
22 | }
23 | },
24 | "main": "./dist/index.cjs",
25 | "module": "./dist/index.js",
26 | "types": "./dist/index.d.ts",
27 | "files": [
28 | "dist"
29 | ],
30 | "publishConfig": {
31 | "access": "public",
32 | "registry": "https://registry.npmjs.org"
33 | },
34 | "peerDependencies": {
35 | "@tiptap/core": "^2.2",
36 | "@tiptap/pm": "^2.2"
37 | },
38 | "devDependencies": {
39 | "@tiptap/core": "^2.2.4",
40 | "@tiptap/extension-document": "^2.2.4",
41 | "@tiptap/pm": "^2.2.4"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-block-container/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tiptap-extension-block-container",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/tiptap-extension-block-container/src",
5 | "projectType": "library",
6 | "targets": {
7 | "build": {
8 | "executor": "@nx/vite:build",
9 | "outputs": ["{options.outputPath}"],
10 | "options": {
11 | "outputPath": "packages/tiptap-extension-block-container/dist",
12 | "main": "packages/tiptap-extension-block-container/src/index.ts",
13 | "tsConfig": "packages/tiptap-extension-block-container/tsconfig.lib.json",
14 | "assets": ["packages/tiptap-extension-block-container/*.md"]
15 | }
16 | }
17 | },
18 | "tags": []
19 | }
20 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-block-container/src/blockContainer.css:
--------------------------------------------------------------------------------
1 | .ProseMirror.tiptap {
2 | padding-left: 0;
3 | padding-right: 32px;
4 | }
5 |
6 | .note-editor__block-container {
7 | position: relative;
8 | padding-left: 32px;
9 | }
10 |
11 | .note-editor__block-container:hover .note-editor__block-container__drag-bar {
12 | display: block;
13 | }
14 |
15 | .note-editor__block-container:hover .note-editor__block-container__content {
16 | background-color: #f1f5f9;
17 | }
18 |
19 | .note-editor__block-container__drag-bar {
20 | display: none;
21 | position: absolute;
22 | left: 4px;
23 | top: 0;
24 | width: 24px;
25 | height: 24px;
26 | cursor: grab;
27 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16px' height='16px' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M9 20q-.825 0-1.412-.587T7 18q0-.825.588-1.412T9 16q.825 0 1.413.588T11 18q0 .825-.587 1.413T9 20m6 0q-.825 0-1.412-.587T13 18q0-.825.588-1.412T15 16q.825 0 1.413.588T17 18q0 .825-.587 1.413T15 20m-6-6q-.825 0-1.412-.587T7 12q0-.825.588-1.412T9 10q.825 0 1.413.588T11 12q0 .825-.587 1.413T9 14m6 0q-.825 0-1.412-.587T13 12q0-.825.588-1.412T15 10q.825 0 1.413.588T17 12q0 .825-.587 1.413T15 14M9 8q-.825 0-1.412-.587T7 6q0-.825.588-1.412T9 4q.825 0 1.413.588T11 6q0 .825-.587 1.413T9 8m6 0q-.825 0-1.412-.587T13 6q0-.825.588-1.412T15 4q.825 0 1.413.588T17 6q0 .825-.587 1.413T15 8'/%3E%3C/svg%3E");
28 | background-position: center;
29 | background-repeat: no-repeat;
30 | }
31 |
32 | .note-editor__block-container__content {
33 | padding: 0 4px;
34 | }
35 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-block-container/src/blockContainer.ts:
--------------------------------------------------------------------------------
1 | import { Node, createStyleTag, mergeAttributes } from '@tiptap/core'
2 | import { Fragment, Slice } from '@tiptap/pm/model'
3 | import { TextSelection } from '@tiptap/pm/state'
4 | import document from './extentDocument'
5 | import style from './blockContainer.css?raw'
6 |
7 | export interface BlockContainerOptions {
8 | HTMLAttributes: Record
9 | }
10 |
11 | declare module '@tiptap/core' {
12 | interface Commands {
13 | blockContainer: {
14 | splitBlockContainer: () => ReturnType
15 | }
16 | }
17 | }
18 |
19 | export const blockContainer = Node.create({
20 | name: 'blockContainer',
21 | content: 'block',
22 | group: 'block top',
23 | draggable: true,
24 | defining: true,
25 | addOptions() {
26 | return {
27 | HTMLAttributes: {},
28 | }
29 | },
30 | parseHTML() {
31 | return [
32 | {
33 | tag: 'div.note-editor__block-container',
34 | },
35 | ]
36 | },
37 | renderHTML({ HTMLAttributes }) {
38 | return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]
39 | },
40 | addExtensions() {
41 | return [document]
42 | },
43 | addCommands() {
44 | return {
45 | splitBlockContainer: () => ({ state: { selection, doc, schema, tr }, dispatch }) => {
46 | if (!dispatch)
47 | return false
48 |
49 | const startPos = selection.from
50 | const resolved = doc.resolve(startPos)
51 | const endPos = resolved.end(resolved.depth)
52 | const newBlockContent = tr.doc.cut(startPos, endPos)
53 | const newBlock = schema.nodes[this.name].createAndFill()!
54 |
55 | tr.replace(endPos + 1, endPos + 2, newBlockContent.content.size > 0 ? new Slice(Fragment.from(newBlockContent), 0, 0) : new Slice(Fragment.from(newBlock), 0, 0))
56 | tr.setSelection(new TextSelection(tr.doc.resolve(endPos + 1)))
57 | tr.delete(startPos, endPos)
58 |
59 | return dispatch(tr)
60 | },
61 | }
62 | },
63 | addKeyboardShortcuts() {
64 | const handleEnter = () => this.editor.commands.first(({ commands }) => {
65 | return [
66 | () => commands.newlineInCode(),
67 | () => commands.splitBlockContainer(),
68 | ]
69 | })
70 |
71 | return {
72 | Enter: handleEnter,
73 | }
74 | },
75 | addNodeView() {
76 | return ({ HTMLAttributes }) => {
77 | const dom = window.document.createElement('div')
78 | dom.classList.add('note-editor__block-container')
79 | Object.keys(HTMLAttributes).forEach((key) => {
80 | dom.setAttribute(key, HTMLAttributes[key])
81 | })
82 |
83 | const dragBar = window.document.createElement('div')
84 | dragBar.classList.add('note-editor__block-container__drag-bar')
85 |
86 | const content = window.document.createElement('div')
87 | content.classList.add('note-editor__block-container__content')
88 |
89 | createStyleTag(style, undefined, 'block-container')
90 |
91 | dom.append(dragBar, content)
92 |
93 | return {
94 | dom,
95 | contentDOM: content,
96 | }
97 | }
98 | },
99 | })
100 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-block-container/src/extentDocument.ts:
--------------------------------------------------------------------------------
1 | import { Document } from '@tiptap/extension-document'
2 |
3 | export default Document.extend({
4 | content: 'top+',
5 | })
6 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-block-container/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './blockContainer'
2 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-block-container/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "strict": true,
6 | "noFallthroughCasesInSwitch": true,
7 | "noImplicitOverride": true,
8 | "noImplicitReturns": true,
9 | "noPropertyAccessFromIndexSignature": true,
10 | "forceConsistentCasingInFileNames": true
11 | },
12 | "references": [
13 | {
14 | "path": "./tsconfig.lib.json"
15 | }
16 | ],
17 | "files": [],
18 | "include": []
19 | }
20 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-block-container/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "types": ["node", "vite/client"],
5 | "declaration": true,
6 | "outDir": "../../dist/out-tsc"
7 | },
8 | "include": ["src/**/*.ts"],
9 | "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-block-container/vite.config.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import * as path from 'node:path'
3 | import { defineConfig } from 'vite'
4 | import dts from 'vite-plugin-dts'
5 | import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'
6 |
7 | export default defineConfig({
8 | root: __dirname,
9 | cacheDir: '../../node_modules/.vite/packages/tiptap-extension-block-container',
10 |
11 | plugins: [
12 | nxViteTsPaths(),
13 | dts({
14 | entryRoot: 'src',
15 | tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'),
16 | skipDiagnostics: true,
17 | }),
18 | ],
19 |
20 | // Uncomment this if you are using workers.
21 | // worker: {
22 | // plugins: [ nxViteTsPaths() ],
23 | // },
24 |
25 | // Configuration for building your library.
26 | // See: https://vitejs.dev/guide/build.html#library-mode
27 | build: {
28 | outDir: 'dist',
29 | reportCompressedSize: true,
30 | commonjsOptions: {
31 | transformMixedEsModules: true,
32 | },
33 | lib: {
34 | // Could also be a dictionary or array of multiple entry points.
35 | entry: 'src/index.ts',
36 | name: 'tiptap-extension-block-container',
37 | fileName: 'index',
38 | // Change this to the formats you want to support.
39 | // Don't forget to update your package.json as well.
40 | formats: ['es', 'cjs'],
41 | },
42 | rollupOptions: {
43 | // External packages that should not be bundled into your library.
44 | external: [/^@tiptap\//],
45 | },
46 | },
47 | })
48 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-code-block-shiki/README.md:
--------------------------------------------------------------------------------
1 | # tiptap-extension-code-block-shiki
2 |
3 | code block extension for tiptap
4 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-code-block-shiki/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@note-editor/tiptap-extension-code-block-shiki",
3 | "type": "module",
4 | "version": "0.3.1",
5 | "description": "code block extension with shiki for tiptap",
6 | "license": "MIT",
7 | "homepage": "https://note-editor.liting.ink/",
8 | "repository": {
9 | "type": "git",
10 | "url": "https://github.com/liting-yes/note-editor.git",
11 | "directory": "packages/tiptap-extension-code-block-shiki"
12 | },
13 | "keywords": [
14 | "tiptap",
15 | "tiptap extension",
16 | "shiki",
17 | "code block"
18 | ],
19 | "exports": {
20 | ".": {
21 | "types": "./dist/index.d.ts",
22 | "import": "./dist/index.js",
23 | "require": "./dist/index.cjs"
24 | }
25 | },
26 | "main": "./dist/index.cjs",
27 | "module": "./dist/index.js",
28 | "types": "./dist/index.d.ts",
29 | "files": [
30 | "dist"
31 | ],
32 | "publishConfig": {
33 | "access": "public",
34 | "registry": "https://registry.npmjs.org"
35 | },
36 | "dependencies": {
37 | "@tiptap/core": "^2.2.4",
38 | "@tiptap/extension-code-block": "^2.2.4",
39 | "@tiptap/pm": "^2.2.4",
40 | "shiki": "^1.2.0"
41 | },
42 | "devDependencies": {
43 | "@types/hast": "^3.0.4",
44 | "hast": "^1.0.0"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-code-block-shiki/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tiptap-extension-code-block-shiki",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/tiptap-extension-code-block-shiki/src",
5 | "projectType": "library",
6 | "targets": {
7 | "build": {
8 | "executor": "@nx/vite:build",
9 | "outputs": ["{options.outputPath}"],
10 | "options": {
11 | "outputPath": "packages/tiptap-extension-code-block-shiki/dist",
12 | "main": "packages/tiptap-extension-code-block-shiki/src/index.ts",
13 | "tsConfig": "packages/tiptap-extension-code-block-shiki/tsconfig.lib.json",
14 | "assets": ["packages/tiptap-extension-code-block-shiki/*.md"]
15 | }
16 | }
17 | },
18 | "tags": []
19 | }
20 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-code-block-shiki/src/codeBlockShiki.css:
--------------------------------------------------------------------------------
1 | .node-editor__code-block-shiki {
2 | position: relative;
3 | border-radius: 8px;
4 | padding: 4px 8px;
5 | }
6 |
7 | .note-editor__code-block-shiki__lang-tag {
8 | position: absolute;
9 | top: 4px;
10 | right: 4px;
11 | font-size: 12px;
12 | line-height: 16px;
13 | padding: 2px 4px;
14 | border-radius: 4px;
15 | }
16 |
17 | .note-editor__code-block-shiki__select-lang {
18 | position: absolute;
19 | top: 4px;
20 | right: 4px;
21 | font-size: 12px;
22 | line-height: 16px;
23 | cursor: pointer;
24 | padding: 2px 4px;
25 | border-radius: 4px;
26 | border: 1px solid #f1f5f9;
27 | }
28 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-code-block-shiki/src/codeBlockShiki.ts:
--------------------------------------------------------------------------------
1 | import type { CodeBlockOptions } from '@tiptap/extension-code-block'
2 | import { CodeBlock } from '@tiptap/extension-code-block'
3 | import type { Node as ProsemirrorNode } from '@tiptap/pm/model'
4 | import { Plugin, PluginKey } from '@tiptap/pm/state'
5 | import type { DecorationAttrs } from '@tiptap/pm/view'
6 | import { Decoration, DecorationSet } from '@tiptap/pm/view'
7 | import { createStyleTag, findChildren } from '@tiptap/core'
8 | import type { BundledLanguage, BundledTheme, HighlighterGeneric, StringLiteralUnion } from 'shiki/bundle/web'
9 | import { bundledLanguagesInfo, getHighlighter } from 'shiki/bundle/web'
10 | import type { Element } from 'hast'
11 | import style from './codeBlockShiki.css?raw'
12 |
13 | export interface CodeBlockShikiOptions extends CodeBlockOptions {
14 | theme: StringLiteralUnion
15 | }
16 |
17 | export interface CodeBlockShikiStorage {
18 | highlighter: HighlighterGeneric | null
19 | }
20 |
21 | export const codeBlockShiki = CodeBlock.extend({
22 | addOptions() {
23 | return {
24 | ...this.parent?.(),
25 | theme: 'vitesse-light',
26 | }
27 | },
28 | addStorage() {
29 | return {
30 | highlighter: null,
31 | }
32 | },
33 | async onBeforeCreate() {
34 | createStyleTag(style, undefined, 'code-block-shiki')
35 | this.storage.highlighter = await getHighlighter({
36 | themes: [this.options.theme],
37 | langs: bundledLanguagesInfo.map(item => item.id),
38 | })
39 | },
40 | addProseMirrorPlugins() {
41 | return [
42 | ...(this.parent?.() ?? []),
43 | new Plugin({
44 | key: new PluginKey(this.name),
45 | state: {
46 | init: (_, { doc }) => {
47 | return getDecorations({ doc, name: this.name, highlighter: this.storage.highlighter, theme: this.options.theme })
48 | },
49 | apply: (transaction, decorationSet, oldState, newState) => {
50 | const oldNodeName = oldState.selection.$head.parent.type.name
51 | const newNodeName = newState.selection.$head.parent.type.name
52 |
53 | if (
54 | transaction.docChanged
55 | && ([oldNodeName, newNodeName].includes(this.name)
56 | // only toggle language for code block
57 | // @ts-expect-error attr
58 | || transaction.steps.find(item => item.attr === 'language')
59 | )
60 | ) {
61 | return getDecorations({
62 | doc: transaction.doc,
63 | name: this.name,
64 | highlighter: this.storage.highlighter,
65 | theme: this.options.theme,
66 | })
67 | }
68 |
69 | return decorationSet.map(transaction.mapping, transaction.doc)
70 | },
71 | },
72 | props: {
73 | decorations(state) {
74 | return this.getState(state)
75 | },
76 | },
77 | }),
78 | ]
79 | },
80 | addNodeView() {
81 | return ({ editor, node, getPos, HTMLAttributes }) => {
82 | const dom = window.document.createElement('pre')
83 | dom.classList.add('note-editor__code-block-shiki')
84 | Object.keys(HTMLAttributes).forEach((key) => {
85 | dom.setAttribute(key, HTMLAttributes[key])
86 | })
87 |
88 | const content = window.document.createElement('code')
89 | // @ts-expect-error language
90 | const langClass = this.options.languageClassPrefix + node.attrs.language
91 | content.classList.add(langClass)
92 | dom.append(content)
93 |
94 | if (this.editor.isEditable) {
95 | const selectLang = window.document.createElement('select')
96 | selectLang.classList.add('note-editor__code-block-shiki__select-lang')
97 | selectLang.addEventListener('change', (event) => {
98 | // @ts-expect-error value
99 | const lang = event.target.value
100 | editor.commands.command(({ tr }) => {
101 | const pos = (getPos as () => number)()
102 | tr.setNodeAttribute(pos, 'language', lang)
103 |
104 | return true
105 | })
106 | })
107 | const options = bundledLanguagesInfo.map((item) => {
108 | const option = document.createElement('option')
109 | option.setAttribute('value', item.id)
110 | // @ts-expect-error language
111 | if (node.attrs.language === item.id || node.attrs.language === item.name || item.aliases?.includes(node.attrs.language))
112 | option.setAttribute('selected', '')
113 |
114 | option.textContent = item.id
115 | return option
116 | })
117 | selectLang.append(...options)
118 | dom.append(selectLang)
119 | }
120 | else {
121 | const langTag = window.document.createElement('div')
122 | langTag.classList.add('note-editor__code-block-shiki__lang-tag')
123 | // @ts-expect-error language
124 | langTag.textContent = node.attrs.language ?? 'text'
125 | dom.append(langTag)
126 | }
127 |
128 | return {
129 | dom,
130 | contentDOM: content,
131 | }
132 | }
133 | },
134 | })
135 |
136 | function formatLanguage(lang: string) {
137 | if (!lang)
138 | return null
139 |
140 | return bundledLanguagesInfo.find(item => [item.id, item.name, ...(item.aliases ?? [])])?.id
141 | }
142 |
143 | function getDecorations({
144 | doc,
145 | name,
146 | highlighter,
147 | theme,
148 | }: {
149 | doc: ProsemirrorNode
150 | name: string
151 | highlighter: CodeBlockShikiStorage['highlighter']
152 | theme: CodeBlockShikiOptions['theme']
153 | }) {
154 | let decorations: Decoration[] = []
155 | if (!highlighter)
156 | return DecorationSet.create(doc, decorations)
157 |
158 | findChildren(doc, node => node.type.name === name).forEach((block) => {
159 | // @ts-expect-error language
160 | block.node.attrs.language = formatLanguage(block.node.attrs.language) ?? 'text'
161 |
162 | const preNode = highlighter!.codeToHast(block.node.textContent, {
163 | theme,
164 | // @ts-expect-error language
165 | lang: block.node.attrs.language,
166 | }).children[0] as Element
167 |
168 | decorations.push(Decoration.node(block.pos, block.pos + block.node.nodeSize, {
169 | // @ts-expect-error class
170 | class: `${preNode.properties?.class} node-editor__code-block-shiki`,
171 | // @ts-expect-error style
172 | style: preNode.properties?.style,
173 | } as DecorationAttrs))
174 |
175 | let from = block.pos + 1
176 | const lines = (preNode.children[0] as Element).children
177 | for (const line of lines) {
178 | if ((line as Element).children?.length) {
179 | let lineFrom = from
180 | // @ts-expect-error line type
181 | line.children?.forEach((node) => {
182 | const nodeLen = node.children[0].value.length
183 | decorations.push(Decoration.inline(lineFrom, lineFrom + nodeLen, (node as Element).properties as DecorationAttrs))
184 | lineFrom += nodeLen
185 | })
186 |
187 | // prosemirror do not support add wrap for line
188 | // decorations.push(Decoration.inline(from, lineFrom, line.properties as DecorationAttrs))
189 | from = lineFrom
190 | }
191 | else if (line.type === 'text') {
192 | from += line.value.length
193 | }
194 | }
195 | })
196 |
197 | decorations = decorations.filter(item => !!item)
198 |
199 | return DecorationSet.create(doc, decorations)
200 | }
201 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-code-block-shiki/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './codeBlockShiki'
2 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-code-block-shiki/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "strict": true,
6 | "noFallthroughCasesInSwitch": true,
7 | "noImplicitOverride": true,
8 | "noImplicitReturns": true,
9 | "noPropertyAccessFromIndexSignature": true,
10 | "forceConsistentCasingInFileNames": true
11 | },
12 | "references": [
13 | {
14 | "path": "./tsconfig.lib.json"
15 | }
16 | ],
17 | "files": [],
18 | "include": []
19 | }
20 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-code-block-shiki/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "types": ["node", "vite/client"],
5 | "declaration": true,
6 | "outDir": "../../dist/out-tsc"
7 | },
8 | "include": ["src/**/*.ts"],
9 | "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-code-block-shiki/vite.config.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import * as path from 'node:path'
3 | import { defineConfig } from 'vite'
4 | import dts from 'vite-plugin-dts'
5 | import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'
6 |
7 | export default defineConfig({
8 | root: __dirname,
9 | cacheDir:
10 | '../../node_modules/.vite/packages/tiptap-extension-code-block-shiki',
11 |
12 | plugins: [
13 | nxViteTsPaths(),
14 | dts({
15 | entryRoot: 'src',
16 | tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'),
17 | skipDiagnostics: true,
18 | }),
19 | ],
20 |
21 | // Uncomment this if you are using workers.
22 | // worker: {
23 | // plugins: [ nxViteTsPaths() ],
24 | // },
25 |
26 | // Configuration for building your library.
27 | // See: https://vitejs.dev/guide/build.html#library-mode
28 | build: {
29 | outDir: 'dist',
30 | reportCompressedSize: true,
31 | commonjsOptions: {
32 | transformMixedEsModules: true,
33 | },
34 | lib: {
35 | // Could also be a dictionary or array of multiple entry points.
36 | entry: 'src/index.ts',
37 | name: 'tiptap-extension-code-block-shiki',
38 | fileName: 'index',
39 | // Change this to the formats you want to support.
40 | // Don't forget to update your package.json as well.
41 | formats: ['es', 'cjs'],
42 | },
43 | rollupOptions: {
44 | // External packages that should not be bundled into your library.
45 | external: [/^@tiptap\//, 'shiki/bundle/web'],
46 | },
47 | },
48 | })
49 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-details/README.md:
--------------------------------------------------------------------------------
1 | # tiptap-extension-details
2 |
3 | details extension for tiptap
4 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-details/eslint.config.js:
--------------------------------------------------------------------------------
1 | const { FlatCompat } = require('@eslint/eslintrc')
2 | const js = require('@eslint/js')
3 | const baseConfig = require('../../eslint.config.js')
4 |
5 | const compat = new FlatCompat({
6 | baseDirectory: __dirname,
7 | recommendedConfig: js.configs.recommended,
8 | })
9 |
10 | module.exports = [
11 | ...baseConfig,
12 | {
13 | files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
14 | rules: {},
15 | },
16 | {
17 | files: ['**/*.ts', '**/*.tsx'],
18 | rules: {},
19 | },
20 | {
21 | files: ['**/*.js', '**/*.jsx'],
22 | rules: {},
23 | },
24 | ...compat.config({ parser: 'jsonc-eslint-parser' }).map(config => ({
25 | ...config,
26 | files: ['**/*.json'],
27 | rules: {
28 | '@nx/dependency-checks': [
29 | 'error',
30 | {
31 | ignoredFiles: ['{projectRoot}/vite.config.{js,ts,mjs,mts}'],
32 | },
33 | ],
34 | },
35 | })),
36 | ]
37 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-details/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@note-editor/tiptap-extension-details",
3 | "type": "module",
4 | "version": "0.3.1",
5 | "description": "details extension for tiptap",
6 | "license": "MIT",
7 | "homepage": "https://note-editor.liting.ink/",
8 | "repository": {
9 | "type": "git",
10 | "url": "https://github.com/liting-yes/note-editor.git",
11 | "directory": "packages/tiptap-extension-details"
12 | },
13 | "keywords": [
14 | "tiptap",
15 | "tiptap extension",
16 | "details"
17 | ],
18 | "exports": {
19 | ".": {
20 | "types": "./dist/index.d.ts",
21 | "import": "./dist/index.js",
22 | "require": "./dist/index.cjs"
23 | }
24 | },
25 | "main": "./dist/index.cjs",
26 | "module": "./dist/index.js",
27 | "types": "./dist/index.d.ts",
28 | "files": [
29 | "dist"
30 | ],
31 | "peerDependencies": {
32 | "@tiptap/core": "^2.2"
33 | },
34 | "dependencies": {
35 | "@tiptap/pm": "^2.2.4"
36 | },
37 | "publishConfig": {
38 | "access": "public",
39 | "registry": "https://registry.npmjs.org"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-details/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tiptap-extension-details",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/tiptap-extension-details/src",
5 | "projectType": "library",
6 | "targets": {
7 | "build": {
8 | "executor": "@nx/vite:build",
9 | "outputs": ["{options.outputPath}"],
10 | "options": {
11 | "outputPath": "packages/tiptap-extension-details/dist",
12 | "main": "packages/tiptap-extension-details/src/index.ts",
13 | "tsConfig": "packages/tiptap-extension-details/tsconfig.lib.json",
14 | "assets": ["packages/tiptap-extension-details/*.md"]
15 | }
16 | }
17 | },
18 | "tags": []
19 | }
20 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-details/src/details.ts:
--------------------------------------------------------------------------------
1 | import { Node, mergeAttributes } from '@tiptap/core'
2 | import type { DetailsSummaryOptions } from './detailsSummary'
3 | import { detailsSummary } from './detailsSummary'
4 | import type { DetailsContentOptions } from './detailsContent'
5 | import { detailsContent } from './detailsContent'
6 |
7 | export interface DetailsOptions {
8 | HTMLAttributes: Record
9 | detailSummaryOptions: Partial
10 | detailContentOptions: Partial
11 | }
12 |
13 | declare module '@tiptap/core' {
14 | interface Commands {
15 | details: {
16 | insertDetails: () => ReturnType
17 | }
18 | }
19 | }
20 |
21 | export const details = Node.create({
22 | name: 'details',
23 | group: 'block',
24 | content: 'detailsSummary detailsContent',
25 | addOptions() {
26 | return {
27 | HTMLAttributes: {},
28 | detailSummaryOptions: {},
29 | detailContentOptions: {},
30 | }
31 | },
32 | addAttributes() {
33 | return {
34 | open: {
35 | default: null,
36 | rendered: true,
37 | isRequired: true,
38 | parseHTML: element => element.getAttribute('open'),
39 | renderHTML: (attributes) => {
40 | // @ts-expect-error open
41 | if (attributes.open) {
42 | return {
43 | open: true,
44 | }
45 | }
46 |
47 | return {}
48 | },
49 | },
50 | }
51 | },
52 | parseHTML() {
53 | return [
54 | {
55 | tag: 'details',
56 | },
57 | ]
58 | },
59 | renderHTML({ HTMLAttributes }) {
60 | return ['details', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
61 | class: 'node-editor__details',
62 | }), 0]
63 | },
64 | addCommands() {
65 | return {
66 | insertDetails: () => ({ commands }) => {
67 | commands.insertContent({
68 | type: this.name,
69 | content: [
70 | {
71 | type: detailsSummary.name,
72 | },
73 | {
74 | type: detailsContent.name,
75 | },
76 | ],
77 | })
78 |
79 | return true
80 | },
81 | }
82 | },
83 | addExtensions() {
84 | return [
85 | detailsSummary.configure(this.options.detailSummaryOptions),
86 | detailsContent.configure(this.options.detailContentOptions),
87 | ]
88 | },
89 |
90 | })
91 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-details/src/detailsContent.ts:
--------------------------------------------------------------------------------
1 | import { Node, mergeAttributes } from '@tiptap/core'
2 |
3 | export interface DetailsContentOptions {
4 | HTMLAttributes: Record
5 | }
6 |
7 | export const detailsContent = Node.create({
8 | name: 'detailsContent',
9 | group: 'details',
10 | content: 'block*',
11 | addOptions() {
12 | return {
13 | HTMLAttributes: {},
14 | }
15 | },
16 | parseHTML() {
17 | return [
18 | {
19 | tag: 'div.node-editor__details-content',
20 | },
21 | ]
22 | },
23 | renderHTML({ HTMLAttributes }) {
24 | return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
25 | class: 'node-editor__details-content',
26 | }), 0]
27 | },
28 | })
29 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-details/src/detailsSummary.ts:
--------------------------------------------------------------------------------
1 | import { Node, mergeAttributes } from '@tiptap/core'
2 | import { Plugin, PluginKey } from '@tiptap/pm/state'
3 |
4 | export interface DetailsSummaryOptions {
5 | HTMLAttributes: Record
6 | }
7 |
8 | export const detailsSummary = Node.create({
9 | name: 'detailsSummary',
10 | group: 'details',
11 | content: 'inline*',
12 | addOptions() {
13 | return {
14 | HTMLAttributes: {},
15 | }
16 | },
17 | parseHTML() {
18 | return [
19 | {
20 | tag: 'summary',
21 | },
22 | ]
23 | },
24 | renderHTML({ HTMLAttributes }) {
25 | return ['summary', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
26 | class: 'node-editor__details-summary',
27 | }), 0]
28 | },
29 | addProseMirrorPlugins() {
30 | return [
31 | new Plugin({
32 | key: new PluginKey(this.name),
33 | props: {
34 | handleClickOn: (view, pos, node, nodePos, event, direct) => {
35 | if (!direct || node.type.name !== this.name)
36 | return
37 |
38 | const detailsNode = view.state.doc.resolve(nodePos).parent
39 | // @ts-expect-error open
40 | const tr = view.state.tr.setNodeAttribute(nodePos - 1, 'open', !detailsNode.attrs.open)
41 | view.dispatch(tr)
42 | },
43 | },
44 | }),
45 | ]
46 | },
47 | })
48 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-details/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './details'
2 | export * from './detailsContent'
3 | export * from './detailsSummary'
4 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-details/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "strict": true,
6 | "noFallthroughCasesInSwitch": true,
7 | "noImplicitOverride": true,
8 | "noImplicitReturns": true,
9 | "noPropertyAccessFromIndexSignature": true,
10 | "forceConsistentCasingInFileNames": true
11 | },
12 | "references": [
13 | {
14 | "path": "./tsconfig.lib.json"
15 | }
16 | ],
17 | "files": [],
18 | "include": []
19 | }
20 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-details/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "types": ["node", "vite/client"],
5 | "declaration": true,
6 | "outDir": "../../dist/out-tsc"
7 | },
8 | "include": ["src/**/*.ts"],
9 | "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-details/vite.config.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import * as path from 'node:path'
3 | import { defineConfig } from 'vite'
4 | import dts from 'vite-plugin-dts'
5 | import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'
6 |
7 | export default defineConfig({
8 | root: __dirname,
9 | cacheDir: '../../node_modules/.vite/packages/tiptap-extension-details',
10 |
11 | plugins: [
12 | nxViteTsPaths(),
13 | dts({
14 | entryRoot: 'src',
15 | tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'),
16 | skipDiagnostics: true,
17 | }),
18 | ],
19 |
20 | // Uncomment this if you are using workers.
21 | // worker: {
22 | // plugins: [ nxViteTsPaths() ],
23 | // },
24 |
25 | // Configuration for building your library.
26 | // See: https://vitejs.dev/guide/build.html#library-mode
27 | build: {
28 | outDir: 'dist',
29 | reportCompressedSize: true,
30 | commonjsOptions: {
31 | transformMixedEsModules: true,
32 | },
33 | lib: {
34 | // Could also be a dictionary or array of multiple entry points.
35 | entry: 'src/index.ts',
36 | name: 'tiptap-extension-details',
37 | fileName: 'index',
38 | // Change this to the formats you want to support.
39 | // Don't forget to update your package.json as well.
40 | formats: ['es', 'cjs'],
41 | },
42 | rollupOptions: {
43 | // External packages that should not be bundled into your library.
44 | external: [/^@tiptap\//],
45 | },
46 | },
47 | })
48 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-emoji/README.md:
--------------------------------------------------------------------------------
1 | # tiptap-extension-emoji
2 |
3 | emoji extension for tiptap
4 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-emoji/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@note-editor/tiptap-extension-emoji",
3 | "type": "module",
4 | "version": "0.3.1",
5 | "description": "emoji extension for tiptap",
6 | "license": "MIT",
7 | "homepage": "https://note-editor.liting.ink/",
8 | "repository": {
9 | "type": "git",
10 | "url": "https://github.com/liting-yes/note-editor.git",
11 | "directory": "packages/tiptap-extension-emoji"
12 | },
13 | "keywords": [
14 | "tiptap",
15 | "tiptap extension",
16 | "emoji"
17 | ],
18 | "exports": {
19 | ".": {
20 | "types": "./dist/index.d.ts",
21 | "import": "./dist/index.js",
22 | "require": "./dist/index.cjs"
23 | }
24 | },
25 | "main": "./dist/index.cjs",
26 | "module": "./dist/index.js",
27 | "types": "./dist/index.d.ts",
28 | "files": [
29 | "dist"
30 | ],
31 | "dependencies": {
32 | "@tiptap/core": "^2.2.4",
33 | "emojilib": "^3.0.12"
34 | },
35 | "publishConfig": {
36 | "access": "public",
37 | "registry": "https://registry.npmjs.org"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-emoji/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tiptap-extension-emoji",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/tiptap-extension-emoji/src",
5 | "projectType": "library",
6 | "targets": {
7 | "build": {
8 | "executor": "@nx/vite:build",
9 | "outputs": ["{options.outputPath}"],
10 | "options": {
11 | "outputPath": "packages/tiptap-extension-emoji/dist",
12 | "main": "packages/tiptap-extension-emoji/src/index.ts",
13 | "tsConfig": "packages/tiptap-extension-emoji/tsconfig.lib.json",
14 | "assets": ["packages/tiptap-extension-emoji/*.md"]
15 | }
16 | }
17 | },
18 | "tags": []
19 | }
20 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-emoji/src/emoji.ts:
--------------------------------------------------------------------------------
1 | import { InputRule, Node, PasteRule } from '@tiptap/core'
2 | import emojiJson from 'emojilib'
3 |
4 | const emojiMap = new Map()
5 | Object.entries(emojiJson).forEach(([emoji, names]) => {
6 | names.forEach(name => emojiMap.set(name, emoji))
7 | })
8 |
9 | export interface EmojiOptions {
10 | }
11 |
12 | export const emoji = Node.create({
13 | name: 'emoji',
14 | inline: true,
15 | group: 'inline',
16 | atom: true,
17 | addInputRules() {
18 | return Object.entries(emojiJson).map(([emoji, names]) => new InputRule({
19 | find: new RegExp(`:(${names.map(name => name.replace(/(\(|\)|\+)/, str => `\\${str}`)).join('|')}):$`),
20 | handler({ state, range }) {
21 | state.tr.insertText(emoji, range.from, range.to)
22 | },
23 | }))
24 | },
25 | addPasteRules() {
26 | return Object.entries(emojiJson).map(([emoji, names]) => new PasteRule({
27 | find: new RegExp(`(:(${names.map(name => name.replace(/(\(|\)|\+)/, str => `\\${str}`)).join('|')}):)`, 'g'),
28 | handler({ state, range }) {
29 | state.tr.insertText(emoji, range.from, range.to)
30 | },
31 | }))
32 | },
33 | })
34 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-emoji/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './emoji'
2 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-emoji/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "strict": true,
6 | "noFallthroughCasesInSwitch": true,
7 | "noImplicitOverride": true,
8 | "noImplicitReturns": true,
9 | "noPropertyAccessFromIndexSignature": true,
10 | "forceConsistentCasingInFileNames": true
11 | },
12 | "references": [
13 | {
14 | "path": "./tsconfig.lib.json"
15 | }
16 | ],
17 | "files": [],
18 | "include": []
19 | }
20 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-emoji/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "types": ["node", "vite/client"],
5 | "declaration": true,
6 | "outDir": "../../dist/out-tsc"
7 | },
8 | "include": ["src/**/*.ts"],
9 | "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-emoji/vite.config.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import * as path from 'node:path'
3 | import { defineConfig } from 'vite'
4 | import dts from 'vite-plugin-dts'
5 | import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'
6 |
7 | export default defineConfig({
8 | root: __dirname,
9 | cacheDir: '../../node_modules/.vite/packages/tiptap-extension-emoji',
10 |
11 | plugins: [
12 | nxViteTsPaths(),
13 | dts({
14 | entryRoot: 'src',
15 | tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'),
16 | skipDiagnostics: true,
17 | }),
18 | ],
19 |
20 | // Uncomment this if you are using workers.
21 | // worker: {
22 | // plugins: [ nxViteTsPaths() ],
23 | // },
24 |
25 | // Configuration for building your library.
26 | // See: https://vitejs.dev/guide/build.html#library-mode
27 | build: {
28 | outDir: 'dist',
29 | reportCompressedSize: true,
30 | commonjsOptions: {
31 | transformMixedEsModules: true,
32 | },
33 | lib: {
34 | // Could also be a dictionary or array of multiple entry points.
35 | entry: 'src/index.ts',
36 | name: 'tiptap-extension-emoji',
37 | fileName: 'index',
38 | // Change this to the formats you want to support.
39 | // Don't forget to update your package.json as well.
40 | formats: ['es', 'cjs'],
41 | },
42 | rollupOptions: {
43 | // External packages that should not be bundled into your library.
44 | external: [/^@tiptap\//],
45 | },
46 | },
47 | })
48 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-unique-id/README.md:
--------------------------------------------------------------------------------
1 | # tiptap-extension-unique-id
2 |
3 | unique id extension for tiptap
4 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-unique-id/eslint.config.js:
--------------------------------------------------------------------------------
1 | const { FlatCompat } = require('@eslint/eslintrc')
2 | const js = require('@eslint/js')
3 | const baseConfig = require('../../eslint.config.js')
4 |
5 | const compat = new FlatCompat({
6 | baseDirectory: __dirname,
7 | recommendedConfig: js.configs.recommended,
8 | })
9 |
10 | module.exports = [
11 | ...baseConfig,
12 | {
13 | files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
14 | rules: {},
15 | },
16 | {
17 | files: ['**/*.ts', '**/*.tsx'],
18 | rules: {},
19 | },
20 | {
21 | files: ['**/*.js', '**/*.jsx'],
22 | rules: {},
23 | },
24 | ...compat.config({ parser: 'jsonc-eslint-parser' }).map(config => ({
25 | ...config,
26 | files: ['**/*.json'],
27 | rules: {
28 | '@nx/dependency-checks': [
29 | 'error',
30 | {
31 | ignoredFiles: ['{projectRoot}/vite.config.{js,ts,mjs,mts}'],
32 | },
33 | ],
34 | },
35 | })),
36 | ]
37 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-unique-id/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@note-editor/tiptap-extension-unique-id",
3 | "type": "module",
4 | "version": "0.3.1",
5 | "description": "unique id extension for tiptap",
6 | "license": "MIT",
7 | "homepage": "https://note-editor.liting.ink/",
8 | "repository": {
9 | "type": "git",
10 | "url": "https://github.com/liting-yes/note-editor.git",
11 | "directory": "packages/tiptap-extension-unique-id"
12 | },
13 | "keywords": [
14 | "tiptap",
15 | "tiptap extension"
16 | ],
17 | "exports": {
18 | ".": {
19 | "types": "./dist/index.d.ts",
20 | "import": "./dist/index.js",
21 | "require": "./dist/index.cjs"
22 | }
23 | },
24 | "main": "./dist/index.cjs",
25 | "module": "./dist/index.js",
26 | "types": "./dist/index.d.ts",
27 | "files": [
28 | "dist"
29 | ],
30 | "peerDependencies": {
31 | "@tiptap/core": "^2.2",
32 | "@tiptap/pm": "^2.2"
33 | },
34 | "dependencies": {
35 | "nanoid": "^5.0.6"
36 | },
37 | "publishConfig": {
38 | "access": "public",
39 | "registry": "https://registry.npmjs.org"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-unique-id/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tiptap-extension-unique-id",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/tiptap-extension-unique-id/src",
5 | "projectType": "library",
6 | "targets": {
7 | "build": {
8 | "executor": "@nx/vite:build",
9 | "outputs": ["{options.outputPath}"],
10 | "options": {
11 | "outputPath": "packages/tiptap-extension-unique-id/dist",
12 | "main": "packages/tiptap-extension-unique-id/src/index.ts",
13 | "tsConfig": "packages/tiptap-extension-unique-id/tsconfig.lib.json",
14 | "assets": ["packages/tiptap-extension-unique-id/*.md"]
15 | }
16 | }
17 | },
18 | "tags": []
19 | }
20 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-unique-id/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './uniqueId'
2 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-unique-id/src/uniqueId.ts:
--------------------------------------------------------------------------------
1 | import { Extension, combineTransactionSteps, findChildrenInRange, findDuplicates, getChangedRanges } from '@tiptap/core'
2 | import { nanoid } from 'nanoid'
3 | import type { Transaction } from '@tiptap/pm/state'
4 | import { Plugin, PluginKey } from '@tiptap/pm/state'
5 |
6 | export interface UniqueIdOptions {
7 | attributeName: string
8 | types: string[]
9 | generateID: () => string
10 | injectNodeName: boolean
11 | }
12 |
13 | const pluginKey = new PluginKey('uniqueId')
14 |
15 | export const uniqueId = Extension.create({
16 | name: 'uniqueId',
17 | addOptions() {
18 | return {
19 | attributeName: 'id',
20 | name: 'detailsSummary',
21 | types: ['blockContainer', 'paragraph', 'details', 'detailsSummary', 'detailsContent'],
22 | generateID: () => nanoid(),
23 | injectNodeName: true,
24 | }
25 | },
26 | addGlobalAttributes() {
27 | const { attributeName, types } = this.options
28 |
29 | return [
30 | {
31 | types,
32 | attributes: {
33 | [attributeName!]: {
34 | default: null,
35 | rendered: true,
36 | isRequired: true,
37 | keepOnSplit: false,
38 | parseHTML: element => element.getAttribute(`data-${attributeName}`),
39 | renderHTML: (attributes) => {
40 | return {
41 | [`data-${attributeName}`]: attributes[attributeName!],
42 | }
43 | },
44 | },
45 | },
46 | },
47 | {
48 | types: this.options.injectNodeName ? types : [],
49 | attributes: {
50 | 'data-node-name': {
51 | default: null,
52 | rendered: true,
53 | isRequired: true,
54 | keepOnSplit: false,
55 | parseHTML: element => element.getAttribute('data-node-name'),
56 | renderHTML: (attributes) => {
57 | return {
58 | 'data-node-name': attributes['data-node-name'],
59 | }
60 | },
61 |
62 | },
63 | },
64 | },
65 | ]
66 | },
67 | onCreate() {
68 | const { tr, doc } = this.editor.state
69 | const { attributeName, types, generateID, injectNodeName } = this.options
70 |
71 | doc.descendants((node, pos) => {
72 | if (node.type.name === 'text' || !types?.includes(node.type.name))
73 | return
74 |
75 | if (injectNodeName)
76 | tr.setNodeAttribute(pos, 'data-node-name', node.type.name)
77 |
78 | if (!node.attrs[attributeName!])
79 | tr.setNodeAttribute(pos, attributeName!, generateID!())
80 | })
81 |
82 | this.editor.view.dispatch(tr)
83 | },
84 | addProseMirrorPlugins() {
85 | const { attributeName, types, generateID, injectNodeName } = this.options
86 |
87 | return [
88 | new Plugin({
89 | key: pluginKey,
90 | appendTransaction(trs, { doc: oldDoc }, { doc: newDoc, tr }) {
91 | if (!trs.some(tr => !!tr.docChanged) || oldDoc.eq(newDoc))
92 | return
93 |
94 | const transform = combineTransactionSteps(oldDoc, trs as Transaction[])
95 |
96 | getChangedRanges(transform).forEach(({ newRange }) => {
97 | const newNodes = findChildrenInRange(newDoc, newRange, node => types!.includes(node.type.name))
98 |
99 | const newIds = newNodes.map(({ node }) => node.attrs[attributeName!]).filter(item => !!item)
100 | newNodes.forEach(({ node, pos }) => {
101 | if (injectNodeName && !node.attrs['data-node-name'])
102 | tr.setNodeAttribute(pos, 'data-node-name', node.type.name)
103 |
104 | const uniqueId = node.attrs[attributeName!]
105 |
106 | if (!uniqueId) {
107 | tr.setNodeAttribute(pos, attributeName!, generateID!())
108 | return
109 | }
110 |
111 | if (tr.mapping.invert().mapResult(pos) && findDuplicates(newIds).includes(uniqueId))
112 | tr.setNodeAttribute(pos, attributeName!, generateID!())
113 | })
114 | })
115 |
116 | if (!transform.steps.length)
117 | return null
118 |
119 | return tr
120 | },
121 | }),
122 | ]
123 | },
124 | })
125 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-unique-id/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "strict": true,
6 | "noFallthroughCasesInSwitch": true,
7 | "noImplicitOverride": true,
8 | "noImplicitReturns": true,
9 | "noPropertyAccessFromIndexSignature": true,
10 | "forceConsistentCasingInFileNames": true
11 | },
12 | "references": [
13 | {
14 | "path": "./tsconfig.lib.json"
15 | }
16 | ],
17 | "files": [],
18 | "include": []
19 | }
20 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-unique-id/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "types": ["node", "vite/client"],
5 | "declaration": true,
6 | "outDir": "../../dist/out-tsc"
7 | },
8 | "include": ["src/**/*.ts"],
9 | "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/tiptap-extension-unique-id/vite.config.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import * as path from 'node:path'
3 | import { defineConfig } from 'vite'
4 | import dts from 'vite-plugin-dts'
5 | import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'
6 |
7 | export default defineConfig({
8 | root: __dirname,
9 | cacheDir: '../../node_modules/.vite/packages/tiptap-extension-unique-id',
10 |
11 | plugins: [
12 | nxViteTsPaths(),
13 | dts({
14 | entryRoot: 'src',
15 | tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'),
16 | skipDiagnostics: true,
17 | }),
18 | ],
19 |
20 | // Uncomment this if you are using workers.
21 | // worker: {
22 | // plugins: [ nxViteTsPaths() ],
23 | // },
24 |
25 | // Configuration for building your library.
26 | // See: https://vitejs.dev/guide/build.html#library-mode
27 | build: {
28 | outDir: 'dist',
29 | reportCompressedSize: true,
30 | commonjsOptions: {
31 | transformMixedEsModules: true,
32 | },
33 | lib: {
34 | // Could also be a dictionary or array of multiple entry points.
35 | entry: 'src/index.ts',
36 | name: 'tiptap-extension-unique-id',
37 | fileName: 'index',
38 | // Change this to the formats you want to support.
39 | // Don't forget to update your package.json as well.
40 | formats: ['es', 'cjs'],
41 | },
42 | rollupOptions: {
43 | // External packages that should not be bundled into your library.
44 | external: [/^@tiptap\//],
45 | },
46 | },
47 | })
48 |
--------------------------------------------------------------------------------
/packages/vue-kit/README.md:
--------------------------------------------------------------------------------
1 | # @note-editor/vue-kit
2 |
3 | starter kit for tiptap in vue
4 |
--------------------------------------------------------------------------------
/packages/vue-kit/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@note-editor/vue-kit",
3 | "type": "module",
4 | "version": "0.3.1",
5 | "private": false,
6 | "description": "starter kit for tiptap in vue",
7 | "license": "MIT",
8 | "homepage": "https://note-editor.liting.ink/",
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/liting-yes/note-editor.git",
12 | "directory": "packages/vue-kit"
13 | },
14 | "keywords": [
15 | "tiptap",
16 | "tiptap starter kit",
17 | "vue"
18 | ],
19 | "exports": {
20 | ".": {
21 | "types": "./dist/index.d.ts",
22 | "import": "./dist/index.js",
23 | "require": "./dist/index.cjs"
24 | },
25 | "./style.css": "./dist/style.css"
26 | },
27 | "main": "./dist/index.cjs",
28 | "module": "./dist/index.js",
29 | "types": "./dist/index.d.ts",
30 | "files": [
31 | "dist"
32 | ],
33 | "publishConfig": {
34 | "access": "public",
35 | "registry": "https://registry.npmjs.org"
36 | },
37 | "peerDependencies": {
38 | "vue": "^3"
39 | },
40 | "dependencies": {
41 | "@note-editor/tiptap-extension-block-container": "0.3.1",
42 | "@note-editor/tiptap-extension-code-block-shiki": "0.3.1",
43 | "@note-editor/tiptap-extension-details": "0.3.1",
44 | "@note-editor/tiptap-extension-emoji": "0.3.1",
45 | "@note-editor/tiptap-extension-unique-id": "0.3.1",
46 | "@tiptap/core": "^2.2.4",
47 | "@tiptap/extension-blockquote": "^2.2.4",
48 | "@tiptap/extension-bold": "^2.2.4",
49 | "@tiptap/extension-bullet-list": "^2.2.4",
50 | "@tiptap/extension-character-count": "^2.2.4",
51 | "@tiptap/extension-code": "^2.2.4",
52 | "@tiptap/extension-code-block": "^2.2.4",
53 | "@tiptap/extension-color": "^2.2.4",
54 | "@tiptap/extension-document": "^2.2.4",
55 | "@tiptap/extension-dropcursor": "^2.2.4",
56 | "@tiptap/extension-focus": "^2.2.4",
57 | "@tiptap/extension-font-family": "^2.2.4",
58 | "@tiptap/extension-gapcursor": "^2.2.4",
59 | "@tiptap/extension-hard-break": "^2.2.4",
60 | "@tiptap/extension-heading": "^2.2.4",
61 | "@tiptap/extension-highlight": "^2.2.4",
62 | "@tiptap/extension-history": "^2.2.4",
63 | "@tiptap/extension-horizontal-rule": "^2.2.4",
64 | "@tiptap/extension-italic": "^2.2.4",
65 | "@tiptap/extension-list-item": "^2.2.4",
66 | "@tiptap/extension-ordered-list": "^2.2.4",
67 | "@tiptap/extension-paragraph": "^2.2.4",
68 | "@tiptap/extension-placeholder": "^2.2.4",
69 | "@tiptap/extension-strike": "^2.2.4",
70 | "@tiptap/extension-subscript": "^2.2.4",
71 | "@tiptap/extension-superscript": "^2.2.4",
72 | "@tiptap/extension-table": "^2.2.4",
73 | "@tiptap/extension-table-cell": "^2.2.4",
74 | "@tiptap/extension-table-header": "^2.2.4",
75 | "@tiptap/extension-table-row": "^2.2.4",
76 | "@tiptap/extension-task-item": "^2.2.4",
77 | "@tiptap/extension-task-list": "^2.2.4",
78 | "@tiptap/extension-text": "^2.2.4",
79 | "@tiptap/extension-text-style": "^2.2.4",
80 | "@tiptap/extension-typography": "^2.2.4",
81 | "@tiptap/extension-underline": "^2.2.4",
82 | "@tiptap/vue-3": "^2.2.4"
83 | },
84 | "devDependencies": {
85 | "vue": "^3.4.21"
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/packages/vue-kit/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-kit",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/vue-kit/src",
5 | "projectType": "library",
6 | "tags": [],
7 | "targets": {}
8 | }
9 |
--------------------------------------------------------------------------------
/packages/vue-kit/src/components/NoteEditor.vue:
--------------------------------------------------------------------------------
1 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
73 |
--------------------------------------------------------------------------------
/packages/vue-kit/src/composables/useNoteEditor.ts:
--------------------------------------------------------------------------------
1 | import { onBeforeUnmount, onMounted, shallowRef } from 'vue'
2 | import type { EditorOptions } from '@tiptap/vue-3'
3 | import { Editor } from '@tiptap/vue-3'
4 | import type { SetupKitOptions } from '../setupKit'
5 | import { setupKit } from '../setupKit'
6 |
7 | export interface UseNoteEditorOptions {
8 | kitOptions: SetupKitOptions
9 | }
10 |
11 | export function useNoteEditor(editorOptions?: Partial, kitOptions?: Partial) {
12 | const editor = shallowRef()
13 |
14 | onMounted(() => {
15 | editor.value = new Editor({
16 | content: 'Note editor',
17 | ...editorOptions,
18 | extensions: [...(editorOptions?.extensions ?? []), kitOptions ? setupKit.configure(kitOptions) : setupKit],
19 | })
20 | })
21 | onBeforeUnmount(() => {
22 | editor.value?.destroy()
23 | editor.value = undefined
24 | })
25 |
26 | return {
27 | editor,
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/packages/vue-kit/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './setupKit'
2 | export * from './composables/useNoteEditor'
3 | export * from './components/NoteEditor.vue'
4 | export { default as NodeEditor } from './components/NoteEditor.vue'
5 |
--------------------------------------------------------------------------------
/packages/vue-kit/src/setupKit.ts:
--------------------------------------------------------------------------------
1 | import type { Extensions } from '@tiptap/core'
2 | import { Extension } from '@tiptap/core'
3 | import type { BlockquoteOptions } from '@tiptap/extension-blockquote'
4 | import { Blockquote } from '@tiptap/extension-blockquote'
5 | import type { BoldOptions } from '@tiptap/extension-bold'
6 | import { Bold } from '@tiptap/extension-bold'
7 | import type { BulletListOptions } from '@tiptap/extension-bullet-list'
8 | import { BulletList } from '@tiptap/extension-bullet-list'
9 | import type { CharacterCountOptions } from '@tiptap/extension-character-count'
10 | import { CharacterCount } from '@tiptap/extension-character-count'
11 | import type { CodeOptions } from '@tiptap/extension-code'
12 | import { Code } from '@tiptap/extension-code'
13 | import type { CodeBlockOptions } from '@tiptap/extension-code-block'
14 | import { CodeBlock } from '@tiptap/extension-code-block'
15 | import type { ColorOptions } from '@tiptap/extension-color'
16 | import { Color } from '@tiptap/extension-color'
17 | import Document from '@tiptap/extension-document'
18 | import type { DropcursorOptions } from '@tiptap/extension-dropcursor'
19 | import { Dropcursor } from '@tiptap/extension-dropcursor'
20 | import type { FocusOptions } from '@tiptap/extension-focus'
21 | import { FocusClasses } from '@tiptap/extension-focus'
22 | import type { FontFamilyOptions } from '@tiptap/extension-font-family'
23 | import { FontFamily } from '@tiptap/extension-font-family'
24 | import Gapcursor from '@tiptap/extension-gapcursor'
25 | import type { HardBreakOptions } from '@tiptap/extension-hard-break'
26 | import { HardBreak } from '@tiptap/extension-hard-break'
27 | import type { HeadingOptions } from '@tiptap/extension-heading'
28 | import { Heading } from '@tiptap/extension-heading'
29 | import type { HighlightOptions } from '@tiptap/extension-highlight'
30 | import { Highlight } from '@tiptap/extension-highlight'
31 | import type { HistoryOptions } from '@tiptap/extension-history'
32 | import { History } from '@tiptap/extension-history'
33 | import type { HorizontalRuleOptions } from '@tiptap/extension-horizontal-rule'
34 | import { HorizontalRule } from '@tiptap/extension-horizontal-rule'
35 | import type { ItalicOptions } from '@tiptap/extension-italic'
36 | import { Italic } from '@tiptap/extension-italic'
37 | import type { ListItemOptions } from '@tiptap/extension-list-item'
38 | import { ListItem } from '@tiptap/extension-list-item'
39 | import type { OrderedListOptions } from '@tiptap/extension-ordered-list'
40 | import { OrderedList } from '@tiptap/extension-ordered-list'
41 | import type { ParagraphOptions } from '@tiptap/extension-paragraph'
42 | import { Paragraph } from '@tiptap/extension-paragraph'
43 | import type { PlaceholderOptions } from '@tiptap/extension-placeholder'
44 | import { Placeholder } from '@tiptap/extension-placeholder'
45 | import type { StrikeOptions } from '@tiptap/extension-strike'
46 | import { Strike } from '@tiptap/extension-strike'
47 | import type { SubscriptExtensionOptions } from '@tiptap/extension-subscript'
48 | import { Subscript } from '@tiptap/extension-subscript'
49 | import type { SuperscriptExtensionOptions } from '@tiptap/extension-superscript'
50 | import { Superscript } from '@tiptap/extension-superscript'
51 | import type { TableOptions } from '@tiptap/extension-table'
52 | import { Table } from '@tiptap/extension-table'
53 | import type { TableCellOptions } from '@tiptap/extension-table-cell'
54 | import { TableCell } from '@tiptap/extension-table-cell'
55 | import type { TableHeaderOptions } from '@tiptap/extension-table-header'
56 | import { TableHeader } from '@tiptap/extension-table-header'
57 | import type { TableRowOptions } from '@tiptap/extension-table-row'
58 | import { TableRow } from '@tiptap/extension-table-row'
59 | import type { TaskItemOptions } from '@tiptap/extension-task-item'
60 | import { TaskItem } from '@tiptap/extension-task-item'
61 | import type { TaskListOptions } from '@tiptap/extension-task-list'
62 | import { TaskList } from '@tiptap/extension-task-list'
63 | import Text from '@tiptap/extension-text'
64 | import type { TextStyleOptions } from '@tiptap/extension-text-style'
65 | import { TextStyle } from '@tiptap/extension-text-style'
66 | import type { TypographyOptions } from '@tiptap/extension-typography'
67 | import { Typography } from '@tiptap/extension-typography'
68 | import type { UnderlineOptions } from '@tiptap/extension-underline'
69 | import { Underline } from '@tiptap/extension-underline'
70 |
71 | import type { UniqueIdOptions } from '@note-editor/tiptap-extension-unique-id'
72 | import { uniqueId } from '@note-editor/tiptap-extension-unique-id'
73 | import type { BlockContainerOptions } from '@note-editor/tiptap-extension-block-container'
74 | import { blockContainer } from '@note-editor/tiptap-extension-block-container'
75 | import type { CodeBlockShikiOptions } from '@note-editor/tiptap-extension-code-block-shiki'
76 | import { codeBlockShiki } from '@note-editor/tiptap-extension-code-block-shiki'
77 | import type { DetailsOptions } from '@note-editor/tiptap-extension-details'
78 | import { details } from '@note-editor/tiptap-extension-details'
79 | import type { EmojiOptions } from '@note-editor/tiptap-extension-emoji'
80 | import { emoji } from '@note-editor/tiptap-extension-emoji'
81 |
82 | export interface SetupKitOptions {
83 | blockquote: Partial | false
84 | bold: Partial | false
85 | bulletList: Partial | false
86 | characterCount: Partial | false
87 | code: Partial | false
88 | codeBlock: Partial | false
89 | color: Partial | false
90 | document: false
91 | dropcursor: Partial | false
92 | focus: Partial | false
93 | fontFamily: Partial | false
94 | gapcursor: false
95 | hardBreak: Partial | false
96 | heading: Partial | false
97 | highlight: Partial | false
98 | history: Partial | false
99 | horizontalRule: Partial | false
100 | italic: Partial | false
101 | listItem: Partial | false
102 | orderedList: Partial | false
103 | paragraph: Partial | false
104 | placeholder: Partial | false
105 | strike: Partial | false
106 | subscript: Partial | false
107 | superscript: Partial | false
108 | table: Partial | false
109 | tableCell: Partial | false
110 | tableHeader: Partial | false
111 | tableRow: Partial | false
112 | taskItem: Partial | false
113 | taskList: Partial | false
114 | text: false
115 | textStyle: Partial | false
116 | typography: Partial | false
117 | underline: Partial | false
118 | uniqueId: Partial | false
119 | blockContainer: Partial | false
120 | codeBlockShiki: Partial | false
121 | details: Partial | false
122 | emoji: Partial | false
123 | }
124 |
125 | export const setupKit = Extension.create({
126 | name: 'setupKit',
127 | addExtensions() {
128 | const extensions: Extensions = []
129 |
130 | if (this.options.blockquote !== false)
131 | extensions.push(Blockquote.configure(this.options.blockquote))
132 |
133 | if (this.options.bold !== false)
134 | extensions.push(Bold.configure(this.options.bold))
135 |
136 | if (this.options.bulletList !== false)
137 | extensions.push(BulletList.configure(this.options.bulletList))
138 |
139 | if (this.options.characterCount !== false)
140 | extensions.push(CharacterCount.configure(this.options.characterCount))
141 |
142 | if (this.options.code !== false)
143 | extensions.push(Code.configure(this.options.code))
144 |
145 | if (this.options.codeBlockShiki === false && this.options.codeBlock !== false)
146 | extensions.push(CodeBlock.configure(this.options.codeBlock))
147 |
148 | if (this.options.codeBlockShiki !== false)
149 | extensions.push(codeBlockShiki.configure(this.options.codeBlockShiki))
150 |
151 | if (this.options.color !== false)
152 | extensions.push(Color.configure(this.options.color))
153 |
154 | if (this.options.blockContainer !== false)
155 | extensions.push(blockContainer)
156 |
157 | if (this.options.blockContainer === false && this.options.document !== false)
158 | extensions.push(Document)
159 |
160 | if (this.options.dropcursor !== false)
161 | extensions.push(Dropcursor.configure(this.options.dropcursor))
162 |
163 | if (this.options.focus !== false)
164 | extensions.push(FocusClasses.configure(this.options.focus))
165 |
166 | if (this.options.fontFamily !== false)
167 | extensions.push(FontFamily.configure(this.options.fontFamily))
168 |
169 | if (this.options.gapcursor !== false)
170 | extensions.push(Gapcursor)
171 |
172 | if (this.options.hardBreak !== false)
173 | extensions.push(HardBreak.configure(this.options.hardBreak))
174 |
175 | if (this.options.heading !== false)
176 | extensions.push(Heading.configure(this.options.heading))
177 |
178 | if (this.options.highlight !== false)
179 | extensions.push(Highlight.configure(this.options.highlight))
180 |
181 | if (this.options.history !== false)
182 | extensions.push(History.configure(this.options.history))
183 |
184 | if (this.options.horizontalRule !== false)
185 | extensions.push(HorizontalRule.configure(this.options.horizontalRule))
186 |
187 | if (this.options.italic !== false)
188 | extensions.push(Italic.configure(this.options.italic))
189 |
190 | if (this.options.listItem !== false)
191 | extensions.push(ListItem.configure(this.options.listItem))
192 |
193 | if (this.options.orderedList !== false)
194 | extensions.push(OrderedList.configure(this.options.orderedList))
195 |
196 | if (this.options.paragraph !== false)
197 | extensions.push(Paragraph.configure(this.options.paragraph))
198 |
199 | if (this.options.placeholder !== false)
200 | extensions.push(Placeholder.configure(this.options.placeholder))
201 |
202 | if (this.options.strike !== false)
203 | extensions.push(Strike.configure(this.options.strike))
204 |
205 | if (this.options.subscript !== false)
206 | extensions.push(Subscript.configure(this.options.subscript))
207 |
208 | if (this.options.superscript !== false)
209 | extensions.push(Superscript.configure(this.options.superscript))
210 |
211 | if (this.options.table !== false)
212 | extensions.push(Table.configure(this.options.table))
213 |
214 | if (this.options.tableCell !== false)
215 | extensions.push(TableCell.configure(this.options.tableCell))
216 |
217 | if (this.options.tableHeader !== false)
218 | extensions.push(TableHeader.configure(this.options.tableHeader))
219 |
220 | if (this.options.tableRow !== false)
221 | extensions.push(TableRow.configure(this.options.tableRow))
222 | if (this.options.taskItem !== false)
223 |
224 | extensions.push(TaskItem.configure(this.options.taskItem))
225 |
226 | if (this.options.taskList !== false)
227 | extensions.push(TaskList.configure(this.options.taskList))
228 |
229 | if (this.options.text !== false)
230 | extensions.push(Text)
231 |
232 | if (this.options.textStyle !== false)
233 | extensions.push(TextStyle.configure(this.options.textStyle))
234 |
235 | if (this.options.typography !== false)
236 | extensions.push(Typography.configure(this.options.typography))
237 |
238 | if (this.options.underline !== false)
239 | extensions.push(Underline.configure(this.options.underline))
240 |
241 | if (this.options.uniqueId !== false)
242 | extensions.push(uniqueId.configure(this.options.uniqueId))
243 |
244 | if (this.options.details !== false)
245 | extensions.push(details.configure(this.options.details))
246 |
247 | if (this.options.emoji !== false)
248 | extensions.push(emoji.configure(this.options.emoji))
249 |
250 | return extensions
251 | },
252 | })
253 |
--------------------------------------------------------------------------------
/packages/vue-kit/src/vue-shims.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import type { defineComponent } from 'vue'
3 |
4 | const component: ReturnType
5 | export default component
6 | }
7 |
--------------------------------------------------------------------------------
/packages/vue-kit/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "jsx": "preserve",
5 | "jsxImportSource": "vue",
6 | "moduleResolution": "node",
7 | "resolveJsonModule": true,
8 | "allowJs": true,
9 | "strict": true,
10 | "allowSyntheticDefaultImports": true,
11 | "esModuleInterop": false,
12 | "verbatimModuleSyntax": true
13 | },
14 | "references": [
15 | {
16 | "path": "./tsconfig.lib.json"
17 | }
18 | ],
19 | "files": [],
20 | "include": []
21 | }
22 |
--------------------------------------------------------------------------------
/packages/vue-kit/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "types": ["vite/client"],
5 | "outDir": "../../dist/out-tsc"
6 | },
7 | "include": [
8 | "src/**/*.js",
9 | "src/**/*.jsx",
10 | "src/**/*.ts",
11 | "src/**/*.tsx",
12 | "src/**/*.vue"
13 | ],
14 | "exclude": [
15 | "src/**/__tests__/*",
16 | "src/**/*.spec.ts",
17 | "src/**/*.test.ts",
18 | "src/**/*.spec.tsx",
19 | "src/**/*.test.tsx",
20 | "src/**/*.spec.js",
21 | "src/**/*.test.js",
22 | "src/**/*.spec.jsx",
23 | "src/**/*.test.jsx",
24 | "src/**/*.spec.vue",
25 | "src/**/*.test.vue"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/packages/vue-kit/vite.config.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import * as path from 'node:path'
3 | import { defineConfig } from 'vite'
4 | import vue from '@vitejs/plugin-vue'
5 | import dts from 'vite-plugin-dts'
6 | import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'
7 |
8 | export default defineConfig({
9 | root: __dirname,
10 | cacheDir: '../../node_modules/.vite/packages/vue-kit',
11 |
12 | plugins: [
13 | vue(),
14 | nxViteTsPaths(),
15 | dts({
16 | entryRoot: 'src',
17 | tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'),
18 | skipDiagnostics: true,
19 | }),
20 | ],
21 |
22 | // Uncomment this if you are using workers.
23 | // worker: {
24 | // plugins: [ nxViteTsPaths() ],
25 | // },
26 |
27 | // Configuration for building your library.
28 | // See: https://vitejs.dev/guide/build.html#library-mode
29 | build: {
30 | outDir: 'dist',
31 | reportCompressedSize: true,
32 | commonjsOptions: {
33 | transformMixedEsModules: true,
34 | },
35 | lib: {
36 | // Could also be a dictionary or array of multiple entry points.
37 | entry: 'src/index.ts',
38 | name: 'vue-kit',
39 | fileName: 'index',
40 | // Change this to the formats you want to support.
41 | // Don't forget to update your package.json as well.
42 | formats: ['es', 'cjs'],
43 | },
44 | rollupOptions: {
45 | // External packages that should not be bundled into your library.
46 | external: [/^@tiptap\//, /^@note-editor\//, 'vue'],
47 | },
48 | },
49 | })
50 |
--------------------------------------------------------------------------------
/packages/vue-play/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | vue-play
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/packages/vue-play/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@note-editor/vue-play",
3 | "private": false,
4 | "dependencies": {
5 | "@note-editor/vue-kit": "workspace:*",
6 | "@tiptap/starter-kit": "^2.2.4",
7 | "@tiptap/vue-3": "^2.2.4",
8 | "vue": "^3.4.21"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/vue-play/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-play",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "projectType": "application",
5 | "sourceRoot": "packages/vue-play/src",
6 | "targets": {}
7 | }
8 |
--------------------------------------------------------------------------------
/packages/vue-play/src/App.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
23 |
--------------------------------------------------------------------------------
/packages/vue-play/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './App.vue'
3 |
4 | const app = createApp(App)
5 |
6 | app.mount('#root')
7 |
--------------------------------------------------------------------------------
/packages/vue-play/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "types": ["vite/client"],
5 | "outDir": "../../dist/out-tsc"
6 | },
7 | "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.vue"],
8 | "exclude": [
9 | "src/**/*.spec.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.vue",
12 | "src/**/*.test.vue"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/packages/vue-play/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "jsx": "preserve",
5 | "jsxImportSource": "vue",
6 | "moduleResolution": "node",
7 | "resolveJsonModule": true,
8 | "allowJs": true,
9 | "strict": true,
10 | "allowSyntheticDefaultImports": true,
11 | "esModuleInterop": false,
12 | "verbatimModuleSyntax": true
13 | },
14 | "references": [
15 | {
16 | "path": "./tsconfig.app.json"
17 | }
18 | ],
19 | "files": [],
20 | "include": []
21 | }
22 |
--------------------------------------------------------------------------------
/packages/vue-play/vite.config.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { defineConfig } from 'vite'
3 | import vue from '@vitejs/plugin-vue'
4 | import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'
5 |
6 | export default defineConfig({
7 | root: __dirname,
8 | cacheDir: '../../node_modules/.vite/packages/vue-play',
9 |
10 | server: {
11 | port: 4200,
12 | host: 'localhost',
13 | },
14 |
15 | preview: {
16 | port: 4300,
17 | host: 'localhost',
18 | },
19 |
20 | plugins: [vue(), nxViteTsPaths()],
21 |
22 | // Uncomment this if you are using workers.
23 | // worker: {
24 | // plugins: [ nxViteTsPaths() ],
25 | // },
26 |
27 | build: {
28 | outDir: 'dist',
29 | reportCompressedSize: true,
30 | commonjsOptions: {
31 | transformMixedEsModules: true,
32 | },
33 | },
34 | })
35 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - 'packages/*'
3 |
--------------------------------------------------------------------------------
/tsconfig.base.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "target": "es2015",
5 | "lib": ["es2020", "dom"],
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "baseUrl": ".",
9 | "rootDir": ".",
10 | "module": "esnext",
11 | "moduleResolution": "node",
12 | "paths": {
13 | "tiptap-extension-block-container": [
14 | "packages/tiptap-extension-block-container/src/index.ts"
15 | ],
16 | "tiptap-extension-code-block-shiki": [
17 | "packages/tiptap-extension-code-block-shiki/src/index.ts"
18 | ],
19 | "tiptap-extension-details": [
20 | "packages/tiptap-extension-details/src/index.ts"
21 | ],
22 | "tiptap-extension-emoji": [
23 | "packages/tiptap-extension-emoji/src/index.ts"
24 | ],
25 | "tiptap-extension-unique-id": [
26 | "packages/tiptap-extension-unique-id/src/index.ts"
27 | ],
28 | "vue-kit": ["packages/vue-kit/src/index.ts"],
29 | "vue-play": ["packages/vue-play/src/index.ts"]
30 | },
31 | "declaration": false,
32 | "importHelpers": true,
33 | "sourceMap": true,
34 | "skipDefaultLibCheck": true,
35 | "skipLibCheck": true
36 | },
37 | "exclude": ["node_modules", "tmp"]
38 | }
39 |
--------------------------------------------------------------------------------