diff --git a/.changeset/config.json b/.changeset/config.json index 23fbea9f9c..7828f76af3 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -7,9 +7,7 @@ "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", - "ignore": [ - "@tiptap-shared/rollup-config" - ], + "ignore": [], "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { "onlyUpdatePeerDependentsWhenOutOfRange": true } diff --git a/.changeset/fast-foxes-mate.md b/.changeset/fast-foxes-mate.md deleted file mode 100644 index c6193cc41c..0000000000 --- a/.changeset/fast-foxes-mate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@tiptap/extension-table": patch ---- - -Added new export for TableView class diff --git a/.changeset/popular-geckos-pay.md b/.changeset/popular-geckos-pay.md deleted file mode 100644 index a98e7508e1..0000000000 --- a/.changeset/popular-geckos-pay.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@tiptap/extension-link": patch ---- - -Fixed links with marks not registering click events correctly diff --git a/.changeset/pre.json b/.changeset/pre.json deleted file mode 100644 index 66e6ff0193..0000000000 --- a/.changeset/pre.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "mode": "pre", - "tag": "pre", - "initialVersions": { - "tiptap-demos": "2.5.2", - "@tiptap/core": "2.11.6", - "@tiptap/extension-blockquote": "2.11.6", - "@tiptap/extension-bold": "2.11.6", - "@tiptap/extension-bubble-menu": "2.11.6", - "@tiptap/extension-bullet-list": "2.11.6", - "@tiptap/extension-character-count": "2.11.6", - "@tiptap/extension-code": "2.11.6", - "@tiptap/extension-code-block": "2.11.6", - "@tiptap/extension-code-block-lowlight": "2.11.6", - "@tiptap/extension-collaboration": "2.11.6", - "@tiptap/extension-collaboration-cursor": "2.11.6", - "@tiptap/extension-color": "2.11.6", - "@tiptap/extension-document": "2.11.6", - "@tiptap/extension-dropcursor": "2.11.6", - "@tiptap/extension-floating-menu": "2.11.6", - "@tiptap/extension-focus": "2.11.6", - "@tiptap/extension-font-family": "2.11.6", - "@tiptap/extension-gapcursor": "2.11.6", - "@tiptap/extension-hard-break": "2.11.6", - "@tiptap/extension-heading": "2.11.6", - "@tiptap/extension-highlight": "2.11.6", - "@tiptap/extension-history": "2.11.6", - "@tiptap/extension-horizontal-rule": "2.11.6", - "@tiptap/extension-image": "2.11.6", - "@tiptap/extension-italic": "2.11.6", - "@tiptap/extension-link": "2.11.6", - "@tiptap/extension-list-item": "2.11.6", - "@tiptap/extension-list-keymap": "2.11.6", - "@tiptap/extension-mention": "2.11.6", - "@tiptap/extension-ordered-list": "2.11.6", - "@tiptap/extension-paragraph": "2.11.6", - "@tiptap/extension-placeholder": "2.11.6", - "@tiptap/extension-strike": "2.11.6", - "@tiptap/extension-subscript": "2.11.6", - "@tiptap/extension-superscript": "2.11.6", - "@tiptap/extension-table": "2.11.6", - "@tiptap/extension-table-cell": "2.11.6", - "@tiptap/extension-table-header": "2.11.6", - "@tiptap/extension-table-row": "2.11.6", - "@tiptap/extension-task-item": "2.11.6", - "@tiptap/extension-task-list": "2.11.6", - "@tiptap/extension-text": "2.11.6", - "@tiptap/extension-text-align": "2.11.6", - "@tiptap/extension-text-style": "2.11.6", - "@tiptap/extension-typography": "2.11.6", - "@tiptap/extension-underline": "2.11.6", - "@tiptap/extension-youtube": "2.11.6", - "@tiptap/html": "2.11.6", - "@tiptap/pm": "2.11.6", - "@tiptap/react": "2.11.6", - "@tiptap/starter-kit": "2.11.6", - "@tiptap/suggestion": "2.11.6", - "@tiptap/vue-2": "2.11.6", - "@tiptap/vue-3": "2.11.6", - "@tiptap-shared/rollup-config": "1.0.0" - }, - "changesets": [] -} diff --git a/.changeset/shiny-days-rhyme.md b/.changeset/shiny-days-rhyme.md deleted file mode 100644 index 47ffe0b968..0000000000 --- a/.changeset/shiny-days-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@tiptap/core": patch ---- - -Clone dragged node before dragging to get correct drag preview image diff --git a/.changeset/wise-carpets-unite.md b/.changeset/wise-carpets-unite.md deleted file mode 100644 index 3ca09b8178..0000000000 --- a/.changeset/wise-carpets-unite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@tiptap/extension-image": minor ---- - -Add width and height attributes to Image node diff --git a/.eslintrc.js b/.eslintrc.js index 2731d7b92b..997ff95870 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,28 +9,12 @@ module.exports = { }, overrides: [ { - files: [ - './**/*.ts', - './**/*.tsx', - './**/*.js', - './**/*.jsx', - ], + files: ['./**/*.ts', './**/*.tsx', './**/*.js', './**/*.jsx'], extends: ['plugin:react-hooks/recommended'], }, { - files: [ - './**/*.ts', - './**/*.tsx', - './**/*.js', - './**/*.jsx', - './**/*.vue', - ], - plugins: [ - 'html', - 'cypress', - '@typescript-eslint', - 'simple-import-sort', - ], + files: ['./**/*.ts', './**/*.tsx', './**/*.js', './**/*.jsx', './**/*.vue'], + plugins: ['html', 'cypress', '@typescript-eslint', 'simple-import-sort'], env: { 'cypress/globals': true, }, @@ -43,17 +27,18 @@ module.exports = { 'plugin:@typescript-eslint/recommended', 'plugin:vue/vue3-strongly-recommended', 'airbnb-base', + 'prettier', ], rules: { curly: ['error', 'all'], - 'newline-after-var': ['error', 'always'], 'no-continue': 'off', 'no-alert': 'off', 'no-console': ['warn', { allow: ['warn', 'error'] }], semi: ['error', 'never'], 'import/order': 'off', 'import/extensions': ['error', 'ignorePackages'], - 'no-restricted-imports': ['error', + 'no-restricted-imports': [ + 'error', { paths: [ { @@ -81,14 +66,6 @@ module.exports = { 'vue/one-component-per-file': 'off', 'vue/this-in-template': ['error', 'never'], 'vue/multi-word-component-names': 'off', - 'vue/max-attributes-per-line': ['error', { - singleline: { - max: 3, - }, - multiline: { - max: 1, - }, - }], 'vue/singleline-html-element-content-newline': 'off', 'no-param-reassign': 'off', 'import/prefer-default-export': 'off', @@ -97,7 +74,7 @@ module.exports = { 'no-redeclare': 'off', '@typescript-eslint/no-redeclare': ['error'], 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-vars': ['error', { ignoreRestSiblings: true }], + '@typescript-eslint/no-unused-vars': ['error', { ignoreRestSiblings: true, argsIgnorePattern: '^_' }], 'no-use-before-define': 'off', '@typescript-eslint/no-use-before-define': ['error'], 'no-dupe-class-members': 'off', @@ -113,6 +90,7 @@ module.exports = { '@typescript-eslint/ban-ts-comment': 'off', '@typescript-eslint/ban-types': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/consistent-type-imports': ['error', { disallowTypeAnnotations: false }], 'simple-import-sort/imports': 'error', 'simple-import-sort/exports': 'error', }, diff --git a/.github/DISCUSSION_TEMPLATE/community-extensions.yml b/.github/DISCUSSION_TEMPLATE/community-extensions.yml index dea87b642e..81af9fcc1e 100644 --- a/.github/DISCUSSION_TEMPLATE/community-extensions.yml +++ b/.github/DISCUSSION_TEMPLATE/community-extensions.yml @@ -1,4 +1,4 @@ -title: "Community Extension: " +title: 'Community Extension: ' body: - type: markdown attributes: @@ -9,7 +9,7 @@ body: attributes: label: Description description: Please describe how your extension works and what it does. - placeholder: "My extension does …" + placeholder: 'My extension does …' validations: required: true - type: textarea @@ -17,7 +17,7 @@ body: attributes: label: Installation description: Please describe how users can install your extension. - placeholder: "npm install …" + placeholder: 'npm install …' validations: required: true - type: textarea @@ -25,7 +25,7 @@ body: attributes: label: Usage description: Please describe how users can use your extension in their editor. - placeholder: "To use my extension you have to …" + placeholder: 'To use my extension you have to …' validations: required: true - type: dropdown @@ -34,11 +34,11 @@ body: label: Type description: Please select the type of this extension. options: - - "Node" - - "Mark" - - "Prosemirror plugin" - - "Package or Kit" - - "Other" + - 'Node' + - 'Mark' + - 'Prosemirror plugin' + - 'Package or Kit' + - 'Other' validations: required: true - type: textarea @@ -46,6 +46,6 @@ body: attributes: label: Other description: Feel free to add any other information about your extension. - placeholder: "I hope you like …" + placeholder: 'I hope you like …' validations: required: false diff --git a/.github/DISCUSSION_TEMPLATE/feature-requests.yml b/.github/DISCUSSION_TEMPLATE/feature-requests.yml index c7d3864dc1..e5e99c0d83 100644 --- a/.github/DISCUSSION_TEMPLATE/feature-requests.yml +++ b/.github/DISCUSSION_TEMPLATE/feature-requests.yml @@ -1,6 +1,6 @@ -title: "Feature Request: " +title: 'Feature Request: ' labels: - - "Type: Feature Request" + - 'Type: Feature Request' body: - type: markdown attributes: @@ -11,7 +11,7 @@ body: attributes: label: Description description: Please describe the feature you would like to see in Tiptap. - placeholder: "I wish there was an extension for …" + placeholder: 'I wish there was an extension for …' validations: required: true - type: textarea @@ -19,7 +19,7 @@ body: attributes: label: Use Case description: Please describe the use case for this feature. - placeholder: "I want to use this feature for …" + placeholder: 'I want to use this feature for …' validations: required: true - type: dropdown @@ -28,9 +28,9 @@ body: label: Type description: Please select the type of this feature. options: - - "New extension" - - "New feature" - - "New Tiptap API" - - "Other" + - 'New extension' + - 'New feature' + - 'New Tiptap API' + - 'Other' validations: required: true diff --git a/.github/DISCUSSION_TEMPLATE/showcase.yml b/.github/DISCUSSION_TEMPLATE/showcase.yml index 25b3af32bf..6f4b367b9a 100644 --- a/.github/DISCUSSION_TEMPLATE/showcase.yml +++ b/.github/DISCUSSION_TEMPLATE/showcase.yml @@ -1,4 +1,4 @@ -title: "Community Extension: " +title: 'Community Extension: ' body: - type: markdown attributes: @@ -9,7 +9,7 @@ body: attributes: label: Description description: Please describe what your project is about - placeholder: "My project is about …" + placeholder: 'My project is about …' validations: required: true - type: input @@ -17,7 +17,7 @@ body: attributes: label: URL description: If possible share the URL of your project. - placeholder: "https://example.com" + placeholder: 'https://example.com' validations: required: false - type: textarea @@ -25,7 +25,7 @@ body: attributes: label: About description: Feel free to talk about how you used Tiptap in your project, what you liked about it, what you didn't like about it, and what you would like to see in the future. - placeholder: "If used Tiptap to …" + placeholder: 'If used Tiptap to …' validations: required: true - type: dropdown @@ -34,12 +34,12 @@ body: label: Type description: Please select the type of your project. options: - - "Chat Application" - - "Commenting Application" - - "Content Management System" - - "Document Editor" - - "Document Editor with Collaboration" - - "Other" + - 'Chat Application' + - 'Commenting Application' + - 'Content Management System' + - 'Document Editor' + - 'Document Editor with Collaboration' + - 'Other' validations: required: true - type: textarea @@ -47,6 +47,6 @@ body: attributes: label: Other description: Feel free to add any other information about your project. - placeholder: "I hope you like …" + placeholder: 'I hope you like …' validations: required: false diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 586a94c3c9..34953f6145 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,14 +1,13 @@ name: Bug Report -title: "[Bug]: " description: Found a bug in the editor core or one of the extensions? Report it here to help us improve. -labels: - - "Type: Bug" - - "Category: Open Source" - - "Status: New" + +labels: ["Open Source", "Needs Triage"] +type: "Bug" + body: - type: markdown attributes: - value: "### Please provide details to help us diagnose the bug." + value: '### Please provide details to help us diagnose the bug.' - type: input id: packages attributes: @@ -30,7 +29,7 @@ body: attributes: label: Bug Description description: Provide a clear and concise description of what the bug is. - placeholder: "The issue occurs when..." + placeholder: 'The issue occurs when...' validations: required: true - type: dropdown @@ -59,7 +58,7 @@ body: id: sandbox attributes: label: Code Example URL - description: "Link a CodeSandbox, Stackblitz, GitHub repository, or similar to help us reproduce the issue faster." + description: 'Link a CodeSandbox, Stackblitz, GitHub repository, or similar to help us reproduce the issue faster.' placeholder: https://codesandbox.io/s/example validations: required: false @@ -74,14 +73,14 @@ body: id: context attributes: label: Additional Context (Optional) - description: "Add any other context about the problem here, such as screenshots or videos." + description: 'Add any other context about the problem here, such as screenshots or videos.' - type: checkboxes attributes: label: Dependency Updates - description: "Have you updated your dependencies? This can often resolve issues." + description: 'Have you updated your dependencies? This can often resolve issues.' options: - label: Yes, I've updated all my dependencies. required: true - type: markdown attributes: - value: "Thank you for helping us improve our open-source projects by reporting this issue!" + value: 'Thank you for helping us improve our open-source projects by reporting this issue!' diff --git a/.github/ISSUE_TEMPLATE/bug_report_pro.yml b/.github/ISSUE_TEMPLATE/bug_report_pro.yml index 69ab73dc84..ad646eff05 100644 --- a/.github/ISSUE_TEMPLATE/bug_report_pro.yml +++ b/.github/ISSUE_TEMPLATE/bug_report_pro.yml @@ -1,14 +1,13 @@ name: Bug Report (Tiptap Pro) -title: "[PRO]: " description: If you've encountered a bug with Tiptap Pro features, please report it here. -labels: - - "Type: Bug" - - "Category: Pro" - - "Status: New" + +labels: ["Pro", "Needs Triage"] +type: "Bug" + body: - type: markdown attributes: - value: "### Please ensure this issue is for Tiptap Pro features only. Provide as much detail as possible to help us identify the issue quickly." + value: '### Please ensure this issue is for Tiptap Pro features only. Provide as much detail as possible to help us identify the issue quickly.' - type: input id: packages attributes: @@ -30,7 +29,7 @@ body: attributes: label: Description of the Bug description: Provide a clear and concise description of what the bug is. - placeholder: "The issue occurs when..." + placeholder: 'The issue occurs when...' validations: required: true - type: dropdown @@ -48,10 +47,10 @@ body: required: true - type: markdown attributes: - value: "### Helpful Code Examples" + value: '### Helpful Code Examples' - type: markdown attributes: - value: "Providing a CodeSandbox link is crucial for diagnosing issues faster. Below are templates you might use:" + value: 'Providing a CodeSandbox link is crucial for diagnosing issues faster. Below are templates you might use:' - type: markdown attributes: value: | @@ -63,7 +62,7 @@ body: id: sandbox attributes: label: Code Example (Preferred) - description: "Provide a link to a CodeSandbox or other code repository to help us reproduce the issue." + description: 'Provide a link to a CodeSandbox or other code repository to help us reproduce the issue.' placeholder: https://codesandbox.io/s/example validations: required: false @@ -78,14 +77,14 @@ body: id: context attributes: label: Additional Context (Optional) - description: "Add any other context about the problem here, like screenshots or videos." + description: 'Add any other context about the problem here, like screenshots or videos.' - type: checkboxes attributes: label: Dependency Updates - description: "Have you updated your dependencies? It can often resolve issues." + description: 'Have you updated your dependencies? It can often resolve issues.' options: - label: Yes, I've updated all my dependencies. required: true - type: markdown attributes: - value: "Thank you for contributing to Tiptap Pro by reporting this issue!" + value: 'Thank you for contributing to Tiptap Pro by reporting this issue!' diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml index 7831b4595b..b9eeda0be0 100644 --- a/.github/ISSUE_TEMPLATE/documentation.yml +++ b/.github/ISSUE_TEMPLATE/documentation.yml @@ -1,10 +1,10 @@ name: Documentation feedback description: Share what we need to explain better. -title: "[Documentation]: " +title: '[Documentation]: ' labels: - - "Type: Documentation" - - "Category: Open Source" - - "Status: New" + - 'Type: Documentation' + - 'Category: Open Source' + - 'Status: New' body: - type: input id: url @@ -17,28 +17,28 @@ body: id: part-of-the-documentation attributes: label: What part of the documentation needs improvement? - placeholder: "I’ve read the following page of the documentation …" + placeholder: 'I’ve read the following page of the documentation …' validations: required: true - type: textarea id: good-parts attributes: label: What is helpful about that part? - placeholder: "I think this part is really good: …" + placeholder: 'I think this part is really good: …' validations: required: true - type: textarea id: bad-parts attributes: label: What is hard to understand, missing or misleading? - placeholder: "But you really need to improve …" + placeholder: 'But you really need to improve …' validations: required: true - type: textarea id: context attributes: label: Anything to add? (optional) - description: "Add any other context or screenshots here." + description: 'Add any other context or screenshots here.' - type: markdown attributes: value: | diff --git a/.github/assets/cover.png b/.github/assets/cover.png new file mode 100644 index 0000000000..2bd9053f10 Binary files /dev/null and b/.github/assets/cover.png differ diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 375ab47abf..7000b357c1 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,7 +3,6 @@ version: 2 updates: - - package-ecosystem: 'github-actions' directory: '/' open-pull-requests-limit: 10 @@ -12,4 +11,3 @@ updates: day: 'monday' reviewers: - 'bdbch' - diff --git a/.github/instructions/PR.instructions.md b/.github/instructions/PR.instructions.md new file mode 100644 index 0000000000..45ca6ce3c1 --- /dev/null +++ b/.github/instructions/PR.instructions.md @@ -0,0 +1,43 @@ +--- +applyTo: '**' +--- + +When asked to write a pull request description, use the following template: + +``` +## Changes Overview + + + +## Implementation Approach + + + +## Testing Done + + + +## Verification Steps + + + +## Additional Notes + + + +## Checklist + +- [ ] I have created a [changeset](https://github.com/changesets/changesets) for this PR if necessary. +- [ ] My changes do not break the library. +- [ ] I have added tests where applicable. +- [ ] I have followed the project guidelines. +- [ ] I have fixed any lint issues. + +## Related Issues + + +``` + +When generating the pull request description, ensure it is clear, concise, and follows the provided template. Focus on the key aspects of the changes made, how they were implemented, and how they can be verified. + +Make it as minimal as possible to convey the necessary information effectively without causing to much noise and making it hard to read. diff --git a/.github/instructions/changeset.instructions.md b/.github/instructions/changeset.instructions.md new file mode 100644 index 0000000000..0c22a4da51 --- /dev/null +++ b/.github/instructions/changeset.instructions.md @@ -0,0 +1,9 @@ +--- +applyTo: '**' +--- + +When a user asks for a changeset to be generated, follow the following rules: + +Create a good changeset file for the changes in the diff. Don't include non-frontfacing changes, as the changeset file will be used for the changelog. Our users don't care about deep logic that they'll not interact with so we only want to generate changelog entries for front-facing/user-facing changes and API changes our users will need to know about. + +Make sure that the changeset file stays minimal and short but includes important information that may be important for our users to understand what actually changed. diff --git a/.github/instructions/tiptap.instructions.md b/.github/instructions/tiptap.instructions.md new file mode 100644 index 0000000000..d876570d80 --- /dev/null +++ b/.github/instructions/tiptap.instructions.md @@ -0,0 +1,228 @@ +--- +applyTo: '**' +--- + +# Tiptap + +This document explains how to work on the Tiptap monorepo in VS Code. It covers repo layout, local dev, linting and formatting, tests, docs, and release workflow. It is written to be friendly for both humans and AI coding assistants. + +--- + +## What is Tiptap + +Tiptap is a headless rich text editor toolkit built on ProseMirror. It ships a small Core and many opt-in Extensions so you can compose exactly the editor you need for React, Vue, or vanilla apps. The project is optimized for user experience and developer experience. APIs are predictable, behavior is testable, and everything should be documented with JSDoc and runnable examples so we can generate API docs automatically. + +Key points for AI assistants: + +* Treat Tiptap as a collection of focused packages that together form an editor system. +* Do not assume a single framework. Many packages are framework agnostic, with separate bindings for React and Vue. +* Favor small pure utilities and deterministic code. Side effects should be explicit. + +--- + +## Repository layout + +``` +. +├─ packages/ # Core and all first-party extensions +│ ├─ core/ # Editor core (@tiptap/core) +│ ├─ extension-*/ # Individual extensions +│ ├─ pm/ # ProseMirror related internals and helpers +│ └─ ... # Shared utilities, framework bindings, etc. +├─ demos/ # Vite app for live examples +│ ├─ react/ # React demos +│ └─ vue/ # Vue demos +├─ tests/ # Cypress e2e tests that run against the demos +├─ .changeset/ # Changesets for versioning and changelogs +└─ .github/ # Workflows and docs like this file +``` + +Notes: + +* All packages we publish or use live under `packages/*`. +* The `demos/` folder contains a Vite app. It automatically discovers and parses React and Vue demos so they appear in the UI without manual wiring. +* Cypress tests in `tests/` expect the demos to be available on `http://localhost:3000`. + +## NPM scripts + +Scripts defined at the repo root: + +* `pnpm dev` - start the demos on port 3000 +* `pnpm build` - build all packages via Turborepo +* `pnpm lint` - run eslint checks +* `pnpm lint:fix` - run prettier + eslint fix +* `pnpm test:open` - open Cypress against `tests/` +* `pnpm test:run` - run Cypress in headless mode +* `pnpm test` - build then run all tests +* `pnpm serve` - build and serve the demos on port 3000 +* `pnpm publish` - build and publish with Changesets +* `pnpm reset` - remove caches, build artifacts, and reinstall deps + +--- + +## Linting & formatting + +* ESLint config is at **`.eslintrc.js`** in the repo root. +* Prettier config is at **`.prettierrc`** (or `prettier.config.json`). +* Husky and lint-staged run automatically on commits. + +Run manually: + +```bash +pnpm lint +pnpm lint:fix +``` + +--- + +## Demos + +* Demos are a Vite app in `demos/`. +* React and Vue examples live in `demos/react` and `demos/vue`. They are automatically parsed into the app. +* Start in dev mode: + + ```bash + pnpm dev + ``` +* Build static output and serve locally: + + ```bash + pnpm serve + ``` + +When adding a demo, keep it small and self-contained, with imports from published package names (`@tiptap/...`). + +--- + +## Testing with Cypress + +* Cypress lives in `tests/` and drives the demos in a browser. +* Tests assume the app is running on `http://localhost:3000`. + +Workflow: + +```bash +pnpm dev # terminal A +pnpm test:open # terminal B +``` + +or for headless CI runs: + +```bash +pnpm test:run +``` + +--- + +## Documentation style + +We focus heavily on **User Experience** and **Developer Experience**. Every public API must be documented with JSDoc, including: + +* `@param` and `@returns` annotations +* Argument descriptions +* At least one runnable example + +This ensures our automated API docs are complete and examples are usable without extra context. + +Example: + +````ts +/** + * Toggle bold mark on the current selection. + * + * Example + * ```ts + * editor.chain().focus().toggleBold().run() + * ``` + * + * @param editor - The editor instance + * @returns true if the command was applied + */ +export function toggleBold(editor: Editor): boolean { + // ... +} +```` + +--- + +## Versioning and releases with Changesets + +* Run `pnpm changeset` to create a new changeset (choose packages + bump type). +* Run `pnpm version` to update versions and changelogs. +* Maintainers publish with `pnpm publish`. + +Changelogs must describe **user-facing changes**. Avoid internal noise. + +--- + +## Cleaning and resetting + +* `pnpm run clean:packages` - remove build artifacts +* `pnpm run clean:packs` - remove generated tarballs +* `pnpm reset` - full reset of caches, node\_modules, and lockfiles + +--- + +## Principles + +* Keep packages modular and framework-agnostic where possible. +* Breaking changes require a major bump and a clear migration path. +* Always add or update demos and tests when introducing a feature. +* Code should be deterministic, documented, and tested. + +--- + +## Extra guidance (short additions) + +To make these instructions easier for automated agents and new contributors, the sections below add a few operational details and guardrails that speed up safe, repeatable changes. + +### Environment + +- Recommended Node version: >=18.x. Use a node version manager (nvm, fnm) or Corepack to pin a runtime. +- Recommended package manager: pnpm (use the repo's lockfile). If you see unexpected errors, run `pnpm reset`. + +### Where to edit packages + +Packages live under `packages/*`. Public entry points are typically `packages//src/index.ts` and are referenced by the package's `package.json` (`main`/`module`/`exports`). Prefer editing `src/` files and keep package diffs focused. For framework bindings check `packages/react/` and `packages/vue-2/` or `packages/vue-3/`. + +### Demos auto-discovery rules + +The demos app discovers examples automatically. When adding a demo: +- Keep demo files small and self-contained. Import from published package names (for example `@tiptap/extension-foo`). +- Name demo files clearly; follow existing naming conventions in `demos/`. + +### Validation checklist (run locally before opening a PR) + +Run the following to validate changes quickly: + +```bash +pnpm lint +pnpm build +pnpm test # runs unit and/or cypress where configured +pnpm dev # optionally run the demos and open http://localhost:3000 +``` + +If a single package is failing types, run a targeted build for that package (e.g. `pnpm -w -F @tiptap/core build`), or run `pnpm build` at the repo root. + +### PR checklist + +- All checks pass (lint/build/tests). +- Changeset added for user-facing changes (`pnpm changeset`). +- Demo added/updated for UI-visible changes. +- Short, clear PR description and changelog entry that explains why the change is needed. + +### Guidance for automated agents and AI assistants + +- Make single-purpose, small diffs. Avoid sweeping changes in one PR. +- Always run the validation checklist above after edits. +- Add or update a demo and tests for user-visible behavior. For deterministic behaviour, favour unit tests over fragile e2e tests where possible. +- Add a Changeset for any user-facing change. Do not change public APIs without a major bump; document migration steps in the PR description. + +### Troubleshooting notes + +- If CI fails with dependency or lockfile errors, run `pnpm reset` locally and re-run the build. +- For flaky Cypress tests, run the demo locally with `pnpm dev` and reproduce the failing test in `pnpm test:open`. + +--- + +These additions are intentionally short so they are easy to follow and scriptable by tools and agents. If you'd like, I can apply a slightly different tone or expand any section into more detail (for example, exact node/pnpm version pinning or demo naming patterns). diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f3eea948d9..93766d19df 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,19 +1,25 @@ ## Changes Overview + ## Implementation Approach + ## Testing Done + ## Verification Steps + ## Additional Notes + ## Checklist + - [ ] I have created a [changeset](https://github.com/changesets/changesets) for this PR if necessary. - [ ] My changes do not break the library. - [ ] I have added tests where applicable. @@ -21,4 +27,5 @@ - [ ] I have fixed any lint issues. ## Related Issues + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index df5f21db74..91ea9dec56 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,6 +3,9 @@ name: build +env: + PNPM_VERSION: 9.15.4 + concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true @@ -12,7 +15,6 @@ on: branches: - main - develop - - next - release/* tags: - '*' @@ -20,10 +22,9 @@ on: branches: - main - develop - - next jobs: - lint: + build: runs-on: ubuntu-latest strategy: @@ -31,84 +32,157 @@ jobs: node-version: [20] steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v6 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.1.0 with: node-version: ${{ matrix.node-version }} + cache: 'pnpm' - - name: Load cached dependencies - uses: actions/cache@v4.2.3 - id: cache + - name: Load turbo cache + uses: actions/cache@v5.0.2 + id: turbo-cache with: path: | - **/node_modules - **/.turbo - /home/runner/.cache/Cypress - key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }} + .turbo + **/.eslintcache + key: ${{ runner.os }}-turbo-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-turbo-${{ github.sha }} + ${{ runner.os }}-turbo- - name: Install dependencies id: install-dependencies - if: steps.cache.outputs.cache-hit != 'true' - run: npm install - - # - name: Fix code style linting errors - # id: lint-fix - # run: npm run lint:fix - # continue-on-error: true - # - # - name: Commit fixed linting errors - # id: commit - # uses: stefanzweifel/git-auto-commit-action@v4 - # with: - # commit_message: "ci: fix code style linting errors" + run: pnpm install - name: Lint code - id: lint - run: npm run lint + run: pnpm run lint + + - name: Try to build the packages + id: build-packages + run: pnpm run build + + - name: Pack build artifact + run: tar -czf /tmp/build-output.tar.gz --exclude=node_modules packages/*/dist packages-deprecated/*/dist + + - name: Upload build artifact + uses: actions/upload-artifact@v4.6.2 + with: + name: build-output + path: /tmp/build-output.tar.gz + retention-days: 1 + + unit-test: + runs-on: ubuntu-latest + + needs: build + + strategy: + matrix: + node-version: [20] + + steps: + - uses: actions/checkout@v6 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4.1.0 + with: + node-version: ${{ matrix.node-version }} + cache: 'pnpm' + + - name: Install dependencies + id: install-dependencies + run: pnpm install + + - name: Download build artifact + uses: actions/download-artifact@v4.3.0 + with: + name: build-output + path: /tmp + + - name: Restore build output + run: tar -xzf /tmp/build-output.tar.gz + + - name: Run unit tests + id: unit-tests + run: pnpm run test:unit test: runs-on: ubuntu-latest + needs: [build, unit-test] + strategy: matrix: node-version: [20] test-spec: - - { name: "Integration", spec: "./tests/cypress/integration/**/*.spec.{js,ts}" } - #- { name: "Demos/Commands", spec: "./demos/src/Commands/**/*.spec.{js,ts}" } - - { name: "Demos/Examples", spec: "./demos/src/Examples/**/*.spec.{js,ts}" } - - { name: "Demos/Experiments", spec: "./demos/src/Experiments/**/*.spec.{js,ts}" } - - { name: "Demos/Extensions", spec: "./demos/src/Extensions/**/*.spec.{js,ts}" } - - { name: "Demos/GuideContent", spec: "./demos/src/GuideContent/**/*.spec.{js,ts}" } - - { name: "Demos/GuideGettingStarted", spec: "./demos/src/GuideGettingStarted/**/*.spec.{js,ts}" } - #- { name: "Demos/GuideNodeViews", "./demos/src/GuideNodeViews/**/*.spec.{js,ts}" } - - { name: "Demos/Marks", spec: "./demos/src/Marks/**/*.spec.{js,ts}" } - - { name: "Demos/Nodes", spec: "./demos/src/Nodes/**/*.spec.{js,ts}" } - #- { name: "Demos/Overview", spec: "./demos/src/Overview/**/*.spec.{js,ts}" } + - { id: 'integration', name: 'Integration', spec: './tests/cypress/integration/**/*.spec.{js,ts}' } + - { id: 'demos-commands', name: 'Demos/Commands', spec: './demos/src/Commands/**/*.spec.{js,ts}' } + - { id: 'demos-examples', name: 'Demos/Examples', spec: './demos/src/Examples/**/*.spec.{js,ts}' } + - { id: 'demos-experiments', name: 'Demos/Experiments', spec: './demos/src/Experiments/**/*.spec.{js,ts}' } + - { id: 'demos-extensions', name: 'Demos/Extensions', spec: './demos/src/Extensions/**/*.spec.{js,ts}' } + - { id: 'demos-guidecontent', name: 'Demos/GuideContent', spec: './demos/src/GuideContent/**/*.spec.{js,ts}' } + - { id: 'demos-guidegettingstarted', name: 'Demos/GuideGettingStarted', spec: './demos/src/GuideGettingStarted/**/*.spec.{js,ts}' } + #- { id: 'demos-guidenodeviews', name: "Demos/GuideNodeViews", spec: "./demos/src/GuideNodeViews/**/*.spec.{js,ts}" } + - { id: 'demos-marks', name: 'Demos/Marks', spec: './demos/src/Marks/**/*.spec.{js,ts}' } + - { id: 'demos-nodes', name: 'Demos/Nodes', spec: './demos/src/Nodes/**/*.spec.{js,ts}' } + #- { id: 'demos-overview', name: "Demos/Overview", spec: "./demos/src/Overview/**/*.spec.{js,ts}" } steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v6 + - name: Load build cache + uses: actions/cache@v5.0.2 + id: cache + with: + path: | + ./demos/node_modules/.vite + /home/runner/.cache/Cypress + key: ${{ runner.os }}-build-${{ matrix.test-spec.id }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-build-${{ matrix.test-spec.id }}-${{ github.sha }} + ${{ runner.os }}-build-${{ matrix.test-spec.id }}- + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.1.0 with: node-version: ${{ matrix.node-version }} + cache: 'pnpm' - name: Install dependencies id: install-dependencies - run: npm install + run: pnpm install --strict-peer-dependencies && pnpm exec cypress install - - name: Try to build the packages - id: build-packages - run: npm run build:pm + - name: Download build artifact + uses: actions/download-artifact@v4.3.0 + with: + name: build-output + path: /tmp + + - name: Restore build output + run: tar -xzf /tmp/build-output.tar.gz - name: Test ${{ matrix.test-spec.name }} id: cypress - uses: cypress-io/github-action@v6.7.16 + uses: cypress-io/github-action@v6.10.2 with: - cache-key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }} - start: npm run serve + cache-key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/pnpm-lock.yaml') }} + start: pnpm run serve wait-on: 'http://localhost:3000' spec: ${{ matrix.test-spec.spec }} project: ./tests @@ -119,7 +193,7 @@ jobs: uses: actions/upload-artifact@v4.6.2 if: failure() with: - name: cypress-screenshots + name: cypress-screenshots-${{ matrix.test-spec.id }} path: tests/cypress/screenshots retention-days: 7 @@ -127,46 +201,46 @@ jobs: uses: actions/upload-artifact@v4.6.2 if: failure() with: - name: cypress-videos + name: cypress-videos-${{ matrix.test-spec.id }} path: tests/cypress/videos retention-days: 7 - build: + release: runs-on: ubuntu-latest - needs: lint - strategy: matrix: node-version: [20] + needs: [test, unit-test] + steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v6 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.0.0 + - name: Install pnpm + uses: pnpm/action-setup@v4 with: - node-version: ${{ matrix.node-version }} + version: ${{ env.PNPM_VERSION }} - - name: Load cached dependencies - uses: actions/cache@v4.2.3 - id: cache + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4.1.0 with: - path: | - **/node_modules - **/.turbo - /home/runner/.cache/Cypress - key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }} + node-version: ${{ matrix.node-version }} + cache: 'pnpm' - name: Install dependencies id: install-dependencies - if: steps.cache.outputs.cache-hit != 'true' - run: npm install + run: pnpm install - - name: Try to build the packages - id: build-packages - run: npm run build:ci + - name: Download build artifact + uses: actions/download-artifact@v4.3.0 + with: + name: build-output + path: /tmp + + - name: Restore build output + run: tar -xzf /tmp/build-output.tar.gz - name: Soft release id: soft-release - run: npx pkg-pr-new publish './packages/*' --compact + run: pnpm exec pkg-pr-new publish './packages/*' './packages-deprecated/*' --compact diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml deleted file mode 100644 index 7886bb3115..0000000000 --- a/.github/workflows/issues.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Add issues to Tiptap project - -on: - issues: - types: - - opened - -jobs: - add-to-project: - name: Add issue to project - runs-on: ubuntu-latest - steps: - - uses: actions/add-to-project@main - with: - project-url: ${{ secrets.ADD_TO_PROJECT_URL }} - github-token: ${{ secrets.ADD_TO_PROJECT_PAT }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ed6464bf11..4badc05f47 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,10 +1,13 @@ name: Publish +env: + PNPM_VERSION: 9.15.4 + on: push: branches: - main - - develop + - release/* # manual trigger for other branches workflow_dispatch: @@ -28,47 +31,59 @@ jobs: steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} - name: Setup Node ${{ matrix.node-version }} uses: actions/setup-node@v4 with: - node-version: ${{ matrix.node-version }} - registry-url: 'https://registry.npmjs.org/' + node-version: ${{ matrix.node-version }} + cache: 'pnpm' + + - name: Update npm for Trusted Publishing + run: npm install -g npm@11.6.2 - - name: Load cached dependencies - uses: actions/cache@v4.2.3 - id: cache + - name: Load turbo cache + uses: actions/cache@v5.0.2 + id: turbo-cache with: path: | - **/node_modules - **/.turbo - /home/runner/.cache/Cypress - key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }} + .turbo + **/.eslintcache + key: ${{ runner.os }}-turbo-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-turbo-${{ github.sha }} + ${{ runner.os }}-turbo- - name: Install Dependencies - run: npm ci + run: pnpm install --strict-peer-dependencies - name: Create Release PR or publish stable version to npm id: changesets uses: changesets/action@v1 with: createGithubReleases: false - publish: npm run publish - version: npm run version + publish: pnpm run publish + version: pnpm run version title: ${{ github.ref_name == 'main' && 'Publish a new stable version' || 'Publish a new pre-release version' }} commit: >- ${{ github.ref_name == 'main' && 'chore(release): publish a new release version' || 'chore(release): publish a new pre-release version' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} NPM_CONFIG_PROVENANCE: true + NPM_CONFIG_ACCESS: public - name: Send release notification if: steps.changesets.outputs.published == 'true' id: slack - uses: slackapi/slack-github-action@v1.27.0 + uses: slackapi/slack-github-action@v2.1.1 with: + webhook: ${{ secrets.SLACK_WEBHOOK_URL }} + webhook-type: incoming-webhook payload: | { "message": "[Tiptap Editor Release]: New Tiptap Editor version has been released to NPM." @@ -79,8 +94,10 @@ jobs: - name: Send failure notification if: failure() id: slack_failure - uses: slackapi/slack-github-action@v1.27.0 + uses: slackapi/slack-github-action@v2.1.1 with: + webhook: ${{ secrets.SLACK_WEBHOOK_URL }} + webhook-type: incoming-webhook payload: | { "message": "[Tiptap Editor Release]: There was an issue publishing a new version. You can find the logs here: https://github.com/ueberdosis/tiptap/actions/runs/${{ github.run_id }}" diff --git a/.github/workflows/release-to-discord.yml b/.github/workflows/release-to-discord.yml new file mode 100644 index 0000000000..ea4444e544 --- /dev/null +++ b/.github/workflows/release-to-discord.yml @@ -0,0 +1,24 @@ +name: Notify Discord on Release + +on: + release: + types: [published] + +jobs: + discord_notify: + name: Send release to Discord + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Post release to Discord (tsickert/discord-webhook) + uses: tsickert/discord-webhook@v7.0.0 + with: + webhook-url: ${{ secrets.DISCORD_RELEASES_STABLE_WEBHOOK }} + embed-title: ${{ github.event.release.name || github.event.release.tag_name }} + embed-description: ${{ github.event.release.body }} + embed-url: ${{ github.event.release.html_url }} + wait: true diff --git a/.gitignore b/.gitignore index bd129fe8f5..ed4df01ce8 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,13 @@ node_modules dist .env .env.* -.npmrc .eslintcache +.instructions +.agent + +docs + # Log files npm-debug.log* yarn-debug.log* @@ -33,8 +37,15 @@ tests/cypress/videos # packaged files packages/**/*.tgz +packages-deprecated/**/*.tgz demos/*.tgz # demo directories demos/src/Dev/** !demos/src/Dev/.gitkeep + +# instructions +.github/instructions/* +!.github/instructions/tiptap.instructions.md +!.github/instructions/changeset.instructions.md +!.github/instructions/PR.instructions.md diff --git a/.husky/pre-commit b/.husky/pre-commit index 26e0c553ee..21664ec323 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" -npm run lint:staged +pnpm run lint:staged diff --git a/.lintstagedrc.js b/.lintstagedrc.js deleted file mode 100644 index 1809afe22c..0000000000 --- a/.lintstagedrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - "./**/*.{ts,tsx,js,jsx,vue}": ["eslint --fix --quiet --no-error-on-unmatched-pattern"], -}; diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000000..beae5694f8 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +link-workspace-packages=deep +prefer-workspace-packages=true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..0186fd168d --- /dev/null +++ b/.prettierignore @@ -0,0 +1,12 @@ +**/.git +**/.svn +**/.hg +**/node_modules + +.turbo +.changeset +.github/**/* + +demos/dist/**/* +demos/node_modules/**/* +pnpm-lock.yaml diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000000..7e202150bf --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "trailingComma": "all", + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "arrowParens": "avoid", + "printWidth": 120 +} diff --git a/.vscode/settings.json b/.vscode/settings.json index b94d68021b..ffdb4c3610 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,13 +15,14 @@ "extension/code-block", "extension/code-block-lowlight", "extension/collaboration", - "extension/collaboration-cursor", + "extension/collaboration-caret", "extension/color", "extension/document", "extension/dropcursor", "extension/floating-menu", "extension/focus", "extension/font-family", + "extension/font-size", "extension/gapcursor", "extension/hard-break", "extension/heading", @@ -57,14 +58,17 @@ "vue-2", "vue-3" ], - "editor.defaultFormatter": "dbaeumer.vscode-eslint", + "editor.defaultFormatter": "esbenp.prettier-vscode", "[typescript]": { - "editor.defaultFormatter": "dbaeumer.vscode-eslint" + "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[javascript]": { - "editor.defaultFormatter": "dbaeumer.vscode-eslint" + "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[typescriptreact]": { - "editor.defaultFormatter": "dbaeumer.vscode-eslint" + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" } } diff --git a/CHANGELOG.md b/CHANGELOG.md index ab80259471..d381ead948 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,1132 +1,2046 @@ -# Change Log +# Releases -> **Important information** -> -> As of version 2.4.1 Tiptap uses **Changesets** which don't allow the generation of one generic CHANGELOG file. -> If you want to check changes of a specific package version, check the **CHANGELOG.md** file in the specific package -> directory or out [Github Releases](https://github.com/ueberdosis/tiptap/releases) +## v3.20.1 -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +### @tiptap/extension-code-block -# [2.4.0](https://github.com/ueberdosis/tiptap/compare/v2.3.2...v2.4.0) (2024-05-14) +#### Patch Changes +- Fix tilde-fenced code blocks (`~~~`) being silently dropped when parsing markdown -### Bug Fixes +### @tiptap/extension-drag-handle -* **core:** configure should use the parent of the current instance, to avoid duplication ([#5147](https://github.com/ueberdosis/tiptap/issues/5147)) ([4db463c](https://github.com/ueberdosis/tiptap/commit/4db463c6bbcc3a17ee8eb591bea8e357120ecb35)) -* fix ts error for BubbleMenu and FloatingMenu in @tiptap/react ([#5126](https://github.com/ueberdosis/tiptap/issues/5126)) ([baff4af](https://github.com/ueberdosis/tiptap/commit/baff4af39e2b8970d7cab99859ece41228643f9d)) +#### Patch Changes +- Fix Drag event listener is removed when a plugin is registered after the DragHandle plugin. -### Features +### @tiptap/extension-unique-id -* added jsdocs ([#4356](https://github.com/ueberdosis/tiptap/issues/4356)) ([b941eea](https://github.com/ueberdosis/tiptap/commit/b941eea6daba09d48a5d18ccc1b9a1d84b2249dd)) +#### Patch Changes +- Add support for `types: 'all'` in `UniqueID` to target every node type except `doc` and `text`. +### @tiptap/core +#### Patch Changes +- Fix inline `style` parsing in `mergeAttributes` for values containing `:` or `;` (e.g. `url(https://...)` or `url(data:...;charset=...,)`) and skip incomplete declarations -## [2.3.2](https://github.com/ueberdosis/tiptap/compare/v2.3.1...v2.3.2) (2024-05-08) +## v3.20.0 +### @tiptap/core -### Bug Fixes +#### Minor Changes -* NodePos querySelectorAll function ([#5094](https://github.com/ueberdosis/tiptap/issues/5094)) ([4900a27](https://github.com/ueberdosis/tiptap/commit/4900a27c5389d9a2d0d69f407ca3db0155304315)) +- Add `transformPastedHTML` extension API that allows extensions to transform pasted HTML content before it's parsed into the editor, enabling cleanup of styles, removal of dangerous content, and modification of pasted HTML through a chainable transform system. +#### Patch Changes +- Fix checking if mark is active and toggling off marks when part of the selection does not allow the mark (e.g. a code block) +- Global attributes now support shorthand string values for `types`: use `'*'` to apply to all nodes and marks, `'nodes'` for all nodes (excluding text), or `'marks'` for all marks. +- Fixed a typo in the documentation of `editor.view` +### @tiptap/extension-drag-handle +#### Patch Changes -## [2.3.1](https://github.com/ueberdosis/tiptap/compare/v2.3.0...v2.3.1) (2024-04-30) +- Fix drag handle not appearing for atom/leaf nodes like images in both nested and non-nested modes +- Add table structure rules to prevent drag handle on table rows, cells, and headers, and fix ghost table rows when dragging tables +- Fix drag position resolving outside the document when dragging an empty text node at the end of the document -**Note:** Version bump only for package tiptap +### @tiptap/markdown +#### Patch Changes +- Fixed getMarkdown() returning ` ` instead of empty string when editor is empty +### @tiptap/extension-bubble-menu +#### Patch Changes -# [2.3.0](https://github.com/ueberdosis/tiptap/compare/v2.2.6...v2.3.0) (2024-04-09) +- Fix `BubbleMenu`/`FloatingMenu` to use `pluginKey` as the transaction meta key so that multiple instances can be updated independently without affecting each other +### @tiptap/extension-floating-menu -### Bug Fixes +#### Patch Changes -* **core:** fix nodepos child lookup ([#5038](https://github.com/ueberdosis/tiptap/issues/5038)) ([22ced31](https://github.com/ueberdosis/tiptap/commit/22ced318723003365fbfd8f59b8dac79c7563017)) +- Fix `BubbleMenu`/`FloatingMenu` to use `pluginKey` as the transaction meta key so that multiple instances can be updated independently without affecting each other +### @tiptap/react -### Features +#### Minor Changes -* **core:** apply input and paste rules when using insertContent methods ([#5046](https://github.com/ueberdosis/tiptap/issues/5046)) ([96b6abc](https://github.com/ueberdosis/tiptap/commit/96b6abcf6edbc6cac03a391130d9feebb6de3a04)) +- Moved BubbleMenu and FloatingMenu to separate `@tiptap/react/menus` entrypoint to keep floating-ui optional +- Simplified Tiptap component API with guaranteed non-null editor instance from useTiptap hook +#### Patch Changes +- Fix `BubbleMenu`/`FloatingMenu` to use `pluginKey` as the transaction meta key so that multiple instances can be updated independently without affecting each other +### @tiptap/extension-code-block-lowlight +#### Patch Changes -## [2.2.6](https://github.com/ueberdosis/tiptap/compare/v2.2.5...v2.2.6) (2024-04-06) +- Fixed a runtime error when initializing `CodeBlockLowlight` by switching the `CodeBlock` import to a named export. This prevents `extend is not a function` errors caused by ESM/CJS interop issues. +### @tiptap/extension-invisible-characters -### Bug Fixes +#### Patch Changes -* unexpected renderText() for contentful nodes ([#3410](https://github.com/ueberdosis/tiptap/issues/3410)) ([d6c71a8](https://github.com/ueberdosis/tiptap/commit/d6c71a838d590f78fdff15c805d93f43c8a5a1a5)) +- Added missing storage typings +## v3.19.0 +### @tiptap/extension-link +#### Patch Changes +- Add `title` attribute to Link extension. The title can now be set via `setLink` and `toggleLink` commands and is rendered as an HTML title attribute. +- Add title attribute support for markdown rendering. Links with titles are now serialized to markdown format `[text](url "title")`. -## [2.2.5](https://github.com/ueberdosis/tiptap/compare/v2.2.4...v2.2.5) (2024-04-05) +### @tiptap/react +#### Minor Changes -### Bug Fixes +- Moved BubbleMenu and FloatingMenu to separate `@tiptap/react/menus` entrypoint to keep floating-ui optional +- Simplified Tiptap component API with guaranteed non-null editor instance from useTiptap hook -* Disallow only whitespace between markdown shortcuts delimiters ([#4866](https://github.com/ueberdosis/tiptap/issues/4866)) ([aa029fe](https://github.com/ueberdosis/tiptap/commit/aa029fe2242aeadc38555b2832df6ae1614c7d1d)) -* **extension-link:** Avoid auto-linking partial text for invalid TLDs ([#4865](https://github.com/ueberdosis/tiptap/issues/4865)) ([4474d05](https://github.com/ueberdosis/tiptap/commit/4474d056daf9280ebb10b31f98bb000e953132e5)) +## v3.18.0 +### @tiptap/extension-bubble-menu +#### Patch Changes +- Fix BubbleMenu and FloatingMenu props not updating after initialization +### @tiptap/extension-floating-menu -## [2.2.4](https://github.com/ueberdosis/tiptap/compare/v2.2.3...v2.2.4) (2024-02-23) +#### Patch Changes +- Fix BubbleMenu and FloatingMenu props not updating after initialization -### Bug Fixes +### @tiptap/react -* mark nocookie youtube url as valid when parsing html ([#4883](https://github.com/ueberdosis/tiptap/issues/4883)) ([099e10d](https://github.com/ueberdosis/tiptap/commit/099e10df923d851dd866354e9abca331d995b65c)) -* typecheck drag and clipboard events for testing environments ([bbee9a3](https://github.com/ueberdosis/tiptap/commit/bbee9a3c3090fa40bf366591682b42a3f6ec5f91)) +#### Minor Changes +- Introduce a new, optional React integration that provides a declarative `` component for setting up editors in React apps. + + Summary + - Add a new, ergonomic way to initialize and use Tiptap editors in React via `` components. This is an additive change and does not remove or change existing APIs. + + Why this change + - Improves ergonomics for React users by offering a component-first API that pairs well with React patterns (hooks, JSX composition and props-driven configuration). + + Migration and usage + - The old programmatic setup remains supported for this major version — nothing breaks. We encourage consumers to try the new `` component and migrate when convenient. + + Example + + ```tsx + import { Tiptap, useEditor } from '@tiptap/react' + + function MyEditor() { + const editor = useEditor({ extensions: [StarterKit], content: '

Hello from Tiptap

' }) + + return ( + + + My Bubble Menu + My Floating Menu + {/* MenuBar can use the new `useTiptap` hook to read the editor instance from context */} + + ) + } + ``` + + Deprecation plan + - The old imperative setup will remain fully backward-compatible for this major release. We plan to deprecate (and remove) the legacy setup in the next major version — a deprecation notice and migration guide will be published ahead of that change. +#### Patch Changes +- Fix BubbleMenu and FloatingMenu props not updating after initialization +- Fixed extension storage not updating in React and Vue node views +### @tiptap/vue-3 -## [2.2.3](https://github.com/ueberdosis/tiptap/compare/v2.2.2...v2.2.3) (2024-02-15) +#### Patch Changes +- Fixed extension storage not updating in React and Vue node views -### Bug Fixes +### @tiptap/markdown -* fix test path ([21aa96d](https://github.com/ueberdosis/tiptap/commit/21aa96dee8deab1f439b7f655b8ed266a516a4cd)) +#### Patch Changes +- Upgrade marked.js from v15.0.12 to v17.0.1. Note that `**)**` requires whitespace when adjacent to alphanumeric text per CommonMark specification. +### @tiptap/extensions +#### Patch Changes +- Added a new `dataAttribute` to the extension option to control which attribute name will be used for the placeholder label. -## [2.2.2](https://github.com/ueberdosis/tiptap/compare/v2.2.1...v2.2.2) (2024-02-07) +## v3.17.1 +### @tiptap/extension-paragraph -### Bug Fixes +#### Patch Changes -* **react:** use ref instead of state in useEditor to prevent rerenders ([#4856](https://github.com/ueberdosis/tiptap/issues/4856)) ([56a5737](https://github.com/ueberdosis/tiptap/commit/56a5737ed102ee75ec72f9cc2847e3c977f431bd)) +- Fixed markdown serialization doubling newlines and parsing collapsing multiple blank lines +### @tiptap/markdown +#### Patch Changes +- Fixed markdown serialization doubling newlines and parsing collapsing multiple blank lines +- Fixed markdown HTML parsing when window object is unavailable in server-side environments +- Fixed ordered list numbering when list has a non-default start value +### @tiptap/vue-3 -## [2.2.1](https://github.com/ueberdosis/tiptap/compare/v2.2.0...v2.2.1) (2024-01-31) +#### Patch Changes -**Note:** Version bump only for package tiptap +- Fixed IME input (Chinese, Japanese, Korean) in Vue 3 mark views by preventing DOM element destruction during composition events +### @tiptap/extension-collaboration-caret +#### Patch Changes +- Fixed CollaborationCaret crash with "Cannot read properties of undefined (reading 'doc')" error by updating to @tiptap/y-tiptap@3.0.2, which includes a guard against undefined state during editor initialization. This issue affected editors initialized with HTML content, particularly when using tables. +### @tiptap/extension-collaboration -# [2.2.0](https://github.com/ueberdosis/tiptap/compare/v2.1.16...v2.2.0) (2024-01-29) +#### Patch Changes +- Fixed CollaborationCaret crash with "Cannot read properties of undefined (reading 'doc')" error by updating to @tiptap/y-tiptap@3.0.2, which includes a guard against undefined state during editor initialization. This issue affected editors initialized with HTML content, particularly when using tables. -### Bug Fixes +### @tiptap/extension-drag-handle -* **core:** fix new lines being added via elementFromString ([#4767](https://github.com/ueberdosis/tiptap/issues/4767)) ([b7a2504](https://github.com/ueberdosis/tiptap/commit/b7a2504f16f46563537c890930cb2c332c256175)) -* fix bug [#4785](https://github.com/ueberdosis/tiptap/issues/4785) ([#4836](https://github.com/ueberdosis/tiptap/issues/4836)) ([f3cba1e](https://github.com/ueberdosis/tiptap/commit/f3cba1e0b0288156c1427437e5a0b9e03cd67e63)) -* fix imports, fix demos, unpin y-prosemirror ([681aa57](https://github.com/ueberdosis/tiptap/commit/681aa577bff500015c3f925e300c55a71c73efaf)) -* fix newline stripping via insertContent ([8954007](https://github.com/ueberdosis/tiptap/commit/8954007b2b92b040d69b26a0866ae58fabf5e512)) +#### Patch Changes +- Fixed CollaborationCaret crash with "Cannot read properties of undefined (reading 'doc')" error by updating to @tiptap/y-tiptap@3.0.2, which includes a guard against undefined state during editor initialization. This issue affected editors initialized with HTML content, particularly when using tables. +### @tiptap/html -# [2.2.0-rc.8](https://github.com/ueberdosis/tiptap/compare/v2.1.14...v2.2.0-rc.8) (2024-01-08) +#### Patch Changes +- Fixed server-side HTML parsing crash when content contains link, script, or style tags with resource references. +- Fixed server exports failing in Node.js test environments with jsdom/happy-dom -### Bug Fixes +### @tiptap/extension-bubble-menu -* **core:** fix options now being empty ([fc67cb1](https://github.com/ueberdosis/tiptap/commit/fc67cb1b7166c1ab6b6e0174539c9e29c364eace)) +#### Patch Changes +- Fixed bubble and floating menus to properly handle hide middleware data, hiding menus when reference element is scrolled out of view +### @tiptap/extension-floating-menu -# [2.2.0-rc.7](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.6...v2.2.0-rc.7) (2023-11-27) +#### Patch Changes +- Fixed bubble and floating menus to properly handle hide middleware data, hiding menus when reference element is scrolled out of view -### Bug Fixes +### @tiptap/core -* **core:** set defaultOptions to undefined by default ([448b433](https://github.com/ueberdosis/tiptap/commit/448b433ee7847bfba4cd803d8c8820763ceedafc)) +#### Patch Changes +- Fixed `$nodes()` method to correctly return inline nodes (like text, mention, etc.) by fixing the `children` getter in `NodePos` class +- Fixed ResizableNodeView contentDOM getter to return null instead of undefined for proper TypeScript compatibility +### @tiptap/extension-list -# [2.2.0-rc.6](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.5...v2.2.0-rc.6) (2023-11-23) +#### Patch Changes +- Fixed ordered list numbering when list has a non-default start value -### Reverts +## v3.17.0 -* Revert "fix/react-renderer-node-attrs (#4321)" ([a4af83c](https://github.com/ueberdosis/tiptap/commit/a4af83ca52c8e020f88990af53981591559205a9)), closes [#4321](https://github.com/ueberdosis/tiptap/issues/4321) -* Revert "autolink improvement" ([ef10ae5](https://github.com/ueberdosis/tiptap/commit/ef10ae53b2a3854fceefc2999e166ed1fe4e9b32)) +### @tiptap/extension-bubble-menu +#### Patch Changes +- Added a safeguard to avoid `TypeError: Cannot read properties of null (reading 'domFromPos')` being thrown when the editor was being destroyed -# [2.2.0-rc.4](https://github.com/ueberdosis/tiptap/compare/v2.1.11...v2.2.0-rc.4) (2023-10-10) +### @tiptap/extension-drag-handle +#### Minor Changes -### Bug Fixes +- Added nested drag handle support, allowing drag handles to appear for nested content like list items and blockquotes with configurable edge detection and custom rules. -* add missing attributes in extension-link ([#4429](https://github.com/ueberdosis/tiptap/issues/4429)) ([0578265](https://github.com/ueberdosis/tiptap/commit/0578265bfe548a7f574cdbe055ef07b9029d8797)) -* **history:** use correct shortcuts for undo/redo ([520ce79](https://github.com/ueberdosis/tiptap/commit/520ce790c3dff2d0774211fe30fdce1905655b09)) +#### Patch Changes +- Fixed Firefox bug where the text caret becomes invisible after drag and drop. -### Features +### @tiptap/core -* **extension/youtube:** Allow youtube shorts urls to be embedded ([4d79cb8](https://github.com/ueberdosis/tiptap/commit/4d79cb85c93353cdb5ead518da63cf8f9fa71497)) +#### Patch Changes +- Added `isFirefox` utility to core +### @tiptap/extension-drag-handle-react -# [2.2.0-rc.3](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.2...v2.2.0-rc.3) (2023-08-18) +#### Minor Changes +- Added nested drag handle support, allowing drag handles to appear for nested content like list items and blockquotes with configurable edge detection and custom rules. +### @tiptap/extension-drag-handle-vue-2 -# [2.2.0-rc.1](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.0...v2.2.0-rc.1) (2023-08-18) +#### Minor Changes +- Added nested drag handle support, allowing drag handles to appear for nested content like list items and blockquotes with configurable edge detection and custom rules. +### @tiptap/extension-drag-handle-vue-3 -# [2.2.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.2.0-rc.0) (2023-08-18) +#### Minor Changes +- Added nested drag handle support, allowing drag handles to appear for nested content like list items and blockquotes with configurable edge detection and custom rules. -### Features +## v3.16.0 -* **placeholder:** allow editor-is-empty class on any node ([#4335](https://github.com/ueberdosis/tiptap/issues/4335)) ([ff929b1](https://github.com/ueberdosis/tiptap/commit/ff929b179de930619005a773bb4186ae2aa2ec58)) +### @tiptap/extension-audio +#### Minor Changes +- Add a native audio extension with demos and tests. +### @tiptap/markdown +#### Patch Changes -## [2.1.16](https://github.com/ueberdosis/tiptap/compare/v2.1.15...v2.1.16) (2024-01-10) +- Fix incorrect Markdown output when underline is mixed with bold or italic and their ranges do not fully overlap. +- Fix overlapping underline/bold/italic serialization and add tests +### @tiptap/extension-link -### Bug Fixes +#### Patch Changes -* **core:** fix new lines being added via elementFromString ([#4767](https://github.com/ueberdosis/tiptap/issues/4767)) ([2235908](https://github.com/ueberdosis/tiptap/commit/2235908c28f388eda041d1d5d017554d513fe909)) +- Fixed an issue where clicking on non-link elements (like images) required multiple clicks to select them. The link click handler now properly returns early when the clicked element is not a link, allowing other node handlers to process the click event. +### @tiptap/extension-floating-menu -### Reverts +#### Minor Changes -* Revert "fix(extension-link): fix link not being kept when pasting url with link (#3975)" ([1b34271](https://github.com/ueberdosis/tiptap/commit/1b34271edfdd6e81f670f9ddb15cd6838d986e9f)), closes [#3975](https://github.com/ueberdosis/tiptap/issues/3975) +- Add updateEvent support for FloatingMenu to allow programmatic position updates via `setMeta('floatingMenu', 'updatePosition')` +### @tiptap/react +#### Minor Changes +- Add updateEvent support for FloatingMenu to allow programmatic position updates via `setMeta('floatingMenu', 'updatePosition')` +### @tiptap/vue-2 -## [2.1.15](https://github.com/ueberdosis/tiptap/compare/v2.1.14...v2.1.15) (2024-01-08) +#### Minor Changes +- Add updateEvent support for FloatingMenu to allow programmatic position updates via `setMeta('floatingMenu', 'updatePosition')` -### Bug Fixes +### @tiptap/vue-3 -* **core:** fix insertContentAt keeping new lines in html content ([#4465](https://github.com/ueberdosis/tiptap/issues/4465)) ([135a12f](https://github.com/ueberdosis/tiptap/commit/135a12f7aa2df839a0b619704110a360b980c738)) -* **link:** fix tests ([d495d92](https://github.com/ueberdosis/tiptap/commit/d495d92a1f7b1c51e09ac8f4934e15a2d1cf070d)) +#### Minor Changes +- Add updateEvent support for FloatingMenu to allow programmatic position updates via `setMeta('floatingMenu', 'updatePosition')` -### Reverts +### @tiptap/extension-unique-id -* Revert "update package-lock" ([faead69](https://github.com/ueberdosis/tiptap/commit/faead6987337ea8471619fdc3124437954772a1a)) +#### Patch Changes +- Improved `findDuplicates` helper performance from O(n²) to O(n) by using Set-based lookups instead of Array.indexOf +## v3.15.3 +### @tiptap/core +#### Patch Changes -## [2.1.14](https://github.com/ueberdosis/tiptap/compare/v2.1.13...v2.1.14) (2024-01-08) +- Fix Safari scrolling to top when using editor.chain().focus() commands +## v3.15.2 -### Bug Fixes +### @tiptap/extension-link -* **typography:** require spaces after divisions to not break date formats ([#4696](https://github.com/ueberdosis/tiptap/issues/4696)) ([f6d7e00](https://github.com/ueberdosis/tiptap/commit/f6d7e00a746a67fa440a3fa0f5362295959873d2)) +#### Patch Changes +- Prevent auto-linking of bare hostnames (e.g., `localhost`) and IP addresses without a protocol prefix +### @tiptap/extension-list +#### Patch Changes +- Fix lost HTML attributes in TaskItem node view updates -## [2.1.13](https://github.com/ueberdosis/tiptap/compare/v2.1.12...v2.1.13) (2023-11-30) +### @tiptap/vue-2 -### Bug Fixes -* **react:** fix performance regression because of select/deselect ([#4661](https://github.com/ueberdosis/tiptap/issues/4661)) ([ad7f659](https://github.com/ueberdosis/tiptap/commit/ad7f659ed08a6a7c57056b78edbded014549f2dc)) +#### Patch Changes +- Fix Vue prop validation warning for `appendTo` prop in BubbleMenu and FloatingMenu +### @tiptap/vue-3 +#### Patch Changes +- Fix Vue prop validation warning for `appendTo` prop in BubbleMenu and FloatingMenu -## [2.1.12](https://github.com/ueberdosis/tiptap/compare/v2.1.11...v2.1.12) (2023-10-11) +### @tiptap/extension-youtube +#### Patch Changes -### Bug Fixes +- Fix YouTube Shorts embed URLs using incorrect query parameter separator -* **link:** restore pasteHandler and add existing url check ([#4523](https://github.com/ueberdosis/tiptap/issues/4523)) ([1a7b428](https://github.com/ueberdosis/tiptap/commit/1a7b4280d2f9c334d14b16016c29e9f4862716a0)) +### @tiptap/react +#### Patch Changes +- Fix race conditions in ReactRenderer causing destroyed renderers to be re-added in Strict Mode +## v3.15.1 +### @tiptap/suggestion -## [2.1.11](https://github.com/ueberdosis/tiptap/compare/v2.1.10...v2.1.11) (2023-09-20) +#### Patch Changes +- Add a new `shouldShow` callback to the `Suggestion` utility. This allows developers to filter when suggestions are displayed, which is especially useful for collaborative environments to prevent suggestions from popping open for remote users. -### Reverts +## v3.15.0 -* Revert "v2.2.11" ([6aa755a](https://github.com/ueberdosis/tiptap/commit/6aa755a04b9955fc175c7ab33dee527d0d5deef0)) +### @tiptap/core +#### Minor Changes +- Add a new `dispatchTransaction` hook to extensions, allowing developers to intercept, modify, or block transactions before they are applied to the editor state. +### @tiptap/extension-unique-id +#### Patch Changes -## [2.1.10](https://github.com/ueberdosis/tiptap/compare/v2.1.9...v2.1.10) (2023-09-15) +- Fix unique ID assignment when handling empty nodes by checking next node's attribute state in the transaction document before modifying it, preventing incorrect ID assignments. -**Note:** Version bump only for package tiptap +## v3.14.0 +### @tiptap/extension-twitch +#### Minor Changes +- Add new Twitch extension for embedding Twitch videos, clips, and live channels in the editor. Supports customizable parameters like autoplay, muted, and start time, with attribute-level overrides for per-embed configuration. +### @tiptap/react -## [2.1.9](https://github.com/ueberdosis/tiptap/compare/v2.1.8...v2.1.9) (2023-09-14) +#### Patch Changes +- Append all children of editors parent node to element + + Fixes a regression introduced by #6972, that resulted in elements that got appended to the editors parent node staying detached. E.g. the drag handle plugin is affected by this regression. -### Bug Fixes +### @tiptap/vue-2 -* add missing attributes in extension-link ([#4429](https://github.com/ueberdosis/tiptap/issues/4429)) ([74b6444](https://github.com/ueberdosis/tiptap/commit/74b644438829d6ee9b0795bc70c55f2755d7438c)) +#### Patch Changes +- Append all children of editors parent node to element + + Fixes a regression introduced by #6972, that resulted in elements that got appended to the editors parent node staying detached. E.g. the drag handle plugin is affected by this regression. +### @tiptap/vue-3 +#### Patch Changes +- Append all children of editors parent node to element + + Fixes a regression introduced by #6972, that resulted in elements that got appended to the editors parent node staying detached. E.g. the drag handle plugin is affected by this regression. -## [2.1.8](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.7...v2.1.8) (2023-09-04) +### @tiptap/extension-drag-handle -**Note:** Version bump only for package tiptap +#### Patch Changes +- Fix `findElementNextToCoords` to resolve the parent when `nodeAt(pos)` is null + (e.g., inside an atom node that allows inline content) +## v3.13.0 +### @tiptap/extension-drag-handle +#### Patch Changes -## [2.1.7](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.6...v2.1.7) (2023-09-04) +- Added `data-dragging` attribute to drag handle elements to track drag state. +### @tiptap/extension-drag-handle-react -### Bug Fixes +#### Patch Changes -* **horizontal-rule:** fix insertion being broken on empty docs ([#4375](https://github.com/ueberdosis/tiptap-workspace/issues/4375)) ([2a83166](https://github.com/ueberdosis/tiptap-workspace/commit/2a83166a46f97a9fc42ae23ce5367bb58bcdab74)) +- Added `data-dragging` attribute to drag handle elements to track drag state. +### @tiptap/extension-drag-handle-vue-2 +#### Patch Changes +- Added `data-dragging` attribute to drag handle elements to track drag state. +### @tiptap/extension-drag-handle-vue-3 -## [2.1.6](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.1.6) (2023-08-18) +#### Patch Changes +- Added `data-dragging` attribute to drag handle elements to track drag state. -### Bug Fixes +### @tiptap/extension-link -* **core:** fix broken export ([4227f32](https://github.com/ueberdosis/tiptap/commit/4227f324a5bfd4f0905c70ac8ea68903352f911b)) +#### Patch Changes +- Ensure `enableClickSelection` works regardless of the `openOnClick` option by always registering the link click handler plugin. +### @tiptap/extension-table-of-contents +#### Patch Changes +- Skip the table of contents update logic during IME input method composition to avoid interference with input. -## [2.1.5](https://github.com/ueberdosis/tiptap/compare/v2.1.4...v2.1.5) (2023-08-18) +### @tiptap/markdown +#### Patch Changes -### Bug Fixes +- Fixed trailing and leading whitespace handling in markdown serialization for inline marks -* **list-key-map:** fix broken imports ([#4350](https://github.com/ueberdosis/tiptap/issues/4350)) ([e40ac25](https://github.com/ueberdosis/tiptap/commit/e40ac2584e813893a61c91a456bdcd2cf6652b50)) +### @tiptap/extension-mention +#### Patch Changes +- Add 'mentionSuggestionChar' to allowedAttributes for Markdown serialization in multi-mention setups. The attribute is only serialized when it differs from the default '@' character, keeping markdown output clean for single-mention users. +### @tiptap/core +#### Minor Changes -## [2.1.4](https://github.com/ueberdosis/tiptap/compare/v2.1.3...v2.1.4) (2023-08-18) +- 1. **Added** an optional `createCustomHandle` callback to `ResizableNodeView`, allowing developers to fully customize resize handles. When provided, it replaces the default handle creation and bypasses the built-in `positionHandle` logic, giving complete control over markup, styling, and positioning while preserving backward compatibility. + 2. **Removed** predefined inline styles from the `wrapper` element to better support dynamic alignment. This eliminates the need for `!important` overrides in user styles. + 3. **Added** an editor `update` event listener to dynamically attach or remove resize handles based on the editor’s editable state. The implementation tracks the previous editable state to avoid unnecessary re-renders. +#### Patch Changes -### Bug Fixes +- Add 'mentionSuggestionChar' to allowedAttributes for Markdown serialization in multi-mention setups. The attribute is only serialized when it differs from the default '@' character, keeping markdown output clean for single-mention users. -* replace the whole node in nodeInputRule ([#4341](https://github.com/ueberdosis/tiptap/issues/4341)) ([ffeefe2](https://github.com/ueberdosis/tiptap/commit/ffeefe21ff3c1f951a5a4f9ae9697317ddd1c5ad)) +### @tiptap/extension-image +#### Minor Changes +- 1. **Added** an optional `createCustomHandle` callback to `ResizableNodeView`, allowing developers to fully customize resize handles. When provided, it replaces the default handle creation and bypasses the built-in `positionHandle` logic, giving complete control over markup, styling, and positioning while preserving backward compatibility. + 2. **Removed** predefined inline styles from the `wrapper` element to better support dynamic alignment. This eliminates the need for `!important` overrides in user styles. + 3. **Added** an editor `update` event listener to dynamically attach or remove resize handles based on the editor’s editable state. The implementation tracks the previous editable state to avoid unnecessary re-renders. +## v3.12.1 +### @tiptap/extension-table-of-contents -## [2.1.3](https://github.com/ueberdosis/tiptap/compare/v2.1.2...v2.1.3) (2023-08-18) +#### Patch Changes +- Fixed a bug that mutated the ProseMirror document during server-side rendering, which could cause "Invalid content for node doc" errors. -### Bug Fixes +## v3.12.0 -* fix autolink when code is not enabled for editor ([#4344](https://github.com/ueberdosis/tiptap/issues/4344)) ([f2ac7b9](https://github.com/ueberdosis/tiptap/commit/f2ac7b90912a78b90216a7d7d084c86f0c0eef48)) +### @tiptap/extension-collaboration +#### Minor Changes +- Implement position mapping using the `MappablePosition` class. This enables position mapping in collaborative editing scenarios. + + - Introduce `MappablePosition` class in core with `position`, `fromJSON`, and `toJSON` methods + - Add `editor.utils` property with `getUpdatedPosition(position, transaction)` and `createMappablePosition()` methods + - Create `CollaborationMappablePosition` subclass that extends `MappablePosition` with Y.js relative position support +### @tiptap/core +#### Minor Changes -## [2.1.2](https://github.com/ueberdosis/tiptap/compare/v2.1.1...v2.1.2) (2023-08-17) +- Implement position mapping using the `MappablePosition` class. This enables position mapping in collaborative editing scenarios. + + - Introduce `MappablePosition` class in core with `position`, `fromJSON`, and `toJSON` methods + - Add `editor.utils` property with `getUpdatedPosition(position, transaction)` and `createMappablePosition()` methods + - Create `CollaborationMappablePosition` subclass that extends `MappablePosition` with Y.js relative position support +### @tiptap/extension-collaboration-caret -### Bug Fixes +#### Patch Changes -* **core:** fix error when merging class attributes ([#4340](https://github.com/ueberdosis/tiptap/issues/4340)) ([a251946](https://github.com/ueberdosis/tiptap/commit/a2519468589e2baa44901a66a3a06b24dc8626d6)) +- Avoid mutating `this.options` in the `updateUser` command. `this.options` can be a getter and is not writable; the command now updates the provider awareness directly so user updates are applied correctly. +### @tiptap/react +#### Minor Changes +- Replaced unmaintained `fast-deep-equal` dependency with maintained `fast-equals` +#### Patch Changes -## [2.1.1](https://github.com/ueberdosis/tiptap/compare/v2.1.0...v2.1.1) (2023-08-16) +- Fix a bug where React node views could receive invalid positions from `this.getPos()` when ProseMirror and React render cycles got out of sync, which could cause errors during updates. -**Note:** Version bump only for package tiptap +## v3.11.1 +### @tiptap/core +#### Patch Changes +- Improve TypeScript generics for Node.extend + + The Node.extend method's TypeScript signature was updated so that ExtendedConfig can extend NodeConfig and MarkConfig, + improving type inference when extending Node and Mark classes with additional config properties. + + This is a type-only change — there are no runtime behavior changes. +### @tiptap/extensions -# [2.1.0](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.14...v2.1.0) (2023-08-16) +#### Patch Changes -**Note:** Version bump only for package tiptap +- Fixed a bug where the TrailingNode extension would not use the node option to assume the default node type +## v3.11.0 +### @tiptap/core +#### Minor Changes +- Add native text direction support for RTL and bidirectional content. The editor now includes a `textDirection` option that can be set to `'ltr'`, `'rtl'`, or `'auto'` to control the direction of all content globally. Additionally, new `setTextDirection` and `unsetTextDirection` commands allow for granular control of text direction on specific nodes. This enables proper rendering of right-to-left languages like Arabic and Hebrew, as well as bidirectional text mixing multiple languages. -# [2.1.0-rc.14](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.13...v2.1.0-rc.14) (2023-08-11) +## v3.10.8 -**Note:** Version bump only for package tiptap +### @tiptap/core +#### Patch Changes +- Fixed a bug that caused extra characters to be inserted after a parsed, nestable content block by accounting for leading newlines +- Add documentation comments to Tiptap JSON types +- allow `undefined` as a value for the `default` attribute key +- Fix `updateAttributes` and `resetAttributes` commands to return accurate results when used with `.can()`. Previously, these commands would always return `true` even when they couldn't perform the operation. Now they correctly return `false` when no matching nodes or marks are found in the selection. +### @tiptap/extension-text-align +#### Patch Changes -# [2.1.0-rc.13](https://github.com/ueberdosis/tiptap-workspace/compare/v2.0.4...v2.1.0-rc.13) (2023-08-11) +- Fix `setTextAlign` and `unsetTextAlign` commands to work correctly with `.can()` checks. Changed logic from `.every()` to `.some()` to return `true` when at least one configured node type matches, rather than requiring all types to match. +### @tiptap/static-renderer -### Bug Fixes +#### Patch Changes -* **demos:** add missing extensions ([6383fd5](https://github.com/ueberdosis/tiptap-workspace/commit/6383fd54080b2ad555286cd0e7c4ad880200200f)) -* **demos:** update deps ([05a2edf](https://github.com/ueberdosis/tiptap-workspace/commit/05a2edfc16e297effa86d1583fb1680be0320f25)) -* **link:** Fix autolinking and pasting ([#4292](https://github.com/ueberdosis/tiptap-workspace/issues/4292)) ([a2ce734](https://github.com/ueberdosis/tiptap-workspace/commit/a2ce734d681039fd61d402987e0842ddef6af595)) -* **strikethrough:** update strikethrough shortcut ([#4288](https://github.com/ueberdosis/tiptap-workspace/issues/4288)) ([fd35db4](https://github.com/ueberdosis/tiptap-workspace/commit/fd35db4d090d9fdfef1196fb1f6f858f13cf53d1)) +- Fix static HTML renderer incorrectly generating self-closing tags for HTML elements that require proper closing tags (iframe, script, style, etc.). +### @tiptap/markdown +#### Patch Changes -# [2.1.0-rc.12](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.11...v2.1.0-rc.12) (2023-07-14) +- Fixed CommonJS compatibility by downgrading `marked` dependency from v16 to v15. +## v3.10.7 +### @tiptap/vue-2 -# [2.1.0-rc.11](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.10...v2.1.0-rc.11) (2023-07-07) +#### Patch Changes +- Fix BubbleMenu plugin registration not triggering due to missing element reference during component initialization. -### Bug Fixes +## v3.10.6 -* **core:** fix cut and insertContentAt functions ([#4187](https://github.com/ueberdosis/tiptap-workspace/issues/4187)) ([6b65af8](https://github.com/ueberdosis/tiptap-workspace/commit/6b65af8fc31ffbbcf79b89bfdaceee7aadbf3f27)) -* **tests:** fix link rel tests ([c1d1854](https://github.com/ueberdosis/tiptap-workspace/commit/c1d18543b03b1fb6b99a2f3546aa5da10c919920)) +### @tiptap/vue-2 +#### Patch Changes +- Fix BubbleMenu and FloatingMenu component runtime errors in Vue 2. -# [2.1.0-rc.10](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.9...v2.1.0-rc.10) (2023-07-07) +## v3.10.5 +### @tiptap/extension-collaboration -### Bug Fixes +#### Patch Changes -* do not use window.open for links in readonly mode ([#4073](https://github.com/ueberdosis/tiptap-workspace/issues/4073)) ([4bca77e](https://github.com/ueberdosis/tiptap-workspace/commit/4bca77e4e9c96596d584cf71b8d831dc2ab0a421)) -* **extension-link:** fixes link going to wrong url ([#4078](https://github.com/ueberdosis/tiptap-workspace/issues/4078)) ([3053865](https://github.com/ueberdosis/tiptap-workspace/commit/30538654752ab3ded6e56c869745ccacc8cdeabc)) -* **link:** Prevent auto-linking when typing URL inside inline code mark ([#4160](https://github.com/ueberdosis/tiptap-workspace/issues/4160)) ([b24df3a](https://github.com/ueberdosis/tiptap-workspace/commit/b24df3aa4c2f3fdb2ed6122d2d32fb7c4e07f2af)) -* **react:** check props.clientRect before creating ReactRenderer ([#4138](https://github.com/ueberdosis/tiptap-workspace/issues/4138)) ([d710846](https://github.com/ueberdosis/tiptap-workspace/commit/d710846ecb6a3059dfbc21300b9a4b887a8defa3)) -* **react:** update select state when text selection is around node ([#4148](https://github.com/ueberdosis/tiptap-workspace/issues/4148)) ([5bd5bd4](https://github.com/ueberdosis/tiptap-workspace/commit/5bd5bd4ecdbe1f952b23d5f5efad16b6ed5cc44f)) +- Fixed collaborative editing errors with certain emoji combinations (like 🔴🟢, 😎🐈, 🟣🔵) by updating `@tiptap/y-tiptap` to stable v3.0.0. +### @tiptap/extension-collaboration-caret -### Features +#### Patch Changes -* **docs:** added cdn installation guide ([#4045](https://github.com/ueberdosis/tiptap-workspace/issues/4045)) ([8536508](https://github.com/ueberdosis/tiptap-workspace/commit/853650885b7c4f2217a4b37bc42ee65b4cd6026a)) +- Fixed collaborative editing errors with certain emoji combinations (like 🔴🟢, 😎🐈, 🟣🔵) by updating `@tiptap/y-tiptap` to stable v3.0.0. +### @tiptap/extension-drag-handle +#### Patch Changes -# [2.1.0-rc.9](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.8...v2.1.0-rc.9) (2023-06-15) +- Fixed collaborative editing errors with certain emoji combinations (like 🔴🟢, 😎🐈, 🟣🔵) by updating `@tiptap/y-tiptap` to stable v3.0.0. +### @tiptap/core +#### Patch Changes -# [2.1.0-rc.8](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.7...v2.1.0-rc.8) (2023-05-25) +- Fixed ProseMirror schema generation to properly respect `isRequired` attribute configuration. Previously, attributes marked with `isRequired: true` were incorrectly treated as optional because a `default` property was always included in the schema specification. ProseMirror determines attribute requirements by the absence of the `default` property, so now the `default` is only included when the attribute is not required and a default value is explicitly defined. +### @tiptap/extension-unique-id +#### Patch Changes -# [2.1.0-rc.7](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.6...v2.1.0-rc.7) (2023-05-25) +- Fixed infinite transaction loop that caused browser tabs to freeze when using UniqueID and TrailingNode extensions together. +### @tiptap/extensions +#### Patch Changes -# [2.1.0-rc.5](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.4...v2.1.0-rc.5) (2023-05-25) +- Fixed infinite transaction loop that caused browser tabs to freeze when using UniqueID and TrailingNode extensions together. + +## v3.10.4 + +### @tiptap/core + +#### Patch Changes + +- Fix autofocus behavior to prevent unwanted scrolling when disabled + +### @tiptap/extension-blockquote + +#### Patch Changes + +- Fixed nested blockquote markdown serialization to properly handle multi-level nesting + +## v3.10.3 + +### @tiptap/markdown + +#### Patch Changes + +- Fix markdown serialization to prevent marks from continuing after hard breaks. Previously, marks like bold would incorrectly persist across hard breaks in the markdown output. +- Fixed a bug where marks were resolved in incorrect orders, breaking markdown rendering for nested marks. +- Fix parsing of mixed bullet lists and task lists. Previously, Marked.js would group consecutive bullet list items and task list items into a single list token, causing incorrect parsing. Now the parser detects mixed lists and splits them into separate bulletList and taskList nodes. + +## v3.10.2 + +### @tiptap/markdown + +#### Patch Changes + +- Fix parsing of mixed inline HTML within Markdown content so that inline HTML fragments are parsed correctly. + +### @tiptap/extension-table + +#### Patch Changes + +- Allow setting custom table widths by respecting user-provided `style` attributes instead of always overriding them with calculated widths. + +## v3.10.1 + +### @tiptap/core + +#### Patch Changes + +- Use correct `ResizableNodeView` class name + +## v3.10.0 + +### @tiptap/core + +#### Minor Changes + +- Add a new ResizableNodeview NodeView to core that wraps elements (images, videos, iframes) with configurable resize handles. It provides live onResize/onCommit callbacks, min/max constraints, aspect-ratio support, and styling hooks (class names + data attributes) to improve UX when resizing media inside the editor. +- the addNodeView function can now return `null` to dynamically disable rendering of a node view + + While this should not directly cause any issues, it's noteworthy as it still could affect some behavior in some edge cases. + +### @tiptap/extension-image + +#### Minor Changes + +- Added a new `resize` option that allows images to be resized. The option adds resize handlers to images allowing users to manually resize images via drag and drop or touch + +## v3.9.1 + +### @tiptap/extension-table + +#### Patch Changes + +- Add a `renderWrapper` option to the Table extension so consumers can customize whether the table wrapper for the resizable node view should be rendered in non-editable mode as well. + +## v3.9.0 + +### @tiptap/vue-3 + +#### Patch Changes + +- Fix attribute forwarding for BubbleMenu and FloatingMenu Vue 3 components to allow setting z-index and other HTML attributes + +### @tiptap/extension-hard-break + +#### Patch Changes + +- Ensure that markdown hard breaks (two spaces followed by a newline) are parsed so they render as line breaks (`
`) in the editor when using `contentType: 'markdown'`. + + Fixes #7107 + +### @tiptap/extension-unique-id + +#### Minor Changes + +- Add `updateDocument` option to disable document updates caused by the Unique ID extension. + +### @tiptap/core + +#### Patch Changes + +- Only remove injected CSS on unmount if no other editors are in the document (fixes #6836) + +### @tiptap/extension-drag-handle + +#### Patch Changes + +- Replace DOM traversal with browser's native elementsFromPoint for better performance. + + - Use elementsFromPoint instead of querySelectorAll + - Add clampToContent helper for coordinate boundary validation + - Add findClosestTopLevelBlock helper for efficient block lookup + - Future-proof for root-level mousemove listeners + +### @tiptap/react + +#### Patch Changes + +- Prevent Bubble Menu plugin from re-loading every time the BubbleMenu component re-renders. Reverts a regression introduced in v3.6.3, in PR #7028. + +## v3.8.0 + +### @tiptap/extension-unique-id + +#### Minor Changes + +- Add `updateDocument` option to disable document updates caused by the Unique ID extension. + +### @tiptap/react + +#### Patch Changes + +- Prevent Bubble Menu plugin from re-loading every time the BubbleMenu component re-renders. Reverts a regression introduced in v3.6.3, in PR #7028. + +## v3.7.2 + +### @tiptap/html + +#### Patch Changes + +- Fix [CVE-2025-62410](https://www.cve.org/CVERecord?id=CVE-2025-62410) by updating happy-dom to ^20.0.2 + +## v3.7.1 + +### @tiptap/markdown + +#### Patch Changes + +- Editors will not throw an error anymore when `content` is an empty string and `contentType` is `markdown` +- Remove invalid server configuration from package.json + +## v3.7.0 + +### @tiptap/core + +#### Minor Changes + +- All commands and their corresponding TypeScript types are now exported from `@tiptap/core` so they can be imported and referenced directly by consumers. This makes it easier to build typed helpers, extensions, and tests that depend on the command signatures. + + Why: + + - Previously some command option types were only available as internal types or scattered across files, which made it awkward for downstream users to import and reuse them. + + ```ts + import { commands } from '@tiptap/core' + ``` + + Notes: + + - This is a non-breaking, additive change. It improves ergonomics for TypeScript consumers. + - If you rely on previously private/internal types, prefer the exported types from `@tiptap/core` going forward. + +- Add comprehensive bidirectional markdown support to Tiptap through a new `@tiptap/markdown` package and Markdown utilities in `@tiptap/core`. + + **New Package: `@tiptap/markdown`** - A new official extension that provides full Markdown parsing and serialization capabilities using [MarkedJS](https://marked.js.org) as the underlying Markdown parser. + + **Core Features:** + + **Extension API** + + - **`Markdown` Extension**: Main extension that adds Markdown support to your editor + - **`MarkdownManager`**: Core engine for parsing and serializing Markdown + - Parse Markdown strings to Tiptap JSON: `editor.markdown.parse(markdown)` + - Serialize Tiptap JSON to Markdown: `editor.markdown.serialize(json)` + - Access to underlying marked.js instance: `editor.markdown.instance` + + #### Editor Methods + + - **`editor.getMarkdown()`**: Serialize current editor content to Markdown string + - **`editor.markdown`**: Access to MarkdownManager instance for advanced operations + + **Editor Options:** + + - **`contentType`**: Control the type of content that is inserted into the editor. Can be `json`, `html` or `markdown` - defaults to `json` and will automatically detect invalid content types (like JSON when it is actually Markdown). + ```typescript + new Editor({ + content: '# Hello World', + contentType: 'markdown', + }) + ``` + + **Command Options:** All content commands now support an `contentType` option: + + - **`setContent(markdown, { contentType: 'markdown' })`**: Replace editor content with markdown + - **`insertContent(markdown, { contentType: 'markdown' })`**: Insert markdown at cursor position + - **`insertContentAt(position, markdown, { contentType: 'markdown' })`**: Insert Markdown at specific position + + For more, check [the documentation](https://tiptap.dev/docs/editor/markdown). + +#### Patch Changes + +- The extension manager now provides a new property `baseExtensions` that contains an unflattened array of extensions + +### @tiptap/markdown + +#### Minor Changes + +- Add comprehensive bidirectional markdown support to Tiptap through a new `@tiptap/markdown` package and Markdown utilities in `@tiptap/core`. + + **New Package: `@tiptap/markdown`** - A new official extension that provides full Markdown parsing and serialization capabilities using [MarkedJS](https://marked.js.org) as the underlying Markdown parser. + + **Core Features:** + + **Extension API** + + - **`Markdown` Extension**: Main extension that adds Markdown support to your editor + - **`MarkdownManager`**: Core engine for parsing and serializing Markdown + - Parse Markdown strings to Tiptap JSON: `editor.markdown.parse(markdown)` + - Serialize Tiptap JSON to Markdown: `editor.markdown.serialize(json)` + - Access to underlying marked.js instance: `editor.markdown.instance` + + #### Editor Methods + + - **`editor.getMarkdown()`**: Serialize current editor content to Markdown string + - **`editor.markdown`**: Access to MarkdownManager instance for advanced operations + + **Editor Options:** + + - **`contentType`**: Control the type of content that is inserted into the editor. Can be `json`, `html` or `markdown` - defaults to `json` and will automatically detect invalid content types (like JSON when it is actually Markdown). + ```typescript + new Editor({ + content: '# Hello World', + contentType: 'markdown', + }) + ``` + + **Command Options:** All content commands now support an `contentType` option: + + - **`setContent(markdown, { contentType: 'markdown' })`**: Replace editor content with markdown + - **`insertContent(markdown, { contentType: 'markdown' })`**: Insert markdown at cursor position + - **`insertContentAt(position, markdown, { contentType: 'markdown' })`**: Insert Markdown at specific position + + For more, check [the documentation](https://tiptap.dev/docs/editor/markdown). + +### @tiptap/extension-link + +#### Patch Changes + +- Paste Handlers and onPaste plugin now respect shouldAutoLink/validate options + +### @tiptap/extensions + +#### Patch Changes + +- Make the `TrailingNode` extension's `node` option optional and derive the + default node type from the editor schema when available. + + Previously the extension used a hard-coded `'paragraph'` default and the + `node` option was required in the TypeScript definitions. This change: + + - makes `node` optional in the options type, + - prefers the editor schema's top node default type when resolving the + trailing node, and + - falls back to the configured option or `'paragraph'` as a last resort. + + This fixes cases where projects use a different top-level default node and + prevents the extension from inserting an incorrect trailing node type. + +## v3.6.7 + +### @tiptap/html + +#### Patch Changes + +- Fix CVE-2025-61927 by bumping happy-dom to 20.0.0 + + Bumps the transitive/dev dependency happy-dom from ^18.0.1 → ^20.0.0 in @tiptap/html to address CVE-2025-61927. This is a dependency/security-only change and does not modify any public APIs. + + Why: + + - happy-dom released a security fix for CVE-2025-61927; updating prevents the vulnerability being pulled into consumers that depend on @tiptap/html. + +## v3.6.6 + +### @tiptap/extension-floating-menu + +#### Patch Changes + +- Fixed a problem where the position of a menu is not updated on creation when shouldShow is true + +### @tiptap/extension-bubble-menu + +#### Patch Changes + +- Fixed a problem where the position of a menu is not updated on creation when shouldShow is true + +### @tiptap/vue-3 + +#### Patch Changes + +- Fixed a bug that caused conditionally rendered bubble menus not to be attached to the DOM correctly + +## v3.6.5 + +### @tiptap/extension-horizontal-rule + +#### Patch Changes + +- Added nextNodeType option to horizontal-rule extension, allowing users to specify which node type should be inserted after a horizontal rule + +### @tiptap/html + +#### Patch Changes + +- Fix: Clean up happy-dom window instance fixing a memory leak caused by unclosed happy-dom windows + +### @tiptap/core + +#### Patch Changes + +- Editors can now emit `transaction` and `update` events before being mounted. + This means smoother state handling and instant feedback from editors, even when they're not in the DOM. + +## v3.6.4 + +### @tiptap/html + +#### Patch Changes + +- Fix: Clean up happy-dom window instance fixing a memory leak caused by unclosed happy-dom windows + +## v3.6.3 + +### @tiptap/react + +#### Patch Changes + +- Updated the React `FloatingMenu` plugin hook dependencies to match the `BubbleMenu` behavior. + The FloatingMenu will now respond to changes in `appendTo`, `pluginKey`, `shouldShow`, and `options`. +- Resolved an issue where the React BubbleMenu did not update when FloatingUI option props changed after initial mount. The BubbleMenu now correctly responds to updated option props. +- Improved the BubbleMenu's usability by ensuring the `appendTo` prop passed to the React BubbleMenu component is now correctly forwarded to the underlying bubble menu plugin. This fix allows developers to customize where the BubbleMenu is attached in the DOM, helping resolve issues with positioning and portal setups in React apps. + +### @tiptap/extensions + +#### Patch Changes + +- The Selection extension now uses the correct SelectionOptions type, providing accurate typings for its options. + +### @tiptap/extension-code-block + +#### Patch Changes + +- Configuration options for the CodeBlock extension now support `null` and `undefined` values. + This makes custom setups more flexible and avoids unnecessary type errors when omitting optional overrides. + All existing default values and fallback logic remain in place - no breaking changes for existing code. +### @tiptap/core + +#### Patch Changes + +- Refined the `JSONContent.attrs` definition to exactly mirror the structure returned by `editor.getJSON()`. This ensures strict type safety and consistency between the editor output and the expected type, eliminating errors caused by mismatched attribute signatures. + +### @tiptap/extension-table-of-contents + +#### Patch Changes + +- Improve typings by inferring the storage type for the Table of Contents extension + +### @tiptap/extension-floating-menu + +#### Patch Changes + +- You can now pass a callback to the `appendTo` option in the floating and bubble menu + extensions. The callback must return an element synchronously, + so menus can be appended to elements that are created dynamically. + +### @tiptap/extension-bubble-menu + +#### Patch Changes + +- You can now pass a callback to the `appendTo` option in the floating and bubble menu + extensions. The callback must return an element synchronously, + so menus can be appended to elements that are created dynamically. + +## v3.6.2 + +### @tiptap/extension-bubble-menu + +#### Patch Changes + +- Fix a bug where the bubble menu could throw an error if the editor was destroyed + while the plugin was cleaning up. + +## v3.6.1 + +### @tiptap/react + +#### Patch Changes + +- Hotfix: Fix a crash in the React package that could occur during mounting/unmounting when the editor wasn't fully initialized. This prevents a runtime error and improves stability. + +## v3.6.0 + +### @tiptap/core + +#### Patch Changes + +- Improve typing and docs for `EditorOptions.element` to reflect all supported mounting modes and align behavior across adapters. + + - `element` now accepts: + - `Element`: the editor is appended inside the given element. + - `{ mount: HTMLElement }`: the editor is mounted directly to `mount` (no extra wrapper). + - `(editorEl: HTMLElement) => void`: a function that receives the editor element so you can place it anywhere in the DOM. + - `null`: no automatic mounting. + +### @tiptap/extension-table + +#### Patch Changes + +- Parse cell `colwidth` from nearest `` when missing on the cell + + When importing HTML, table column widths are often declared on a surrounding `` rather than on each ``. Previously, `tableCell` only read the `colwidth` attribute from the cell itself and would lose width information in that case. The implementation now falls back to reading the corresponding ``'s `width` from the table's `` using the cell's index. + + This is a non-breaking bugfix that preserves layout information when HTML uses ``. Consider adding a small demo or unit test to assert colwidth is preserved for cells when only the `` contains width attributes. + +- Fixes table wrapper replacement and lost selections when `resizable: true`. + + TableView.ignoreMutation now ignores attribute/childList/characterData mutations that occur inside the table wrapper but outside the editable `contentDOM`, preventing wrapper re-creation during resize interactions so selections (e.g. `mergeCells()`) are preserved. + + No API or breaking changes. + +### @tiptap/extension-bubble-menu + +#### Patch Changes + +- Remove recently added `updateBubbleMenuPosition` method because it would not work in the React and Vue versions of the BubbleMenu, only in the vanilla extension. And that would confuse developers. + + Write the `transactionHandler` method as an arrow function because arrow functions have no `this`, so the `this` remains the instance of the `BubbleMenuView` class. + +### @tiptap/extension-unique-id + +#### Minor Changes + +- Create a utility to add unique IDs to a document in the server + + The utility is called `generateUniqueIds` and is exported from the `@tiptap/extension-unique-id` package. + + It has the same functionality as the `UniqueID` extension, but without the need to create an `Editor` instance. This lets you add unique IDs to the document in the server. + + It takes the following parameters: + + - `doc`: The Tiptap JSON document to add unique IDs to. + - `extensions`: The extensions to use. Must include the `UniqueID` extension. + + It returns the updated Tiptap JSON document, with the unique IDs added to the nodes. + +### @tiptap/vue-3 + +#### Minor Changes + +- Pass `attrs` through Vue 3 menus + +## v3.5.3 + +### @tiptap/extension-text-style + +#### Patch Changes + +- Merge nested span styles only for immediate child spans and guard style values. + + - Replace non-standard/fragile selector approach and avoid re-processing nested `` elements. + - Read parent style once, merge with child style only when present, and remove empty `style` attributes. + - Improves parsing performance and robustness in browsers, Node/JSDOM and tests. + + This change fixes a bug that could cause exponential work when parsing deeply + nested `` elements - in extreme cases that could make the tab unresponsive + or crash the renderer. It is a bugfix / performance improvement with no public API + changes. + +## v3.5.2 + +### @tiptap/react + +#### Patch Changes + +- Tiptap will now correctly insert a React MarkViews' content into the correct element within `MarkViewContent` component + +## v3.5.1 + +### @tiptap/extension-floating-menu + +#### Patch Changes + +- Add `appendTo` support to `FloatingMenu` and pass it through in React/Vue 2/Vue 3 for both `BubbleMenu` and `FloatingMenu` to allow fixing clipping/z-index issues. + +### @tiptap/react + +#### Patch Changes + +- Add `appendTo` support to `FloatingMenu` and pass it through in React/Vue 2/Vue 3 for both `BubbleMenu` and `FloatingMenu` to allow fixing clipping/z-index issues. + +### @tiptap/vue-2 + +#### Patch Changes + +- Add `appendTo` support to `FloatingMenu` and pass it through in React/Vue 2/Vue 3 for both `BubbleMenu` and `FloatingMenu` to allow fixing clipping/z-index issues. + +### @tiptap/vue-3 + +#### Patch Changes + +- Add `appendTo` support to `FloatingMenu` and pass it through in React/Vue 2/Vue 3 for both `BubbleMenu` and `FloatingMenu` to allow fixing clipping/z-index issues. + +# [2.4.0](https://github.com/ueberdosis/tiptap/compare/v2.3.2...v2.4.0) (2024-05-14) ### Bug Fixes -* **extension-link:** fix paste handling ([d19267e](https://github.com/ueberdosis/tiptap-workspace/commit/d19267ecefabf08e4bd27c52424ed83991ce7270)) -* typo in commands.md ([a2a9822](https://github.com/ueberdosis/tiptap-workspace/commit/a2a9822f240df2301932a67225d9adcac2f18807)) +- **core:** configure should use the parent of the current instance, to avoid duplication ([#5147](https://github.com/ueberdosis/tiptap/issues/5147)) ([4db463c](https://github.com/ueberdosis/tiptap/commit/4db463c6bbcc3a17ee8eb591bea8e357120ecb35)) +- fix ts error for BubbleMenu and FloatingMenu in @tiptap/react ([#5126](https://github.com/ueberdosis/tiptap/issues/5126)) ([baff4af](https://github.com/ueberdosis/tiptap/commit/baff4af39e2b8970d7cab99859ece41228643f9d)) + +### Features + +- added jsdocs ([#4356](https://github.com/ueberdosis/tiptap/issues/4356)) ([b941eea](https://github.com/ueberdosis/tiptap/commit/b941eea6daba09d48a5d18ccc1b9a1d84b2249dd)) +## [2.3.2](https://github.com/ueberdosis/tiptap/compare/v2.3.1...v2.3.2) (2024-05-08) + +### Bug Fixes + +- NodePos querySelectorAll function ([#5094](https://github.com/ueberdosis/tiptap/issues/5094)) ([4900a27](https://github.com/ueberdosis/tiptap/commit/4900a27c5389d9a2d0d69f407ca3db0155304315)) + +## [2.3.1](https://github.com/ueberdosis/tiptap/compare/v2.3.0...v2.3.1) (2024-04-30) + +**Note:** Version bump only for package tiptap + +# [2.3.0](https://github.com/ueberdosis/tiptap/compare/v2.2.6...v2.3.0) (2024-04-09) + +### Bug Fixes + +- **core:** fix nodepos child lookup ([#5038](https://github.com/ueberdosis/tiptap/issues/5038)) ([22ced31](https://github.com/ueberdosis/tiptap/commit/22ced318723003365fbfd8f59b8dac79c7563017)) ### Features -* add tiptap class ([614fc80](https://github.com/ueberdosis/tiptap-workspace/commit/614fc8082c376bf3c40a05c23ceda6b4a6fbf8d0)) +- **core:** apply input and paste rules when using insertContent methods ([#5046](https://github.com/ueberdosis/tiptap/issues/5046)) ([96b6abc](https://github.com/ueberdosis/tiptap/commit/96b6abcf6edbc6cac03a391130d9feebb6de3a04)) +## [2.2.6](https://github.com/ueberdosis/tiptap/compare/v2.2.5...v2.2.6) (2024-04-06) +### Bug Fixes -# [2.1.0-rc.4](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.3...v2.1.0-rc.4) (2023-04-27) +- unexpected renderText() for contentful nodes ([#3410](https://github.com/ueberdosis/tiptap/issues/3410)) ([d6c71a8](https://github.com/ueberdosis/tiptap/commit/d6c71a838d590f78fdff15c805d93f43c8a5a1a5)) +## [2.2.5](https://github.com/ueberdosis/tiptap/compare/v2.2.4...v2.2.5) (2024-04-05) ### Bug Fixes -* **link:** fix links autolinking when not needed ([#3989](https://github.com/ueberdosis/tiptap-workspace/issues/3989)) ([71946c1](https://github.com/ueberdosis/tiptap-workspace/commit/71946c18accf8a2e8192951de870f84e25f58ed5)) +- Disallow only whitespace between markdown shortcuts delimiters ([#4866](https://github.com/ueberdosis/tiptap/issues/4866)) ([aa029fe](https://github.com/ueberdosis/tiptap/commit/aa029fe2242aeadc38555b2832df6ae1614c7d1d)) +- **extension-link:** Avoid auto-linking partial text for invalid TLDs ([#4865](https://github.com/ueberdosis/tiptap/issues/4865)) ([4474d05](https://github.com/ueberdosis/tiptap/commit/4474d056daf9280ebb10b31f98bb000e953132e5)) +## [2.2.4](https://github.com/ueberdosis/tiptap/compare/v2.2.3...v2.2.4) (2024-02-23) +### Bug Fixes -# [2.1.0-rc.3](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.2...v2.1.0-rc.3) (2023-04-26) +- mark nocookie youtube url as valid when parsing html ([#4883](https://github.com/ueberdosis/tiptap/issues/4883)) ([099e10d](https://github.com/ueberdosis/tiptap/commit/099e10df923d851dd866354e9abca331d995b65c)) +- typecheck drag and clipboard events for testing environments ([bbee9a3](https://github.com/ueberdosis/tiptap/commit/bbee9a3c3090fa40bf366591682b42a3f6ec5f91)) +## [2.2.3](https://github.com/ueberdosis/tiptap/compare/v2.2.2...v2.2.3) (2024-02-15) ### Bug Fixes -* **core:** remove configure from extend functionality ([4af54da](https://github.com/ueberdosis/tiptap-workspace/commit/4af54da3e09c69c0b5326f9952d456436855914d)) +- fix test path ([21aa96d](https://github.com/ueberdosis/tiptap/commit/21aa96dee8deab1f439b7f655b8ed266a516a4cd)) +## [2.2.2](https://github.com/ueberdosis/tiptap/compare/v2.2.1...v2.2.2) (2024-02-07) +### Bug Fixes -# [2.1.0-rc.2](https://github.com/ueberdosis/tiptap-workspace/compare/v2.0.3...v2.1.0-rc.2) (2023-04-26) +- **react:** use ref instead of state in useEditor to prevent rerenders ([#4856](https://github.com/ueberdosis/tiptap/issues/4856)) ([56a5737](https://github.com/ueberdosis/tiptap/commit/56a5737ed102ee75ec72f9cc2847e3c977f431bd)) +## [2.2.1](https://github.com/ueberdosis/tiptap/compare/v2.2.0...v2.2.1) (2024-01-31) + +**Note:** Version bump only for package tiptap + +# [2.2.0](https://github.com/ueberdosis/tiptap/compare/v2.1.16...v2.2.0) (2024-01-29) ### Bug Fixes -* **extension-link:** fix link not being kept when pasting url with link ([#3975](https://github.com/ueberdosis/tiptap-workspace/issues/3975)) ([e7d7d49](https://github.com/ueberdosis/tiptap-workspace/commit/e7d7d496376c8c11e24c342e20bd179a6ea7dcee)) +- **core:** fix new lines being added via elementFromString ([#4767](https://github.com/ueberdosis/tiptap/issues/4767)) ([b7a2504](https://github.com/ueberdosis/tiptap/commit/b7a2504f16f46563537c890930cb2c332c256175)) +- fix bug [#4785](https://github.com/ueberdosis/tiptap/issues/4785) ([#4836](https://github.com/ueberdosis/tiptap/issues/4836)) ([f3cba1e](https://github.com/ueberdosis/tiptap/commit/f3cba1e0b0288156c1427437e5a0b9e03cd67e63)) +- fix imports, fix demos, unpin y-prosemirror ([681aa57](https://github.com/ueberdosis/tiptap/commit/681aa577bff500015c3f925e300c55a71c73efaf)) +- fix newline stripping via insertContent ([8954007](https://github.com/ueberdosis/tiptap/commit/8954007b2b92b040d69b26a0866ae58fabf5e512)) +# [2.2.0-rc.8](https://github.com/ueberdosis/tiptap/compare/v2.1.14...v2.2.0-rc.8) (2024-01-08) +### Bug Fixes -# [2.1.0-rc.1](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.0...v2.1.0-rc.1) (2023-04-12) +- **core:** fix options now being empty ([fc67cb1](https://github.com/ueberdosis/tiptap/commit/fc67cb1b7166c1ab6b6e0174539c9e29c364eace)) +# [2.2.0-rc.7](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.6...v2.2.0-rc.7) (2023-11-27) ### Bug Fixes -* **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap-workspace/issues/3956)) ([e8cef04](https://github.com/ueberdosis/tiptap-workspace/commit/e8cef0404b5039ec2657536976b8b31931afd337)) +- **core:** set defaultOptions to undefined by default ([448b433](https://github.com/ueberdosis/tiptap/commit/448b433ee7847bfba4cd803d8c8820763ceedafc)) +# [2.2.0-rc.6](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.5...v2.2.0-rc.6) (2023-11-23) +### Reverts -# [2.1.0-rc.0](https://github.com/ueberdosis/tiptap-workspace/compare/v2.0.2...v2.1.0-rc.0) (2023-04-05) +- Revert "fix/react-renderer-node-attrs (#4321)" ([a4af83c](https://github.com/ueberdosis/tiptap/commit/a4af83ca52c8e020f88990af53981591559205a9)), closes [#4321](https://github.com/ueberdosis/tiptap/issues/4321) +- Revert "autolink improvement" ([ef10ae5](https://github.com/ueberdosis/tiptap/commit/ef10ae53b2a3854fceefc2999e166ed1fe4e9b32)) +# [2.2.0-rc.4](https://github.com/ueberdosis/tiptap/compare/v2.1.11...v2.2.0-rc.4) (2023-10-10) ### Bug Fixes -* clear nodes when cursor at start of empty isolating parent ([#3943](https://github.com/ueberdosis/tiptap-workspace/issues/3943)) ([7278ee2](https://github.com/ueberdosis/tiptap-workspace/commit/7278ee2b05de2f96efddf3b1dc3bfd3d52262cbb)) -* **list-item:** improve delete behaviour ([09782a5](https://github.com/ueberdosis/tiptap-workspace/commit/09782a5b066b2f9f52f0ef1d8701d6e5b063dc63)) -* **lists:** improve list behaviour ([684e48a](https://github.com/ueberdosis/tiptap-workspace/commit/684e48a4a7778a0140c94f0c5345db868174ad81)) -* Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap-workspace/issues/3914)) ([0c1bba3](https://github.com/ueberdosis/tiptap-workspace/commit/0c1bba3137b535776bcef95ff3c55e13f5a2db46)) +- add missing attributes in extension-link ([#4429](https://github.com/ueberdosis/tiptap/issues/4429)) ([0578265](https://github.com/ueberdosis/tiptap/commit/0578265bfe548a7f574cdbe055ef07b9029d8797)) +- **history:** use correct shortcuts for undo/redo ([520ce79](https://github.com/ueberdosis/tiptap/commit/520ce790c3dff2d0774211fe30fdce1905655b09)) +### Features +- **extension/youtube:** Allow youtube shorts urls to be embedded ([4d79cb8](https://github.com/ueberdosis/tiptap/commit/4d79cb85c93353cdb5ead518da63cf8f9fa71497)) +# [2.2.0-rc.3](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.2...v2.2.0-rc.3) (2023-08-18) +# [2.2.0-rc.1](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.0...v2.2.0-rc.1) (2023-08-18) -# [2.1.0-rc.12](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.11...v2.1.0-rc.12) (2023-07-14) +# [2.2.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.2.0-rc.0) (2023-08-18) -**Note:** Version bump only for package tiptap +### Features +- **placeholder:** allow editor-is-empty class on any node ([#4335](https://github.com/ueberdosis/tiptap/issues/4335)) ([ff929b1](https://github.com/ueberdosis/tiptap/commit/ff929b179de930619005a773bb4186ae2aa2ec58)) +## [2.1.16](https://github.com/ueberdosis/tiptap/compare/v2.1.15...v2.1.16) (2024-01-10) +### Bug Fixes +- **core:** fix new lines being added via elementFromString ([#4767](https://github.com/ueberdosis/tiptap/issues/4767)) ([2235908](https://github.com/ueberdosis/tiptap/commit/2235908c28f388eda041d1d5d017554d513fe909)) -# [2.1.0-rc.11](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.10...v2.1.0-rc.11) (2023-07-07) +### Reverts + +- Revert "fix(extension-link): fix link not being kept when pasting url with link (#3975)" ([1b34271](https://github.com/ueberdosis/tiptap/commit/1b34271edfdd6e81f670f9ddb15cd6838d986e9f)), closes [#3975](https://github.com/ueberdosis/tiptap/issues/3975) +## [2.1.15](https://github.com/ueberdosis/tiptap/compare/v2.1.14...v2.1.15) (2024-01-08) ### Bug Fixes -* **core:** fix cut and insertContentAt functions ([#4187](https://github.com/ueberdosis/tiptap/issues/4187)) ([6b65af8](https://github.com/ueberdosis/tiptap/commit/6b65af8fc31ffbbcf79b89bfdaceee7aadbf3f27)) -* **tests:** fix link rel tests ([c1d1854](https://github.com/ueberdosis/tiptap/commit/c1d18543b03b1fb6b99a2f3546aa5da10c919920)) +- **core:** fix insertContentAt keeping new lines in html content ([#4465](https://github.com/ueberdosis/tiptap/issues/4465)) ([135a12f](https://github.com/ueberdosis/tiptap/commit/135a12f7aa2df839a0b619704110a360b980c738)) +- **link:** fix tests ([d495d92](https://github.com/ueberdosis/tiptap/commit/d495d92a1f7b1c51e09ac8f4934e15a2d1cf070d)) +### Reverts +- Revert "update package-lock" ([faead69](https://github.com/ueberdosis/tiptap/commit/faead6987337ea8471619fdc3124437954772a1a)) +## [2.1.14](https://github.com/ueberdosis/tiptap/compare/v2.1.13...v2.1.14) (2024-01-08) +### Bug Fixes -# [2.1.0-rc.10](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.9...v2.1.0-rc.10) (2023-07-07) +- **typography:** require spaces after divisions to not break date formats ([#4696](https://github.com/ueberdosis/tiptap/issues/4696)) ([f6d7e00](https://github.com/ueberdosis/tiptap/commit/f6d7e00a746a67fa440a3fa0f5362295959873d2)) +## [2.1.13](https://github.com/ueberdosis/tiptap/compare/v2.1.12...v2.1.13) (2023-11-30) ### Bug Fixes -* do not use window.open for links in readonly mode ([#4073](https://github.com/ueberdosis/tiptap/issues/4073)) ([4bca77e](https://github.com/ueberdosis/tiptap/commit/4bca77e4e9c96596d584cf71b8d831dc2ab0a421)) -* **extension-link:** fixes link going to wrong url ([#4078](https://github.com/ueberdosis/tiptap/issues/4078)) ([3053865](https://github.com/ueberdosis/tiptap/commit/30538654752ab3ded6e56c869745ccacc8cdeabc)) -* **link:** Prevent auto-linking when typing URL inside inline code mark ([#4160](https://github.com/ueberdosis/tiptap/issues/4160)) ([b24df3a](https://github.com/ueberdosis/tiptap/commit/b24df3aa4c2f3fdb2ed6122d2d32fb7c4e07f2af)) -* **react:** check props.clientRect before creating ReactRenderer ([#4138](https://github.com/ueberdosis/tiptap/issues/4138)) ([d710846](https://github.com/ueberdosis/tiptap/commit/d710846ecb6a3059dfbc21300b9a4b887a8defa3)) -* **react:** update select state when text selection is around node ([#4148](https://github.com/ueberdosis/tiptap/issues/4148)) ([5bd5bd4](https://github.com/ueberdosis/tiptap/commit/5bd5bd4ecdbe1f952b23d5f5efad16b6ed5cc44f)) +- **react:** fix performance regression because of select/deselect ([#4661](https://github.com/ueberdosis/tiptap/issues/4661)) ([ad7f659](https://github.com/ueberdosis/tiptap/commit/ad7f659ed08a6a7c57056b78edbded014549f2dc)) +## [2.1.12](https://github.com/ueberdosis/tiptap/compare/v2.1.11...v2.1.12) (2023-10-11) -### Features +### Bug Fixes -* **docs:** added cdn installation guide ([#4045](https://github.com/ueberdosis/tiptap/issues/4045)) ([8536508](https://github.com/ueberdosis/tiptap/commit/853650885b7c4f2217a4b37bc42ee65b4cd6026a)) +- **link:** restore pasteHandler and add existing url check ([#4523](https://github.com/ueberdosis/tiptap/issues/4523)) ([1a7b428](https://github.com/ueberdosis/tiptap/commit/1a7b4280d2f9c334d14b16016c29e9f4862716a0)) +## [2.1.11](https://github.com/ueberdosis/tiptap/compare/v2.1.10...v2.1.11) (2023-09-20) +### Reverts +- Revert "v2.2.11" ([6aa755a](https://github.com/ueberdosis/tiptap/commit/6aa755a04b9955fc175c7ab33dee527d0d5deef0)) +## [2.1.10](https://github.com/ueberdosis/tiptap/compare/v2.1.9...v2.1.10) (2023-09-15) -# [2.1.0-rc.9](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.8...v2.1.0-rc.9) (2023-06-15) +**Note:** Version bump only for package tiptap +## [2.1.9](https://github.com/ueberdosis/tiptap/compare/v2.1.8...v2.1.9) (2023-09-14) ### Bug Fixes -* **list-item:** improve delete behaviour ([09782a5](https://github.com/ueberdosis/tiptap/commit/09782a5b066b2f9f52f0ef1d8701d6e5b063dc63)) -* **lists:** improve list behaviour ([684e48a](https://github.com/ueberdosis/tiptap/commit/684e48a4a7778a0140c94f0c5345db868174ad81)) +- add missing attributes in extension-link ([#4429](https://github.com/ueberdosis/tiptap/issues/4429)) ([74b6444](https://github.com/ueberdosis/tiptap/commit/74b644438829d6ee9b0795bc70c55f2755d7438c)) +## [2.1.8](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.7...v2.1.8) (2023-09-04) +**Note:** Version bump only for package tiptap +## [2.1.7](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.6...v2.1.7) (2023-09-04) +### Bug Fixes -# [2.1.0-rc.8](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.7...v2.1.0-rc.8) (2023-05-25) +- **horizontal-rule:** fix insertion being broken on empty docs ([#4375](https://github.com/ueberdosis/tiptap-workspace/issues/4375)) ([2a83166](https://github.com/ueberdosis/tiptap-workspace/commit/2a83166a46f97a9fc42ae23ce5367bb58bcdab74)) -**Note:** Version bump only for package tiptap +## [2.1.6](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.1.6) (2023-08-18) +### Bug Fixes +- **core:** fix broken export ([4227f32](https://github.com/ueberdosis/tiptap/commit/4227f324a5bfd4f0905c70ac8ea68903352f911b)) +## [2.1.5](https://github.com/ueberdosis/tiptap/compare/v2.1.4...v2.1.5) (2023-08-18) +### Bug Fixes -# [2.1.0-rc.7](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.6...v2.1.0-rc.7) (2023-05-25) +- **list-key-map:** fix broken imports ([#4350](https://github.com/ueberdosis/tiptap/issues/4350)) ([e40ac25](https://github.com/ueberdosis/tiptap/commit/e40ac2584e813893a61c91a456bdcd2cf6652b50)) -**Note:** Version bump only for package tiptap +## [2.1.4](https://github.com/ueberdosis/tiptap/compare/v2.1.3...v2.1.4) (2023-08-18) +### Bug Fixes +- replace the whole node in nodeInputRule ([#4341](https://github.com/ueberdosis/tiptap/issues/4341)) ([ffeefe2](https://github.com/ueberdosis/tiptap/commit/ffeefe21ff3c1f951a5a4f9ae9697317ddd1c5ad)) +## [2.1.3](https://github.com/ueberdosis/tiptap/compare/v2.1.2...v2.1.3) (2023-08-18) + +### Bug Fixes +- fix autolink when code is not enabled for editor ([#4344](https://github.com/ueberdosis/tiptap/issues/4344)) ([f2ac7b9](https://github.com/ueberdosis/tiptap/commit/f2ac7b90912a78b90216a7d7d084c86f0c0eef48)) -# [2.1.0-rc.6](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.5...v2.1.0-rc.6) (2023-05-25) +## [2.1.2](https://github.com/ueberdosis/tiptap/compare/v2.1.1...v2.1.2) (2023-08-17) + +### Bug Fixes + +- **core:** fix error when merging class attributes ([#4340](https://github.com/ueberdosis/tiptap/issues/4340)) ([a251946](https://github.com/ueberdosis/tiptap/commit/a2519468589e2baa44901a66a3a06b24dc8626d6)) + +## [2.1.1](https://github.com/ueberdosis/tiptap/compare/v2.1.0...v2.1.1) (2023-08-16) **Note:** Version bump only for package tiptap +# [2.1.0](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.14...v2.1.0) (2023-08-16) +**Note:** Version bump only for package tiptap +# [2.1.0-rc.14](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.13...v2.1.0-rc.14) (2023-08-11) +**Note:** Version bump only for package tiptap -# [2.1.0-rc.5](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.4...v2.1.0-rc.5) (2023-05-25) +# [2.1.0-rc.13](https://github.com/ueberdosis/tiptap-workspace/compare/v2.0.4...v2.1.0-rc.13) (2023-08-11) + +### Bug Fixes + +- **demos:** add missing extensions ([6383fd5](https://github.com/ueberdosis/tiptap-workspace/commit/6383fd54080b2ad555286cd0e7c4ad880200200f)) +- **demos:** update deps ([05a2edf](https://github.com/ueberdosis/tiptap-workspace/commit/05a2edfc16e297effa86d1583fb1680be0320f25)) +- **link:** Fix autolinking and pasting ([#4292](https://github.com/ueberdosis/tiptap-workspace/issues/4292)) ([a2ce734](https://github.com/ueberdosis/tiptap-workspace/commit/a2ce734d681039fd61d402987e0842ddef6af595)) +- **strikethrough:** update strikethrough shortcut ([#4288](https://github.com/ueberdosis/tiptap-workspace/issues/4288)) ([fd35db4](https://github.com/ueberdosis/tiptap-workspace/commit/fd35db4d090d9fdfef1196fb1f6f858f13cf53d1)) +# [2.1.0-rc.12](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.11...v2.1.0-rc.12) (2023-07-14) + +# [2.1.0-rc.11](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.10...v2.1.0-rc.11) (2023-07-07) ### Bug Fixes -* **extension-link:** fix paste handling ([d19267e](https://github.com/ueberdosis/tiptap/commit/d19267ecefabf08e4bd27c52424ed83991ce7270)) -* typo in commands.md ([a2a9822](https://github.com/ueberdosis/tiptap/commit/a2a9822f240df2301932a67225d9adcac2f18807)) +- **core:** fix cut and insertContentAt functions ([#4187](https://github.com/ueberdosis/tiptap-workspace/issues/4187)) ([6b65af8](https://github.com/ueberdosis/tiptap-workspace/commit/6b65af8fc31ffbbcf79b89bfdaceee7aadbf3f27)) +- **tests:** fix link rel tests ([c1d1854](https://github.com/ueberdosis/tiptap-workspace/commit/c1d18543b03b1fb6b99a2f3546aa5da10c919920)) +# [2.1.0-rc.10](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.9...v2.1.0-rc.10) (2023-07-07) -### Features +### Bug Fixes -* add tiptap class ([614fc80](https://github.com/ueberdosis/tiptap/commit/614fc8082c376bf3c40a05c23ceda6b4a6fbf8d0)) +- do not use window.open for links in readonly mode ([#4073](https://github.com/ueberdosis/tiptap-workspace/issues/4073)) ([4bca77e](https://github.com/ueberdosis/tiptap-workspace/commit/4bca77e4e9c96596d584cf71b8d831dc2ab0a421)) +- **extension-link:** fixes link going to wrong url ([#4078](https://github.com/ueberdosis/tiptap-workspace/issues/4078)) ([3053865](https://github.com/ueberdosis/tiptap-workspace/commit/30538654752ab3ded6e56c869745ccacc8cdeabc)) +- **link:** Prevent auto-linking when typing URL inside inline code mark ([#4160](https://github.com/ueberdosis/tiptap-workspace/issues/4160)) ([b24df3a](https://github.com/ueberdosis/tiptap-workspace/commit/b24df3aa4c2f3fdb2ed6122d2d32fb7c4e07f2af)) +- **react:** check props.clientRect before creating ReactRenderer ([#4138](https://github.com/ueberdosis/tiptap-workspace/issues/4138)) ([d710846](https://github.com/ueberdosis/tiptap-workspace/commit/d710846ecb6a3059dfbc21300b9a4b887a8defa3)) +- **react:** update select state when text selection is around node ([#4148](https://github.com/ueberdosis/tiptap-workspace/issues/4148)) ([5bd5bd4](https://github.com/ueberdosis/tiptap-workspace/commit/5bd5bd4ecdbe1f952b23d5f5efad16b6ed5cc44f)) +### Features +- **docs:** added cdn installation guide ([#4045](https://github.com/ueberdosis/tiptap-workspace/issues/4045)) ([8536508](https://github.com/ueberdosis/tiptap-workspace/commit/853650885b7c4f2217a4b37bc42ee65b4cd6026a)) +# [2.1.0-rc.9](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.8...v2.1.0-rc.9) (2023-06-15) +# [2.1.0-rc.8](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.7...v2.1.0-rc.8) (2023-05-25) -# [2.1.0-rc.4](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.3...v2.1.0-rc.4) (2023-04-27) +# [2.1.0-rc.7](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.6...v2.1.0-rc.7) (2023-05-25) +# [2.1.0-rc.5](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.4...v2.1.0-rc.5) (2023-05-25) ### Bug Fixes -* **link:** fix links autolinking when not needed ([#3989](https://github.com/ueberdosis/tiptap/issues/3989)) ([71946c1](https://github.com/ueberdosis/tiptap/commit/71946c18accf8a2e8192951de870f84e25f58ed5)) +- **extension-link:** fix paste handling ([d19267e](https://github.com/ueberdosis/tiptap-workspace/commit/d19267ecefabf08e4bd27c52424ed83991ce7270)) +- typo in commands.md ([a2a9822](https://github.com/ueberdosis/tiptap-workspace/commit/a2a9822f240df2301932a67225d9adcac2f18807)) +### Features +- add tiptap class ([614fc80](https://github.com/ueberdosis/tiptap-workspace/commit/614fc8082c376bf3c40a05c23ceda6b4a6fbf8d0)) +# [2.1.0-rc.4](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.3...v2.1.0-rc.4) (2023-04-27) +### Bug Fixes -# [2.1.0-rc.3](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.2...v2.1.0-rc.3) (2023-04-26) +- **link:** fix links autolinking when not needed ([#3989](https://github.com/ueberdosis/tiptap-workspace/issues/3989)) ([71946c1](https://github.com/ueberdosis/tiptap-workspace/commit/71946c18accf8a2e8192951de870f84e25f58ed5)) +# [2.1.0-rc.3](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.2...v2.1.0-rc.3) (2023-04-26) ### Bug Fixes -* **core:** remove configure from extend functionality ([4af54da](https://github.com/ueberdosis/tiptap/commit/4af54da3e09c69c0b5326f9952d456436855914d)) +- **core:** remove configure from extend functionality ([4af54da](https://github.com/ueberdosis/tiptap-workspace/commit/4af54da3e09c69c0b5326f9952d456436855914d)) + +# [2.1.0-rc.2](https://github.com/ueberdosis/tiptap-workspace/compare/v2.0.3...v2.1.0-rc.2) (2023-04-26) +### Bug Fixes +- **extension-link:** fix link not being kept when pasting url with link ([#3975](https://github.com/ueberdosis/tiptap-workspace/issues/3975)) ([e7d7d49](https://github.com/ueberdosis/tiptap-workspace/commit/e7d7d496376c8c11e24c342e20bd179a6ea7dcee)) +# [2.1.0-rc.1](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.0...v2.1.0-rc.1) (2023-04-12) +### Bug Fixes -# [2.1.0-rc.2](https://github.com/ueberdosis/tiptap/compare/v2.0.3...v2.1.0-rc.2) (2023-04-26) +- **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap-workspace/issues/3956)) ([e8cef04](https://github.com/ueberdosis/tiptap-workspace/commit/e8cef0404b5039ec2657536976b8b31931afd337)) +# [2.1.0-rc.0](https://github.com/ueberdosis/tiptap-workspace/compare/v2.0.2...v2.1.0-rc.0) (2023-04-05) ### Bug Fixes -* **extension-link:** fix link not being kept when pasting url with link ([#3975](https://github.com/ueberdosis/tiptap/issues/3975)) ([e7d7d49](https://github.com/ueberdosis/tiptap/commit/e7d7d496376c8c11e24c342e20bd179a6ea7dcee)) - +- clear nodes when cursor at start of empty isolating parent ([#3943](https://github.com/ueberdosis/tiptap-workspace/issues/3943)) ([7278ee2](https://github.com/ueberdosis/tiptap-workspace/commit/7278ee2b05de2f96efddf3b1dc3bfd3d52262cbb)) +- **list-item:** improve delete behaviour ([09782a5](https://github.com/ueberdosis/tiptap-workspace/commit/09782a5b066b2f9f52f0ef1d8701d6e5b063dc63)) +- **lists:** improve list behaviour ([684e48a](https://github.com/ueberdosis/tiptap-workspace/commit/684e48a4a7778a0140c94f0c5345db868174ad81)) +- Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap-workspace/issues/3914)) ([0c1bba3](https://github.com/ueberdosis/tiptap-workspace/commit/0c1bba3137b535776bcef95ff3c55e13f5a2db46)) +# [2.1.0-rc.12](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.11...v2.1.0-rc.12) (2023-07-14) -# [2.1.0-rc.1](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.0...v2.1.0-rc.1) (2023-04-12) +**Note:** Version bump only for package tiptap +# [2.1.0-rc.11](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.10...v2.1.0-rc.11) (2023-07-07) ### Bug Fixes -* **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap/issues/3956)) ([e8cef04](https://github.com/ueberdosis/tiptap/commit/e8cef0404b5039ec2657536976b8b31931afd337)) +- **core:** fix cut and insertContentAt functions ([#4187](https://github.com/ueberdosis/tiptap/issues/4187)) ([6b65af8](https://github.com/ueberdosis/tiptap/commit/6b65af8fc31ffbbcf79b89bfdaceee7aadbf3f27)) +- **tests:** fix link rel tests ([c1d1854](https://github.com/ueberdosis/tiptap/commit/c1d18543b03b1fb6b99a2f3546aa5da10c919920)) + +# [2.1.0-rc.10](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.9...v2.1.0-rc.10) (2023-07-07) +### Bug Fixes +- do not use window.open for links in readonly mode ([#4073](https://github.com/ueberdosis/tiptap/issues/4073)) ([4bca77e](https://github.com/ueberdosis/tiptap/commit/4bca77e4e9c96596d584cf71b8d831dc2ab0a421)) +- **extension-link:** fixes link going to wrong url ([#4078](https://github.com/ueberdosis/tiptap/issues/4078)) ([3053865](https://github.com/ueberdosis/tiptap/commit/30538654752ab3ded6e56c869745ccacc8cdeabc)) +- **link:** Prevent auto-linking when typing URL inside inline code mark ([#4160](https://github.com/ueberdosis/tiptap/issues/4160)) ([b24df3a](https://github.com/ueberdosis/tiptap/commit/b24df3aa4c2f3fdb2ed6122d2d32fb7c4e07f2af)) +- **react:** check props.clientRect before creating ReactRenderer ([#4138](https://github.com/ueberdosis/tiptap/issues/4138)) ([d710846](https://github.com/ueberdosis/tiptap/commit/d710846ecb6a3059dfbc21300b9a4b887a8defa3)) +- **react:** update select state when text selection is around node ([#4148](https://github.com/ueberdosis/tiptap/issues/4148)) ([5bd5bd4](https://github.com/ueberdosis/tiptap/commit/5bd5bd4ecdbe1f952b23d5f5efad16b6ed5cc44f)) -# [2.1.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.0.2...v2.1.0-rc.0) (2023-04-05) +### Features +- **docs:** added cdn installation guide ([#4045](https://github.com/ueberdosis/tiptap/issues/4045)) ([8536508](https://github.com/ueberdosis/tiptap/commit/853650885b7c4f2217a4b37bc42ee65b4cd6026a)) + +# [2.1.0-rc.9](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.8...v2.1.0-rc.9) (2023-06-15) ### Bug Fixes -* clear nodes when cursor at start of empty isolating parent ([#3943](https://github.com/ueberdosis/tiptap/issues/3943)) ([7278ee2](https://github.com/ueberdosis/tiptap/commit/7278ee2b05de2f96efddf3b1dc3bfd3d52262cbb)) -* Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap/issues/3914)) ([0c1bba3](https://github.com/ueberdosis/tiptap/commit/0c1bba3137b535776bcef95ff3c55e13f5a2db46)) +- **list-item:** improve delete behaviour ([09782a5](https://github.com/ueberdosis/tiptap/commit/09782a5b066b2f9f52f0ef1d8701d6e5b063dc63)) +- **lists:** improve list behaviour ([684e48a](https://github.com/ueberdosis/tiptap/commit/684e48a4a7778a0140c94f0c5345db868174ad81)) +# [2.1.0-rc.8](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.7...v2.1.0-rc.8) (2023-05-25) +**Note:** Version bump only for package tiptap +# [2.1.0-rc.7](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.6...v2.1.0-rc.7) (2023-05-25) +**Note:** Version bump only for package tiptap +# [2.1.0-rc.6](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.5...v2.1.0-rc.6) (2023-05-25) -# [2.1.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.0.2...v2.1.0-rc.0) (2023-04-05) +**Note:** Version bump only for package tiptap +# [2.1.0-rc.5](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.4...v2.1.0-rc.5) (2023-05-25) ### Bug Fixes -* clear nodes when cursor at start of empty isolating parent ([#3943](https://github.com/ueberdosis/tiptap/issues/3943)) ([7278ee2](https://github.com/ueberdosis/tiptap/commit/7278ee2b05de2f96efddf3b1dc3bfd3d52262cbb)) -* Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap/issues/3914)) ([0c1bba3](https://github.com/ueberdosis/tiptap/commit/0c1bba3137b535776bcef95ff3c55e13f5a2db46)) -* **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap/issues/3956)) ([a78f8cd](https://github.com/ueberdosis/tiptap/commit/a78f8cd9646008e4db938fa3c22b0714c8bb5849)) +- **extension-link:** fix paste handling ([d19267e](https://github.com/ueberdosis/tiptap/commit/d19267ecefabf08e4bd27c52424ed83991ce7270)) +- typo in commands.md ([a2a9822](https://github.com/ueberdosis/tiptap/commit/a2a9822f240df2301932a67225d9adcac2f18807)) + +### Features +- add tiptap class ([614fc80](https://github.com/ueberdosis/tiptap/commit/614fc8082c376bf3c40a05c23ceda6b4a6fbf8d0)) +# [2.1.0-rc.4](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.3...v2.1.0-rc.4) (2023-04-27) +### Bug Fixes +- **link:** fix links autolinking when not needed ([#3989](https://github.com/ueberdosis/tiptap/issues/3989)) ([71946c1](https://github.com/ueberdosis/tiptap/commit/71946c18accf8a2e8192951de870f84e25f58ed5)) -## [2.0.3](https://github.com/ueberdosis/tiptap/compare/v2.0.2...v2.0.3) (2023-04-13) +# [2.1.0-rc.3](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.2...v2.1.0-rc.3) (2023-04-26) ### Bug Fixes -* **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap/issues/3956)) ([e8cef04](https://github.com/ueberdosis/tiptap/commit/e8cef0404b5039ec2657536976b8b31931afd337)) +- **core:** remove configure from extend functionality ([4af54da](https://github.com/ueberdosis/tiptap/commit/4af54da3e09c69c0b5326f9952d456436855914d)) +# [2.1.0-rc.2](https://github.com/ueberdosis/tiptap/compare/v2.0.3...v2.1.0-rc.2) (2023-04-26) +### Bug Fixes +- **extension-link:** fix link not being kept when pasting url with link ([#3975](https://github.com/ueberdosis/tiptap/issues/3975)) ([e7d7d49](https://github.com/ueberdosis/tiptap/commit/e7d7d496376c8c11e24c342e20bd179a6ea7dcee)) -## [2.0.2](https://github.com/ueberdosis/tiptap/compare/v2.0.1...v2.0.2) (2023-04-03) +# [2.1.0-rc.1](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.0...v2.1.0-rc.1) (2023-04-12) + +### Bug Fixes + +- **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap/issues/3956)) ([e8cef04](https://github.com/ueberdosis/tiptap/commit/e8cef0404b5039ec2657536976b8b31931afd337)) +# [2.1.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.0.2...v2.1.0-rc.0) (2023-04-05) ### Bug Fixes -* **react:** fix rebinding events not overwriting editor.on ([#3935](https://github.com/ueberdosis/tiptap/issues/3935)) ([64ab357](https://github.com/ueberdosis/tiptap/commit/64ab3570c1e86a65f5022793acb0292d8972dcd7)) +- clear nodes when cursor at start of empty isolating parent ([#3943](https://github.com/ueberdosis/tiptap/issues/3943)) ([7278ee2](https://github.com/ueberdosis/tiptap/commit/7278ee2b05de2f96efddf3b1dc3bfd3d52262cbb)) +- Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap/issues/3914)) ([0c1bba3](https://github.com/ueberdosis/tiptap/commit/0c1bba3137b535776bcef95ff3c55e13f5a2db46)) +# [2.1.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.0.2...v2.1.0-rc.0) (2023-04-05) -### Features +### Bug Fixes -* add box-shadow to collab demo ([c5496c1](https://github.com/ueberdosis/tiptap/commit/c5496c1b27783150dafb5ebdf6bda43648a46316)) -* landingpage demo ([#3925](https://github.com/ueberdosis/tiptap/issues/3925)) ([958925f](https://github.com/ueberdosis/tiptap/commit/958925f2560ca786cd0cf52b83b7ae51deb7dd77)) -* Tiptap collab demo styling ([87840b0](https://github.com/ueberdosis/tiptap/commit/87840b0f0821ca65d9f104d9c90512021aa70113)) +- clear nodes when cursor at start of empty isolating parent ([#3943](https://github.com/ueberdosis/tiptap/issues/3943)) ([7278ee2](https://github.com/ueberdosis/tiptap/commit/7278ee2b05de2f96efddf3b1dc3bfd3d52262cbb)) +- Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap/issues/3914)) ([0c1bba3](https://github.com/ueberdosis/tiptap/commit/0c1bba3137b535776bcef95ff3c55e13f5a2db46)) +- **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap/issues/3956)) ([a78f8cd](https://github.com/ueberdosis/tiptap/commit/a78f8cd9646008e4db938fa3c22b0714c8bb5849)) +## [2.0.3](https://github.com/ueberdosis/tiptap/compare/v2.0.2...v2.0.3) (2023-04-13) +### Bug Fixes +- **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap/issues/3956)) ([e8cef04](https://github.com/ueberdosis/tiptap/commit/e8cef0404b5039ec2657536976b8b31931afd337)) +## [2.0.2](https://github.com/ueberdosis/tiptap/compare/v2.0.1...v2.0.2) (2023-04-03) -## [2.0.1](https://github.com/ueberdosis/tiptap/compare/v2.0.0...v2.0.1) (2023-03-30) +### Bug Fixes + +- **react:** fix rebinding events not overwriting editor.on ([#3935](https://github.com/ueberdosis/tiptap/issues/3935)) ([64ab357](https://github.com/ueberdosis/tiptap/commit/64ab3570c1e86a65f5022793acb0292d8972dcd7)) + +### Features +- add box-shadow to collab demo ([c5496c1](https://github.com/ueberdosis/tiptap/commit/c5496c1b27783150dafb5ebdf6bda43648a46316)) +- landingpage demo ([#3925](https://github.com/ueberdosis/tiptap/issues/3925)) ([958925f](https://github.com/ueberdosis/tiptap/commit/958925f2560ca786cd0cf52b83b7ae51deb7dd77)) +- Tiptap collab demo styling ([87840b0](https://github.com/ueberdosis/tiptap/commit/87840b0f0821ca65d9f104d9c90512021aa70113)) + +## [2.0.1](https://github.com/ueberdosis/tiptap/compare/v2.0.0...v2.0.1) (2023-03-30) ### Bug Fixes -* Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap/issues/3914)) ([0534f76](https://github.com/ueberdosis/tiptap/commit/0534f76401bf5399c01ca7f39d87f7221d91b4f7)) +- Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap/issues/3914)) ([0534f76](https://github.com/ueberdosis/tiptap/commit/0534f76401bf5399c01ca7f39d87f7221d91b4f7)) ## [2.0.0](https://github.com/ueberdosis/tiptap/compare/tiptap@1.32.2...v2.0.0) (2023-03-29) ## What's Changed -* Fix sending of emptystring class for Prosemirror decoration by @ascott18 in https://github.com/ueberdosis/tiptap/pull/1004 -* build(deps): bump actions/cache from v2.1.4 to v2.1.5 by @dependabot in https://github.com/ueberdosis/tiptap/pull/1024 -* build(deps): bump actions/upload-artifact from v2.2.2 to v2.2.3 by @dependabot in https://github.com/ueberdosis/tiptap/pull/1025 -* Add install instructions by @MarcelloTheArcane in https://github.com/ueberdosis/tiptap/pull/1196 -* Fix a small typo by @swanson in https://github.com/ueberdosis/tiptap/pull/1211 -* Add missing word by @swanson in https://github.com/ueberdosis/tiptap/pull/1216 -* Clarify table header documentation by @swanson in https://github.com/ueberdosis/tiptap/pull/1215 -* Typo fix by @swanson in https://github.com/ueberdosis/tiptap/pull/1217 -* Make Horizontal Rule compatible with Typography extension by @chrisarmstrong in https://github.com/ueberdosis/tiptap/pull/1241 -* Fix returning true/false in can().chain().run() by @Markario in https://github.com/ueberdosis/tiptap/pull/1252 -* [Docs] Improve example integration with Laravel Livewire by @iksaku in https://github.com/ueberdosis/tiptap/pull/1255 -* feat: better types for Vue 2 by @zcuric in https://github.com/ueberdosis/tiptap/pull/1253 -* Fix typo by @DannyFeliz in https://github.com/ueberdosis/tiptap/pull/1262 -* HorizontalRule is included in defaultExtensions by @Duncank in https://github.com/ueberdosis/tiptap/pull/1267 -* VueRenderer's ref is undefined when in production mode by @thechrisoshow in https://github.com/ueberdosis/tiptap/pull/1271 -* feat: expose node helpers by @zcuric in https://github.com/ueberdosis/tiptap/pull/1278 -* New Feature: Generate JSON from HTML by @hanspagel in https://github.com/ueberdosis/tiptap/pull/1273 -* feat: export mark helpers by @zcuric in https://github.com/ueberdosis/tiptap/pull/1301 -* When text align is default, don't add a style attribute by @robguthrie in https://github.com/ueberdosis/tiptap/pull/1251 -* docs: complete list of extensions with changed name by @Deckluhm in https://github.com/ueberdosis/tiptap/pull/1305 -* fix(core): Increment `i` in `defaultBlockAt` by @andreavaccari in https://github.com/ueberdosis/tiptap/pull/1315 -* Fix text-align extension url by @ralbear in https://github.com/ueberdosis/tiptap/pull/1325 -* docs: fix typo by @Priestch in https://github.com/ueberdosis/tiptap/pull/1339 -* Allow passing of DependencyList to useEditor by @YousefED in https://github.com/ueberdosis/tiptap/pull/1376 -* a small clerical error? by @akirarika in https://github.com/ueberdosis/tiptap/pull/1380 -* Make HTML in docs valid by @MoPaMo in https://github.com/ueberdosis/tiptap/pull/1381 -* Wording improvement by @jonathanmach in https://github.com/ueberdosis/tiptap/pull/1389 -* Prevent tiptap from creating duplicate style tags when injecting css by @mmachatschek in https://github.com/ueberdosis/tiptap/pull/1399 -* Adding type definition for result and removing the ts-nocheck by @sereneinserenade in https://github.com/ueberdosis/tiptap/pull/1419 -* Fix name of FloatingMenu by @shadow-light in https://github.com/ueberdosis/tiptap/pull/1429 -* New extensions: add subscript and superscript extensions (including docs and tests) by @hanspagel in https://github.com/ueberdosis/tiptap/pull/1404 -* Exclude superscript from subscript, and vice versa. by @BrianHung in https://github.com/ueberdosis/tiptap/pull/1436 -* Add keyboard shortcuts to toggle superscript and subscript marks. by @BrianHung in https://github.com/ueberdosis/tiptap/pull/1437 -* Make drop cursor default to regular caret color by @shadow-light in https://github.com/ueberdosis/tiptap/pull/1444 -* use forwardRef for react wrappers by @YousefED in https://github.com/ueberdosis/tiptap/pull/1452 -* Mention: Add text attribute by @tomhrtly in https://github.com/ueberdosis/tiptap/pull/1322 -* Fix removal of textStyle mark when any style resets by @bttger in https://github.com/ueberdosis/tiptap/pull/1465 -* Fix parsing of mention nodes by @shadow-light in https://github.com/ueberdosis/tiptap/pull/1471 -* Correct default for dropcursor color in docs by @shadow-light in https://github.com/ueberdosis/tiptap/pull/1479 -* Improve gapcursor docs by @carlobeltrame in https://github.com/ueberdosis/tiptap/pull/1497 -* VueRenderer documentation with version 3 by @Tazi0 in https://github.com/ueberdosis/tiptap/pull/1491 -* Update introduction.md by @phillduffy in https://github.com/ueberdosis/tiptap/pull/1509 -* Link to contribution guidelines in CONTRIBUTING.md by @robertvanhoesel in https://github.com/ueberdosis/tiptap/pull/1541 -* build(deps): bump actions/setup-node from 2.1.5 to 2.2.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/1544 -* export createTable by @YousefED in https://github.com/ueberdosis/tiptap/pull/1469 -* doc update: onSelection → onSelectionUpdate by @forresto in https://github.com/ueberdosis/tiptap/pull/1555 -* update task-item.ts nodeview to update data-checked by @BrianHung in https://github.com/ueberdosis/tiptap/pull/1567 -* Fix typo by @JavierMartinz in https://github.com/ueberdosis/tiptap/pull/1587 -* Replace node-sass with dart sass and fix deprecation warning by @mmachatschek in https://github.com/ueberdosis/tiptap/pull/1590 -* Readd russian history shortcuts by @mmachatschek in https://github.com/ueberdosis/tiptap/pull/1589 -* Fix custom start for ordered lists by @mmachatschek in https://github.com/ueberdosis/tiptap/pull/1594 -* Doc fix: Remove braces from isEmpty & isEditable by @WilliamIPark in https://github.com/ueberdosis/tiptap/pull/1599 -* Export NodeViewRendererOptions by @sibiraj-s in https://github.com/ueberdosis/tiptap/pull/1607 -* Update hostic-dom to fix style attributes by @sibiraj-s in https://github.com/ueberdosis/tiptap/pull/1618 -* fix: export text align extension options by @iamursky in https://github.com/ueberdosis/tiptap/pull/1592 -* fix: export starter kit extension options by @iamursky in https://github.com/ueberdosis/tiptap/pull/1593 -* Adding types to Linter and making the structure a bit easier by @sereneinserenade in https://github.com/ueberdosis/tiptap/pull/1492 -* Additional input rules for typography by @arthurmcgregor in https://github.com/ueberdosis/tiptap/pull/1624 -* chore: add repository for all packages.json by @iamandrewluca in https://github.com/ueberdosis/tiptap/pull/1628 -* Fix typo by @ValentaTomas in https://github.com/ueberdosis/tiptap/pull/1634 -* Change TextAlignOptions to interface (not type) by @arthurmcgregor in https://github.com/ueberdosis/tiptap/pull/1623 -* Allow a rule to be skipped from the getAttributes callback by @joevallender in https://github.com/ueberdosis/tiptap/pull/1625 -* Fix multi character suggest by @flaviouk in https://github.com/ueberdosis/tiptap/pull/1620 -* Provide more context to update function to enable fewer re-renders by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1648 -* Examples: Syntax highlighting for React by @hanspagel in https://github.com/ueberdosis/tiptap/pull/1583 -* Apply the correct regex in markPasteRule by @joevallender in https://github.com/ueberdosis/tiptap/pull/1671 -* Fix typo by @Spone in https://github.com/ueberdosis/tiptap/pull/1693 -* build(deps): bump actions/setup-node from 2.2.0 to 2.4.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/1697 -* fix: use correct state when doc changed externally by @dkrym in https://github.com/ueberdosis/tiptap/pull/1646 -* ✨ Add CreateNodeFromContentOptions to insertContent by @castroCrea in https://github.com/ueberdosis/tiptap/pull/1678 -* Use correct reference for options.editorProps by @robertvanhoesel in https://github.com/ueberdosis/tiptap/pull/1540 -* ✨ Add typography trademark by @castroCrea in https://github.com/ueberdosis/tiptap/pull/1699 -* Menu improvements by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1714 -* Docs: Disable history demo buttons when commands are not available by @domnantas in https://github.com/ueberdosis/tiptap/pull/1721 -* fix some react focus issues by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1724 -* Update alpine docs by @sibiraj-s in https://github.com/ueberdosis/tiptap/pull/1733 -* Packages: Add a new `Color` extension to set the text color by @hanspagel in https://github.com/ueberdosis/tiptap/pull/1744 -* docs: add color picker to color extension demo by @domnantas in https://github.com/ueberdosis/tiptap/pull/1790 -* Fix Editor Reactivity by @nVitius in https://github.com/ueberdosis/tiptap/pull/1804 -* Add missing comma in example by @carlobeltrame in https://github.com/ueberdosis/tiptap/pull/1849 -* Allow triggering suggestions without prefix space by @jkosir in https://github.com/ueberdosis/tiptap/pull/1826 -* fix: change `this.value` to `value` in the vue examples with v-model by @MiloLug in https://github.com/ueberdosis/tiptap/pull/1813 -* Fix: Don’t initialize tippy on requestAnimationFrame to avoid race conditions by @enriquecastl in https://github.com/ueberdosis/tiptap/pull/1820 -* ✨ Follow Ref on ForwardRef component in reactRenderer by @castroCrea in https://github.com/ueberdosis/tiptap/pull/1690 -* feat: add extendEmptyMarkRange option to mark commands by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1859 -* Include children in placeholder plugin by @nickdbush in https://github.com/ueberdosis/tiptap/pull/1416 -* Horizontal rule demo: add selected style by @cadars in https://github.com/ueberdosis/tiptap/pull/1848 -* feat: add getText() and generateText() methods (fix #1428) by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1875 -* Fix usage example of CollaborationCursor by @carlobeltrame in https://github.com/ueberdosis/tiptap/pull/1911 -* Add type for async items on suggestions (fix TS strict types complain) by @d8vjork in https://github.com/ueberdosis/tiptap/pull/1912 -* Fix: code-block-lowlight child extensions do not highlight code by @enriquecastl in https://github.com/ueberdosis/tiptap/pull/1917 -* Use pasteRegex in addPasteRules by @jvissers in https://github.com/ueberdosis/tiptap/pull/1922 -* Docs: Clear up Prosemirror EditorProps usage by @domnantas in https://github.com/ueberdosis/tiptap/pull/1918 -* Add enableCoreExtensions flag by @flaviouk in https://github.com/ueberdosis/tiptap/pull/1923 -* Docs: Update command names in upgrade guide by @jakedolan in https://github.com/ueberdosis/tiptap/pull/1906 -* Fix: nodeInputRule() support for group match by @nokola in https://github.com/ueberdosis/tiptap/pull/1574 -* Fix "destory" method in view plugins. by @KaneCohen in https://github.com/ueberdosis/tiptap/pull/1882 -* Fix 'Edit on Github' link url for examples in docs by @mmachatschek in https://github.com/ueberdosis/tiptap/pull/1929 -* New example for custom documents (to force a heading on the top) by @hanspagel in https://github.com/ueberdosis/tiptap/pull/1948 -* Added better types for event emitter by @HuiiBuh in https://github.com/ueberdosis/tiptap/pull/1959 -* Use ref to move contentDOM by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1960 -* fix: compatibility with lowlight v2 by @fengzilong in https://github.com/ueberdosis/tiptap/pull/1939 -* build(deps): bump actions/setup-node from 2.4.0 to 2.4.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/1978 -* Fix typo in hard-break.md by @davidkrijgsman in https://github.com/ueberdosis/tiptap/pull/1988 -* Added Next.js installation guide & express setup for React by @alb in https://github.com/ueberdosis/tiptap/pull/1984 -* Fixed typo in React installation guide by @alb in https://github.com/ueberdosis/tiptap/pull/1989 -* docs: update styling by @hzpeng57 in https://github.com/ueberdosis/tiptap/pull/1998 -* React collaboration demo by @svenadlung in https://github.com/ueberdosis/tiptap/pull/1991 -* Integrate input rules and paste rules into the core by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1997 -* Changing use of InputRule to textInputRule for Savvy example by @jakedolan in https://github.com/ueberdosis/tiptap/pull/2007 -* docs: correct the wording by @mittalyashu in https://github.com/ueberdosis/tiptap/pull/2012 -* Fix #2016 Image input rule by @nokola in https://github.com/ueberdosis/tiptap/pull/2020 -* Improve `ReactRenderer` types by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2011 -* Add `editor` dependency when registering `BubbleMenuPlugin` by @ValentaTomas in https://github.com/ueberdosis/tiptap/pull/2018 -* Allow to use commands within InputRule and PasteRule by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2035 -* build(deps): bump actions/checkout from 2.3.4 to 2.3.5 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2051 -* Add extension storage by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2069 -* Separate drags from drops in stopEvent by @thatsjonsense in https://github.com/ueberdosis/tiptap/pull/2070 -* Add editor to items prop in suggestion plugin by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2082 -* Check node type above custom update fn by @thatsjonsense in https://github.com/ueberdosis/tiptap/pull/2081 -* Add savvy example tests by @donovanglover in https://github.com/ueberdosis/tiptap/pull/2043 -* Add unit tests for demos/src/Examples/Minimal/Vue by @AlexandruValeanu in https://github.com/ueberdosis/tiptap/pull/2047 -* Added tests for Menus example by @alb in https://github.com/ueberdosis/tiptap/pull/2052 -* Docs: Fixing onUpdate example by @chris-sev in https://github.com/ueberdosis/tiptap/pull/2084 -* Fix menu example in doc by @phoenixgao in https://github.com/ueberdosis/tiptap/pull/2089 -* Replace `defaultOptions` with `addOptions` by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2088 -* docs: fix typo by @Deckluhm in https://github.com/ueberdosis/tiptap/pull/2093 -* Use the new storage feature for the `CollaborationCursor` extension by @hanspagel in https://github.com/ueberdosis/tiptap/pull/2096 -* Improve behavior when using insertContent by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2147 -* build(deps): bump actions/checkout from 2.3.5 to 2.4.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2145 -* Switch from hostic dom to zeed dom by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2151 -* fix typo in events.md by @millerrafi in https://github.com/ueberdosis/tiptap/pull/2152 -* update getJSON return type to JSONContent by @lecstor in https://github.com/ueberdosis/tiptap/pull/2153 -* Update image.md by @georgemandis in https://github.com/ueberdosis/tiptap/pull/2154 -* update zeed dom by @floriankrueger in https://github.com/ueberdosis/tiptap/pull/2155 -* Floating menu - remove composition check by @dkrym in https://github.com/ueberdosis/tiptap/pull/2137 -* Remove console.log statement from codeblock-lowlight-plugin file by @enriquecastl in https://github.com/ueberdosis/tiptap/pull/2168 -* Ignore iOS mutations when unfocused by @thatsjonsense in https://github.com/ueberdosis/tiptap/pull/2170 -* feat: Allow array of extensions for `enableInputRules` and `enablePasteRules` by @aguingand in https://github.com/ueberdosis/tiptap/pull/2119 -* Export type ColorOptions by @apaar97 in https://github.com/ueberdosis/tiptap/pull/2180 -* Split vue and react variant for interactivity demo by @svenadlung in https://github.com/ueberdosis/tiptap/pull/2186 -* Add `setEditable` to the Editor documentation by @floriankrueger in https://github.com/ueberdosis/tiptap/pull/2199 -* Bump actions/cache from 2.1.5 to 2.1.7 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2207 -* Bump actions/setup-node from 2.4.1 to 2.5.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2208 -* feat(ReactNodeViewRenderer): Add `as` option and pass through to ReactRenderer by @jessicalc in https://github.com/ueberdosis/tiptap/pull/2213 -* Add support for autolink by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2226 -* initialize autofocus selection in `createView` by @BrianHung in https://github.com/ueberdosis/tiptap/pull/2212 -* Use named exports instead of default exports by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2238 -* Svelte Example: remove wrong `type="context"` tag by @duruer in https://github.com/ueberdosis/tiptap/pull/2240 -* A brand new `CharacterCount` extension by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2256 -* join lists on toggleList by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2260 -* build(deps): bump actions/upload-artifact from 2.2.3 to 2.3.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2269 -* fix: show FloatingMenu by default only if focused by @jaulz in https://github.com/ueberdosis/tiptap/pull/2275 -* Improve backspace handling by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2284 -* Make sure editor is available on first render by @ryanto in https://github.com/ueberdosis/tiptap/pull/2282 -* fix typo in floating menu docs by @nucleartux in https://github.com/ueberdosis/tiptap/pull/2290 -* Add setup for plain js demos by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2288 -* build(deps): bump actions/upload-artifact from 2.3.0 to 2.3.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2300 -* Remove `element.current` from `useEffect` in `BubbleMenu` and `FloatingMenu` by @ValentaTomas in https://github.com/ueberdosis/tiptap/pull/2297 -* Using vue 2 and 3 when passing props to VueRenderer in Mention plugin by @domstrueboy in https://github.com/ueberdosis/tiptap/pull/2319 -* Fix typo in readme by @stijndcl in https://github.com/ueberdosis/tiptap/pull/2333 -* Fix typos in typescript.md by @hatefrad in https://github.com/ueberdosis/tiptap/pull/2339 -* typo in docs/api/editor.md by @milahu in https://github.com/ueberdosis/tiptap/pull/2338 -* Added setup script syntax to Vue 3 install docs by @NuroDev in https://github.com/ueberdosis/tiptap/pull/2324 -* build(deps): bump actions/setup-node from 2.5.0 to 2.5.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2343 -* change reactrenderer component type definition by @lukesmurray in https://github.com/ueberdosis/tiptap/pull/2327 -* Export type FontFamilyOptions by @apaar97 in https://github.com/ueberdosis/tiptap/pull/2345 -* Update vue3.md Grammar Error In Docs by @Aiyush-G in https://github.com/ueberdosis/tiptap/pull/2349 -* Fix typo in contributing.md by @webri in https://github.com/ueberdosis/tiptap/pull/2352 -* Vue3 CLI doesn't have "npm run dev" by @Aiyush-G in https://github.com/ueberdosis/tiptap/pull/2350 -* fix: export type `Level` for external use by @webri in https://github.com/ueberdosis/tiptap/pull/2354 -* add way to cancel inputrules and pasterules by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2368 -* Mark `@tiptap/react` and `@tiptap/core` as side effect free by @dcastil in https://github.com/ueberdosis/tiptap/pull/2361 -* Nuxt specific corrections by @gsqrt2 in https://github.com/ueberdosis/tiptap/pull/2410 -* build(deps): bump nanoid from 3.1.30 to 3.2.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2419 -* build(deps): bump node-fetch from 2.6.6 to 2.6.7 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2424 -* fix: use toggleHeader from prosemirror-tables by @jpobley in https://github.com/ueberdosis/tiptap/pull/2412 -* docs(nodes/image/react): remove v-if by @strdr4605 in https://github.com/ueberdosis/tiptap/pull/2461 -* Fix: Typo in Focus Command Documentation of Editor by @AngadSethi in https://github.com/ueberdosis/tiptap/pull/2476 -* expose hasAnchor to custom placeholder function by @YousefED in https://github.com/ueberdosis/tiptap/pull/2470 -* Add key bindings for uppercase letters for bold, italic and underline by @mejo- in https://github.com/ueberdosis/tiptap/pull/2478 -* Allow individual Typography rules to be disabled by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2449 -* Docs/toc undo fix by @codemzy in https://github.com/ueberdosis/tiptap/pull/2484 -* build(deps): bump nanoid from 3.1.30 to 3.2.0 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/2480 -* chore: added visual studio code debugging launch options by @bdbch in https://github.com/ueberdosis/tiptap/pull/2695 -* fix: don't override behaviour of Home / End in pc keymap by @scottsidwell in https://github.com/ueberdosis/tiptap/pull/2691 -* fix: Mark the bubble/floating menu extensions as side effect free by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2677 -* build(deps-dev): bump minimist from 1.2.5 to 1.2.6 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2667 -* build(deps): bump minimist from 1.2.5 to 1.2.6 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/2672 -* fix: prevent suggestions from being active when editor is readonly by @scottsidwell in https://github.com/ueberdosis/tiptap/pull/2692 -* fix: Allow tippyOptions.getReferenceClientRect in bubble menu to be overridden by @fleon in https://github.com/ueberdosis/tiptap/pull/2668 -* fix: allow [] as a prefix for task items by @bdbch in https://github.com/ueberdosis/tiptap/pull/2698 -* fix: improve Vue nodeViewProps typing by @DanSnow in https://github.com/ueberdosis/tiptap/pull/2681 -* fix: remove extension-text-style from character-cout peer dependencies by @pradel in https://github.com/ueberdosis/tiptap/pull/2696 -* fix(extension-link): prevent parsing `javascript:` pseudo-protocol by @phenax in https://github.com/ueberdosis/tiptap/pull/2646 -* build(deps): bump actions/cache from 2.1.7 to 3.0.2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2701 -* build(deps): bump actions/checkout from 2.4.0 to 3.0.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2699 -* build(deps): bump actions/upload-artifact from 2.3.1 to 3.0.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2700 -* build(deps): bump actions/setup-node from 2.5.1 to 3.1.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2705 -* Add support for React 18 by @dcastil in https://github.com/ueberdosis/tiptap/pull/2676 -* fix broken GuideContent demos not rendering because of unexpected use… by @bdbch in https://github.com/ueberdosis/tiptap/pull/2709 -* Docs: fix file names in PHP installation by @aguingand in https://github.com/ueberdosis/tiptap/pull/2644 -* Add support for CSS Modules by @XAHTEP26 in https://github.com/ueberdosis/tiptap/pull/2723 -* Use vitejs/plugin-react and include react dependencies by @svenadlung in https://github.com/ueberdosis/tiptap/pull/2732 -* build(deps-dev): bump minimist from 1.2.5 to 1.2.6 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2725 -* build(deps): bump actions/checkout from 3.0.0 to 3.0.2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2727 -* feat: Add `onBeforeStart` and `onBeforeUpdate` handlers to the render function by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2628 -* feat: Add a generic type for suggestion items by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2610 -* Reduce bundle size of @tiptap/extension-table package by @enriquecastl in https://github.com/ueberdosis/tiptap/pull/2622 -* Update Suggestion package.json by @dphuang2 in https://github.com/ueberdosis/tiptap/pull/2739 -* fix: Support inline nodes with content in @tiptap/suggestion by @thatsjonsense in https://github.com/ueberdosis/tiptap/pull/2648 -* Allow class attribute through setLink() by @Ken-vdE in https://github.com/ueberdosis/tiptap/pull/2758 -* update people by @patrickbaber in https://github.com/ueberdosis/tiptap/pull/2776 -* fix: properly calculate setDragImage position by @dilizarov in https://github.com/ueberdosis/tiptap/pull/2768 -* Ensure VueNodeViewRenderer will use Editor's Global Vue Instance by @ralphschindler in https://github.com/ueberdosis/tiptap/pull/2604 -* refactor(global): remove yarn in favor for npm by @bdbch in https://github.com/ueberdosis/tiptap/pull/2775 -* add support for CSP nonces in createStyleTag by @fekle in https://github.com/ueberdosis/tiptap/pull/2601 -* add validate option to link extension by @bdbch in https://github.com/ueberdosis/tiptap/pull/2781 -* Cypress tests for examples by @bdbch in https://github.com/ueberdosis/tiptap/pull/2777 -* build(deps): bump actions/setup-node from 3.1.1 to 3.2.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2793 -* fix: extendMarkRange doesn't work when cursor is at end of mark, despite isActive() returning true for that mark by @JDinABox in https://github.com/ueberdosis/tiptap/pull/2717 -* Expose "range" to textSerializer. Used in "getTextBetween" by @panta82 in https://github.com/ueberdosis/tiptap/pull/2684 -* Export `getTextSerializersFromSchema` helper, and fix typo in its name by @sjdemartini in https://github.com/ueberdosis/tiptap/pull/2750 -* fix: disable broken tests for experiements with further todo message by @bdbch in https://github.com/ueberdosis/tiptap/pull/2808 -* Add `className` option and pass through to ReactRenderer by @anton-liubushkin in https://github.com/ueberdosis/tiptap/pull/2794 -* Fix InputRule regex matcher ignoring non-text leaflets in textBefore by @bdbch in https://github.com/ueberdosis/tiptap/pull/2807 -* Add option to allow task items to be checkable (uncontrolled) by @kaspnilsson in https://github.com/ueberdosis/tiptap/pull/2474 -* feat: Required attributes by @thatsjonsense in https://github.com/ueberdosis/tiptap/pull/2640 -* Update team by @montapro in https://github.com/ueberdosis/tiptap/pull/2791 -* fix: Only trigger image input rule at the start or with a preceding space by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2830 -* In Vue 2 VueRenderer, only Vue.extend() non-VueConstructor arguments by @ralphschindler in https://github.com/ueberdosis/tiptap/pull/2824 -* fix(suggestion): :bug: make clientrect prop optional by @bdbch in https://github.com/ueberdosis/tiptap/pull/2813 -* build(deps): bump actions/cache from 3.0.2 to 3.0.3 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2851 -* Fixed(vue-2): `Avoid mutating a prop directly` error message to reproduce by @HondryTravis in https://github.com/ueberdosis/tiptap/pull/2834 -* Add support for custom protocols in extension-link by @shaunabanana in https://github.com/ueberdosis/tiptap/pull/2832 -* fix(textStyle): Null-safe parseHTML getting no color/fontFamily from HTMLElement styles by @d8vjork in https://github.com/ueberdosis/tiptap/pull/2825 -* build(deps): bump actions/upload-artifact from 3.0.0 to 3.1.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2820 -* Declare lowlight as a peerDependency in `@tiptap/extension-code-block-lowlight` by @enriquecastl in https://github.com/ueberdosis/tiptap/pull/2625 -* add precommit hook for linting and automatic eslint fixes + update eslint packages by @bdbch in https://github.com/ueberdosis/tiptap/pull/2862 -* Adding missing extensions to docs in https://tiptap.dev/api/extensions by @Lior539 in https://github.com/ueberdosis/tiptap/pull/2856 -* docs(docs): add missing documentation for commands by @bdbch in https://github.com/ueberdosis/tiptap/pull/2861 -* refactor: use index files for imports to simplify the export flow by @bdbch in https://github.com/ueberdosis/tiptap/pull/2870 -* feat(extension/youtube): :sparkles: new youtube embed extension by @bdbch in https://github.com/ueberdosis/tiptap/pull/2814 -* build(deps): bump actions/cache from 3.0.3 to 3.0.4 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2877 -* build(deps): bump actions/setup-node from 3.2.0 to 3.3.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2878 -* chore: migrate to new versions of prosemirror packages by @bdbch in https://github.com/ueberdosis/tiptap/pull/2854 -* docs: improve docs for youtube extension by @svenadlung in https://github.com/ueberdosis/tiptap/pull/2902 -* Allow setting `whiteSpace` style for `NodeViewWrapper` & `NodeViewContent` by @EvitanRelta in https://github.com/ueberdosis/tiptap/pull/2884 -* refactor(maintainment): set dependency versions for prosemirror and y… by @bdbch in https://github.com/ueberdosis/tiptap/pull/2904 -* feat: Allow multiple prefix characters to trigger a suggestion by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2896 -* fix: editor don't has contentComponent attribute when suggestion onUp… by @Young6118 in https://github.com/ueberdosis/tiptap/pull/2916 -* Fix state update after component unmounted by @SavKS in https://github.com/ueberdosis/tiptap/pull/2857 -* docs: fix livewire attribute by @ccchapman in https://github.com/ueberdosis/tiptap/pull/2928 -* build(deps): bump parse-url from 6.0.0 to 6.0.2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2961 -* fix(core): only respect text of node before current position (#2937) by @svenadlung in https://github.com/ueberdosis/tiptap/pull/2941 -* chore: lint only staged files by @ahhshm in https://github.com/ueberdosis/tiptap/pull/2957 -* fix(core): dont use selection for setContent replacement by @bdbch in https://github.com/ueberdosis/tiptap/pull/2934 -* refactor: remove duplicated function by @ahhshm in https://github.com/ueberdosis/tiptap/pull/2956 -* docs(figure): pass an object to `nodeInputRule` by @ahhshm in https://github.com/ueberdosis/tiptap/pull/2954 -* docs: update alpine installation by @patrickbaber in https://github.com/ueberdosis/tiptap/pull/3081 -* docs(extensions): mention community extensions and discussion thread by @sereneinserenade in https://github.com/ueberdosis/tiptap/pull/2991 -* build(deps-dev): bump svelte from 3.48.0 to 3.49.0 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/2992 -* build(deps-dev): bump svelte from 3.48.0 to 3.49.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2993 -* fix(core): isNodeSelection, isTextSelection not always false by @kivikakk in https://github.com/ueberdosis/tiptap/pull/3089 -* build(deps): bump actions/setup-node from 3.3.0 to 3.4.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2998 -* build(deps): bump terser from 5.14.1 to 5.14.2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3009 -* build(deps): bump actions/cache from 3.0.4 to 3.0.7 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3087 -* Fix pasteRulesPlugin always adding one extra character to text range by @Billiam in https://github.com/ueberdosis/tiptap/pull/2968 -* fix: let StarterKit be imported as common js module via named import by @sipec in https://github.com/ueberdosis/tiptap/pull/2967 -* fix(core): createCan command props shouldn't try dispatch (#3025) by @kivikakk in https://github.com/ueberdosis/tiptap/pull/3026 -* build(deps): bump actions/cache from 3.0.7 to 3.0.8 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3112 -* fix(core): setNodeSelection should not clamp pos by Selection.atStart/atEnd by @kivikakk in https://github.com/ueberdosis/tiptap/pull/3091 -* Make Suggestion extension use view.dom instead of document by @Faleij in https://github.com/ueberdosis/tiptap/pull/3093 -* fix(core): make setEditable trigger onUpdate function by @bdbch in https://github.com/ueberdosis/tiptap/pull/2935 -* fix: fix React Node View render problem in React 18 by @Darmody in https://github.com/ueberdosis/tiptap/pull/2985 -* feature(core): add exit handling for marks by @bdbch in https://github.com/ueberdosis/tiptap/pull/2925 -* build(deps-dev): bump vite from 2.9.12 to 2.9.13 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/3141 -* build(deps-dev): bump vite from 2.9.12 to 2.9.13 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3145 -* fix: vue inject grammar warning by @zhxqc in https://github.com/ueberdosis/tiptap/pull/3144 -* fix(core): make setEditable trigger all 'update' listeners by @Rhys-T in https://github.com/ueberdosis/tiptap/pull/3140 -* fix: Typo by @NagariaHussain in https://github.com/ueberdosis/tiptap/pull/3132 -* docs: fix naming by @masl in https://github.com/ueberdosis/tiptap/pull/3151 -* Include bubble menu element when checking if the editor view still has focus by @StefKors in https://github.com/ueberdosis/tiptap/pull/3150 -* Fix typo in docs by @carlobeltrame in https://github.com/ueberdosis/tiptap/pull/3162 -* fix(extension-code-block-lowlight): Bump lowlight to 2.7.0, remove outdated @types by @tarngerine in https://github.com/ueberdosis/tiptap/pull/3002 -* fix(core): insert PasteRule Node at matched position (#2942) by @edlb in https://github.com/ueberdosis/tiptap/pull/2943 -* add-empty-editor-class-to-root-div by @BrianHung in https://github.com/ueberdosis/tiptap/pull/2665 -* build(deps): bump parse-path from 4.0.4 to 5.0.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3178 -* fix: move React `flushSync` to microtask by @sampi in https://github.com/ueberdosis/tiptap/pull/3188 -* Fix bubble menu and floating menu being available when editor is not editable by @bdbch in https://github.com/ueberdosis/tiptap/pull/3195 -* feat: Add alias condition to code-block-lowlight by @dngwoodo in https://github.com/ueberdosis/tiptap/pull/3155 -* feat(extension-typography): add servicemark input rule by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3220 -* fix(types): fix link and table type errors by @johnfraney in https://github.com/ueberdosis/tiptap/pull/3208 -* test: fix failing test by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3230 -* feat(extension-link): Change autolink to only apply after breaking a word by @C-Hess in https://github.com/ueberdosis/tiptap/pull/3232 -* chore(maintainment): :rocket: update prosemirror packages by @bdbch in https://github.com/ueberdosis/tiptap/pull/3237 -* fix(core): Can() does not work for setting marks by @C-Hess in https://github.com/ueberdosis/tiptap/pull/3223 -* Ensure text blocks exist before referencing them by @ScopeyNZ in https://github.com/ueberdosis/tiptap/pull/3251 -* fix(core): InputRules does not work for ranges containing multiple text nodes by @hamflx in https://github.com/ueberdosis/tiptap/pull/3205 -* fix(core) - support attributes being null/undefined by @albertogiunta in https://github.com/ueberdosis/tiptap/pull/3245 -* fix: set default allowedPrefixes null by @Matrixbirds in https://github.com/ueberdosis/tiptap/pull/3239 -* fix(extension/link): fix last word value being undefined by @bdbch in https://github.com/ueberdosis/tiptap/pull/3258 -* build(deps): bump d3-color from 3.0.1 to 3.1.0 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/3260 -* docs: link YouTube node docs to proper GitHub url by @nielslanting in https://github.com/ueberdosis/tiptap/pull/3283 -* fix: typo in docs by @danielyuenhx in https://github.com/ueberdosis/tiptap/pull/3265 -* Fixed dragged text not being deleted after drop on another editor by @LuchoCateura in https://github.com/ueberdosis/tiptap/pull/3279 -* Fixed using both color and highlight together by @nkonev in https://github.com/ueberdosis/tiptap/pull/3311 -* Cleanup linkifyjs when the editor is destroyed by @educastellano in https://github.com/ueberdosis/tiptap/pull/3316 -* Feature/youtube parameters by @LuchoCateura in https://github.com/ueberdosis/tiptap/pull/3307 -* Fix installation and examples link by @catalinmiron in https://github.com/ueberdosis/tiptap/pull/3298 -* fix(docs): typo by @Calvein in https://github.com/ueberdosis/tiptap/pull/3362 -* fix(extension/placeholder): Resolve placeholder performance issues by @C-Hess in https://github.com/ueberdosis/tiptap/pull/3361 -* build(deps): bump parse-url from 7.0.2 to 8.1.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3384 -* refactor(extension/bubble-menu): add debounce to bubble menu updates by @bdbch in https://github.com/ueberdosis/tiptap/pull/3385 -* build(deps): bump actions/setup-node from 3.4.1 to 3.5.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3318 -* docs: Fix typos in CHANGELOG.md by @rvrvrv in https://github.com/ueberdosis/tiptap/pull/3328 -* build(deps): bump actions/cache from 3.0.8 to 3.0.11 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3317 -* fix: remove blur event listener from tippy element (#3365) by @MihirGH in https://github.com/ueberdosis/tiptap/pull/3366 -* fixes typo in suggestion.ts by @alejandrogarciasalas in https://github.com/ueberdosis/tiptap/pull/3386 -* docs(svelte): fix link to get started with svelte by @taismassaro in https://github.com/ueberdosis/tiptap/pull/3396 -* build(deps): bump loader-utils from 2.0.2 to 2.0.3 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3395 -* Update jobs.md by @montapro in https://github.com/ueberdosis/tiptap/pull/3432 -* extension/table: Fix prosemirror-tables dependency not using a correct namespace by @bdbch in https://github.com/ueberdosis/tiptap/pull/3448 -* typo: custom-extensions.md completely by @williamsk91 in https://github.com/ueberdosis/tiptap/pull/3447 -* Fix #3435 - CommonJS and ESM loading confusion by @tomi-bigpi in https://github.com/ueberdosis/tiptap/pull/3436 -* build(deps): bump loader-utils from 2.0.3 to 2.0.4 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3426 -* Fix cursor not following to new node when using a react node view by @ruipserra in https://github.com/ueberdosis/tiptap/pull/3331 -* fix(core): implement deleteCurrentNode command & fix node joining on Delete key by @bdbch in https://github.com/ueberdosis/tiptap/pull/3192 -* fix(link): allow to unset target attribute by @dargmuesli in https://github.com/ueberdosis/tiptap/pull/3425 -* feat(commands): add joinUp and joinDown command & refactor join command code by @bdbch in https://github.com/ueberdosis/tiptap/pull/3455 -* docs: rotate demo rooms by @patrickbaber in https://github.com/ueberdosis/tiptap/pull/3475 -* Draft: Moves all prosemirror deps to peerDependencies & devDependencies by @janthurau in https://github.com/ueberdosis/tiptap/pull/3487 -* fix(extension-bubble-menu): don't debounce without valid selection by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3501 -* refactor(extension-youtube): rename utility function name by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3498 -* Check if url is valid before creating YouTube player by @umgustavo in https://github.com/ueberdosis/tiptap/pull/3484 -* Fix docs menus.md missing word by @kandros in https://github.com/ueberdosis/tiptap/pull/3457 -* build(deps): bump minimatch from 3.0.4 to 3.1.2 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/3489 -* Fix: custom text serializers should override text serializers defined in the schema by @tovaschreier in https://github.com/ueberdosis/tiptap/pull/3546 -* Update sink-list-item.md by @vuau in https://github.com/ueberdosis/tiptap/pull/3629 -* 🧹 Allow `editor.setEditable` to omit updates by @ZaymonFC in https://github.com/ueberdosis/tiptap/pull/3301 -* Change Build Process to Lerna + tsup & prepare for prosemirror-meta package by @bdbch in https://github.com/ueberdosis/tiptap/pull/3555 -* fix(typo): typescript.md by @N0N1m3 in https://github.com/ueberdosis/tiptap/pull/3657 -* Update schema.md by @matrei in https://github.com/ueberdosis/tiptap/pull/3645 -* New Feature: Prosemirror Meta Package by @bdbch in https://github.com/ueberdosis/tiptap/pull/3556 -* Added CSS Required for Setup by @james-william-r in https://github.com/ueberdosis/tiptap/pull/3711 -* Update installation guides by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3698 -* Make y-prosemirror a peer dependency (extension-collaboration) by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3697 -* Remove lodash types, replace pm deps (extension-bubble-menu) by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3696 -* Remove lodash dependencies in extension-floating-menu by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3695 -* build(deps): bump cypress-io/github-action from 4.2.0 to 5.0.8 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3707 -* build(deps): bump http-cache-semantics from 4.1.0 to 4.1.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3687 -* Move back from tsup/esbuild to rollup by @bdbch in https://github.com/ueberdosis/tiptap/pull/3720 -* fix: Draggable nodes should respect drag handles by @matthewmullin01 in https://github.com/ueberdosis/tiptap/pull/3677 -* build(deps): bump actions/cache from 3.0.11 to 3.2.5 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3741 -* build(deps): bump act10ns/slack from 1 to 2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3404 -* build(deps): bump json5 from 1.0.1 to 1.0.2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3605 -* build(deps): bump json5 from 2.2.1 to 2.2.3 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/3607 -* build(deps): bump actions/checkout from 3.0.2 to 3.3.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3609 -* build(deps): bump actions/upload-artifact from 3.1.0 to 3.1.2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3610 -* build(deps): bump actions/setup-node from 3.5.1 to 3.6.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3613 -* Update regex to exclude channel URL unfurling by @JustMaier in https://github.com/ueberdosis/tiptap/pull/3750 -* Fix type for BubbleMenu prop pluginKey by @rumbcam in https://github.com/ueberdosis/tiptap/pull/3678 -* Extend `nodePasteRule` `find` type to most generic `PasteRuleFinder` by @jiegillet in https://github.com/ueberdosis/tiptap/pull/3759 -* fix(extension-link): Click handler opens selected link instead of clicked link by @jmtaber129 in https://github.com/ueberdosis/tiptap/pull/3732 -* fix(typography): dont create fractions in the middle of a string by @bdbch in https://github.com/ueberdosis/tiptap/pull/3762 -* Use Tailwind CDN direclty? by @RicoTrevisan in https://github.com/ueberdosis/tiptap/pull/3643 -* fix: override schema text serializers if provided in getText options by @harrisonlo in https://github.com/ueberdosis/tiptap/pull/3672 -* chore: add eslintcache by @Simon-He95 in https://github.com/ueberdosis/tiptap/pull/3525 -* document removing or overriding link attributes by @epelc in https://github.com/ueberdosis/tiptap/pull/3576 -* Add onFirstRender callback option by @Flamenco in https://github.com/ueberdosis/tiptap/pull/3600 -* Add Plugin Key to placeholder component. by @tazirahmb in https://github.com/ueberdosis/tiptap/pull/3652 -* Export `createNodeFromContent` and other missing helpers by @jacksleight in https://github.com/ueberdosis/tiptap/pull/3558 -* fix: Queue flushSync call by @kylealwyn in https://github.com/ueberdosis/tiptap/pull/3533 -* build(deps): bump cypress-io/github-action from 5.0.8 to 5.0.9 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3766 -* feat: #3540 Ability to preserve marks on lists by @gethari in https://github.com/ueberdosis/tiptap/pull/3541 -* Move y-prosemirror to peer-deps by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3763 -* fix: #3773 - Array for content breaks editor by @gethari in https://github.com/ueberdosis/tiptap/pull/3786 -* Docs Update for Installation instructions for PHP Livewire by @peterfox in https://github.com/ueberdosis/tiptap/pull/3618 -* add optionalSlashSlash to protocol options by @taras-turchenko-moc in https://github.com/ueberdosis/tiptap/pull/3675 -* fix(core): allow insertContentAt and insertContent text node arrays by @bdbch in https://github.com/ueberdosis/tiptap/pull/3790 -* chore: allow new ReactComponentContent components to be created by @bdbch in https://github.com/ueberdosis/tiptap/pull/3782 -* fix(react): reset initialized when editorcontent is unmounting by @bdbch in https://github.com/ueberdosis/tiptap/pull/3781 -* docs: add extension cli note to contributing docs by @bdbch in https://github.com/ueberdosis/tiptap/pull/3793 -* fix: update typings for node view decorations by @bdbch in https://github.com/ueberdosis/tiptap/pull/3783 -* build(deps): bump actions/cache from 3.2.5 to 3.2.6 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3795 -* Fix destroyed view causing errors on dispatchTransaction by @bdbch in https://github.com/ueberdosis/tiptap/pull/3799 -* Only allow left mouse button to open links by @thecodrr in https://github.com/ueberdosis/tiptap/pull/3777 -* Optimize empty document detection in `documentClear` plugin by @thecodrr in https://github.com/ueberdosis/tiptap/pull/3778 -* fix: use prose-base class for sm screens by @cstrnt in https://github.com/ueberdosis/tiptap/pull/3810 -* Adds attributes to toggleList by @katerlouis in https://github.com/ueberdosis/tiptap/pull/3776 -* fix(tests): add assertion for each valid/invalid link by @bdbch in https://github.com/ueberdosis/tiptap/pull/3815 -* feat(react): allow html attrs in react renderer by @bdbch in https://github.com/ueberdosis/tiptap/pull/3812 -* fix(react): allow updating event handlers on editor by @bdbch in https://github.com/ueberdosis/tiptap/pull/3811 -* Improve Cypress Test runner performance with parallelization by @bdbch in https://github.com/ueberdosis/tiptap/pull/3817 -* build(deps): bump cypress-io/github-action from 5.0.9 to 5.2.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3835 -* fix: Ordered list start support broke in #3541 by @gethari in https://github.com/ueberdosis/tiptap/pull/3833 -* Refactor typings (extension-youtube) by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3842 -* build(deps): bump actions/checkout from 3.3.0 to 3.4.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3864 -* build(deps): bump cypress-io/github-action from 5.2.0 to 5.5.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3863 -* build(deps-dev): bump webpack from 5.73.0 to 5.76.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3855 -* Docs: consistent naming of Tiptap by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3882 -* [PROPOSAL] dynamic default attributes by @mylesj in https://github.com/ueberdosis/tiptap/pull/3379 -* style(core): fix linting issues by @bdbch in https://github.com/ueberdosis/tiptap/pull/3884 -* Handle NodeViews in BubbleMenu positioning by @bdbch in https://github.com/ueberdosis/tiptap/pull/3881 -* chore: add Dev demo folder by @bdbch in https://github.com/ueberdosis/tiptap/pull/3887 -* CI: Remove slack notifications by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3885 -* Docs: Update nodes and extensions lists by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3886 -* Docs: Remove pro extension callout from collab docs by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3883 -* Fixing reoccurring issue #3331 and improving related PR #3533 by @KentoMoriwaki in https://github.com/ueberdosis/tiptap/pull/3862 -* Release Candidate Preparation by @bdbch in https://github.com/ueberdosis/tiptap/pull/3890 -* chore: add new release and prerelease actions by @bdbch in https://github.com/ueberdosis/tiptap/pull/3836 -* Updates @hocuspocus/provider, moves demo to TiptapCollab by @janthurau in https://github.com/ueberdosis/tiptap/pull/3895 -* Merge pull request #3895 from ueberdosis/feature/ttCollabProvider by @janthurau in https://github.com/ueberdosis/tiptap/pull/3897 -* Collaboration: Fix history after late-registering plugins by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3901 -* ci: remove slack notifications by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3898 -* build(deps): bump actions/checkout from 3.4.0 to 3.5.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3889 -* build(deps): bump cypress-io/github-action from 5.5.0 to 5.5.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3888 -* build(deps): bump actions/cache from 3.2.6 to 3.3.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3846 -* docs: prepare for stable release by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3892 -* New Issue & Discussion Templates by @bdbch in https://github.com/ueberdosis/tiptap/pull/3907 -* feat(core): add editor to this context in schema functions by @bdbch in https://github.com/ueberdosis/tiptap/pull/3909 + +- Fix sending of emptystring class for Prosemirror decoration by @ascott18 in https://github.com/ueberdosis/tiptap/pull/1004 +- build(deps): bump actions/cache from v2.1.4 to v2.1.5 by @dependabot in https://github.com/ueberdosis/tiptap/pull/1024 +- build(deps): bump actions/upload-artifact from v2.2.2 to v2.2.3 by @dependabot in https://github.com/ueberdosis/tiptap/pull/1025 +- Add install instructions by @MarcelloTheArcane in https://github.com/ueberdosis/tiptap/pull/1196 +- Fix a small typo by @swanson in https://github.com/ueberdosis/tiptap/pull/1211 +- Add missing word by @swanson in https://github.com/ueberdosis/tiptap/pull/1216 +- Clarify table header documentation by @swanson in https://github.com/ueberdosis/tiptap/pull/1215 +- Typo fix by @swanson in https://github.com/ueberdosis/tiptap/pull/1217 +- Make Horizontal Rule compatible with Typography extension by @chrisarmstrong in https://github.com/ueberdosis/tiptap/pull/1241 +- Fix returning true/false in can().chain().run() by @Markario in https://github.com/ueberdosis/tiptap/pull/1252 +- [Docs] Improve example integration with Laravel Livewire by @iksaku in https://github.com/ueberdosis/tiptap/pull/1255 +- feat: better types for Vue 2 by @zcuric in https://github.com/ueberdosis/tiptap/pull/1253 +- Fix typo by @DannyFeliz in https://github.com/ueberdosis/tiptap/pull/1262 +- HorizontalRule is included in defaultExtensions by @Duncank in https://github.com/ueberdosis/tiptap/pull/1267 +- VueRenderer's ref is undefined when in production mode by @thechrisoshow in https://github.com/ueberdosis/tiptap/pull/1271 +- feat: expose node helpers by @zcuric in https://github.com/ueberdosis/tiptap/pull/1278 +- New Feature: Generate JSON from HTML by @hanspagel in https://github.com/ueberdosis/tiptap/pull/1273 +- feat: export mark helpers by @zcuric in https://github.com/ueberdosis/tiptap/pull/1301 +- When text align is default, don't add a style attribute by @robguthrie in https://github.com/ueberdosis/tiptap/pull/1251 +- docs: complete list of extensions with changed name by @Deckluhm in https://github.com/ueberdosis/tiptap/pull/1305 +- fix(core): Increment `i` in `defaultBlockAt` by @andreavaccari in https://github.com/ueberdosis/tiptap/pull/1315 +- Fix text-align extension url by @ralbear in https://github.com/ueberdosis/tiptap/pull/1325 +- docs: fix typo by @Priestch in https://github.com/ueberdosis/tiptap/pull/1339 +- Allow passing of DependencyList to useEditor by @YousefED in https://github.com/ueberdosis/tiptap/pull/1376 +- a small clerical error? by @akirarika in https://github.com/ueberdosis/tiptap/pull/1380 +- Make HTML in docs valid by @MoPaMo in https://github.com/ueberdosis/tiptap/pull/1381 +- Wording improvement by @jonathanmach in https://github.com/ueberdosis/tiptap/pull/1389 +- Prevent tiptap from creating duplicate style tags when injecting css by @mmachatschek in https://github.com/ueberdosis/tiptap/pull/1399 +- Adding type definition for result and removing the ts-nocheck by @sereneinserenade in https://github.com/ueberdosis/tiptap/pull/1419 +- Fix name of FloatingMenu by @shadow-light in https://github.com/ueberdosis/tiptap/pull/1429 +- New extensions: add subscript and superscript extensions (including docs and tests) by @hanspagel in https://github.com/ueberdosis/tiptap/pull/1404 +- Exclude superscript from subscript, and vice versa. by @BrianHung in https://github.com/ueberdosis/tiptap/pull/1436 +- Add keyboard shortcuts to toggle superscript and subscript marks. by @BrianHung in https://github.com/ueberdosis/tiptap/pull/1437 +- Make drop cursor default to regular caret color by @shadow-light in https://github.com/ueberdosis/tiptap/pull/1444 +- use forwardRef for react wrappers by @YousefED in https://github.com/ueberdosis/tiptap/pull/1452 +- Mention: Add text attribute by @tomhrtly in https://github.com/ueberdosis/tiptap/pull/1322 +- Fix removal of textStyle mark when any style resets by @bttger in https://github.com/ueberdosis/tiptap/pull/1465 +- Fix parsing of mention nodes by @shadow-light in https://github.com/ueberdosis/tiptap/pull/1471 +- Correct default for dropcursor color in docs by @shadow-light in https://github.com/ueberdosis/tiptap/pull/1479 +- Improve gapcursor docs by @carlobeltrame in https://github.com/ueberdosis/tiptap/pull/1497 +- VueRenderer documentation with version 3 by @Tazi0 in https://github.com/ueberdosis/tiptap/pull/1491 +- Update introduction.md by @phillduffy in https://github.com/ueberdosis/tiptap/pull/1509 +- Link to contribution guidelines in CONTRIBUTING.md by @robertvanhoesel in https://github.com/ueberdosis/tiptap/pull/1541 +- build(deps): bump actions/setup-node from 2.1.5 to 2.2.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/1544 +- export createTable by @YousefED in https://github.com/ueberdosis/tiptap/pull/1469 +- doc update: onSelection → onSelectionUpdate by @forresto in https://github.com/ueberdosis/tiptap/pull/1555 +- update task-item.ts nodeview to update data-checked by @BrianHung in https://github.com/ueberdosis/tiptap/pull/1567 +- Fix typo by @JavierMartinz in https://github.com/ueberdosis/tiptap/pull/1587 +- Replace node-sass with dart sass and fix deprecation warning by @mmachatschek in https://github.com/ueberdosis/tiptap/pull/1590 +- Readd russian history shortcuts by @mmachatschek in https://github.com/ueberdosis/tiptap/pull/1589 +- Fix custom start for ordered lists by @mmachatschek in https://github.com/ueberdosis/tiptap/pull/1594 +- Doc fix: Remove braces from isEmpty & isEditable by @WilliamIPark in https://github.com/ueberdosis/tiptap/pull/1599 +- Export NodeViewRendererOptions by @sibiraj-s in https://github.com/ueberdosis/tiptap/pull/1607 +- Update hostic-dom to fix style attributes by @sibiraj-s in https://github.com/ueberdosis/tiptap/pull/1618 +- fix: export text align extension options by @iamursky in https://github.com/ueberdosis/tiptap/pull/1592 +- fix: export starter kit extension options by @iamursky in https://github.com/ueberdosis/tiptap/pull/1593 +- Adding types to Linter and making the structure a bit easier by @sereneinserenade in https://github.com/ueberdosis/tiptap/pull/1492 +- Additional input rules for typography by @arthurmcgregor in https://github.com/ueberdosis/tiptap/pull/1624 +- chore: add repository for all packages.json by @iamandrewluca in https://github.com/ueberdosis/tiptap/pull/1628 +- Fix typo by @ValentaTomas in https://github.com/ueberdosis/tiptap/pull/1634 +- Change TextAlignOptions to interface (not type) by @arthurmcgregor in https://github.com/ueberdosis/tiptap/pull/1623 +- Allow a rule to be skipped from the getAttributes callback by @joevallender in https://github.com/ueberdosis/tiptap/pull/1625 +- Fix multi character suggest by @flaviouk in https://github.com/ueberdosis/tiptap/pull/1620 +- Provide more context to update function to enable fewer re-renders by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1648 +- Examples: Syntax highlighting for React by @hanspagel in https://github.com/ueberdosis/tiptap/pull/1583 +- Apply the correct regex in markPasteRule by @joevallender in https://github.com/ueberdosis/tiptap/pull/1671 +- Fix typo by @Spone in https://github.com/ueberdosis/tiptap/pull/1693 +- build(deps): bump actions/setup-node from 2.2.0 to 2.4.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/1697 +- fix: use correct state when doc changed externally by @dkrym in https://github.com/ueberdosis/tiptap/pull/1646 +- ✨ Add CreateNodeFromContentOptions to insertContent by @castroCrea in https://github.com/ueberdosis/tiptap/pull/1678 +- Use correct reference for options.editorProps by @robertvanhoesel in https://github.com/ueberdosis/tiptap/pull/1540 +- ✨ Add typography trademark by @castroCrea in https://github.com/ueberdosis/tiptap/pull/1699 +- Menu improvements by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1714 +- Docs: Disable history demo buttons when commands are not available by @domnantas in https://github.com/ueberdosis/tiptap/pull/1721 +- fix some react focus issues by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1724 +- Update alpine docs by @sibiraj-s in https://github.com/ueberdosis/tiptap/pull/1733 +- Packages: Add a new `Color` extension to set the text color by @hanspagel in https://github.com/ueberdosis/tiptap/pull/1744 +- docs: add color picker to color extension demo by @domnantas in https://github.com/ueberdosis/tiptap/pull/1790 +- Fix Editor Reactivity by @nVitius in https://github.com/ueberdosis/tiptap/pull/1804 +- Add missing comma in example by @carlobeltrame in https://github.com/ueberdosis/tiptap/pull/1849 +- Allow triggering suggestions without prefix space by @jkosir in https://github.com/ueberdosis/tiptap/pull/1826 +- fix: change `this.value` to `value` in the vue examples with v-model by @MiloLug in https://github.com/ueberdosis/tiptap/pull/1813 +- Fix: Don’t initialize tippy on requestAnimationFrame to avoid race conditions by @enriquecastl in https://github.com/ueberdosis/tiptap/pull/1820 +- ✨ Follow Ref on ForwardRef component in reactRenderer by @castroCrea in https://github.com/ueberdosis/tiptap/pull/1690 +- feat: add extendEmptyMarkRange option to mark commands by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1859 +- Include children in placeholder plugin by @nickdbush in https://github.com/ueberdosis/tiptap/pull/1416 +- Horizontal rule demo: add selected style by @cadars in https://github.com/ueberdosis/tiptap/pull/1848 +- feat: add getText() and generateText() methods (fix #1428) by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1875 +- Fix usage example of CollaborationCursor by @carlobeltrame in https://github.com/ueberdosis/tiptap/pull/1911 +- Add type for async items on suggestions (fix TS strict types complain) by @d8vjork in https://github.com/ueberdosis/tiptap/pull/1912 +- Fix: code-block-lowlight child extensions do not highlight code by @enriquecastl in https://github.com/ueberdosis/tiptap/pull/1917 +- Use pasteRegex in addPasteRules by @jvissers in https://github.com/ueberdosis/tiptap/pull/1922 +- Docs: Clear up Prosemirror EditorProps usage by @domnantas in https://github.com/ueberdosis/tiptap/pull/1918 +- Add enableCoreExtensions flag by @flaviouk in https://github.com/ueberdosis/tiptap/pull/1923 +- Docs: Update command names in upgrade guide by @jakedolan in https://github.com/ueberdosis/tiptap/pull/1906 +- Fix: nodeInputRule() support for group match by @nokola in https://github.com/ueberdosis/tiptap/pull/1574 +- Fix "destory" method in view plugins. by @KaneCohen in https://github.com/ueberdosis/tiptap/pull/1882 +- Fix 'Edit on Github' link url for examples in docs by @mmachatschek in https://github.com/ueberdosis/tiptap/pull/1929 +- New example for custom documents (to force a heading on the top) by @hanspagel in https://github.com/ueberdosis/tiptap/pull/1948 +- Added better types for event emitter by @HuiiBuh in https://github.com/ueberdosis/tiptap/pull/1959 +- Use ref to move contentDOM by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1960 +- fix: compatibility with lowlight v2 by @fengzilong in https://github.com/ueberdosis/tiptap/pull/1939 +- build(deps): bump actions/setup-node from 2.4.0 to 2.4.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/1978 +- Fix typo in hard-break.md by @davidkrijgsman in https://github.com/ueberdosis/tiptap/pull/1988 +- Added Next.js installation guide & express setup for React by @alb in https://github.com/ueberdosis/tiptap/pull/1984 +- Fixed typo in React installation guide by @alb in https://github.com/ueberdosis/tiptap/pull/1989 +- docs: update styling by @hzpeng57 in https://github.com/ueberdosis/tiptap/pull/1998 +- React collaboration demo by @svenadlung in https://github.com/ueberdosis/tiptap/pull/1991 +- Integrate input rules and paste rules into the core by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/1997 +- Changing use of InputRule to textInputRule for Savvy example by @jakedolan in https://github.com/ueberdosis/tiptap/pull/2007 +- docs: correct the wording by @mittalyashu in https://github.com/ueberdosis/tiptap/pull/2012 +- Fix #2016 Image input rule by @nokola in https://github.com/ueberdosis/tiptap/pull/2020 +- Improve `ReactRenderer` types by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2011 +- Add `editor` dependency when registering `BubbleMenuPlugin` by @ValentaTomas in https://github.com/ueberdosis/tiptap/pull/2018 +- Allow to use commands within InputRule and PasteRule by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2035 +- build(deps): bump actions/checkout from 2.3.4 to 2.3.5 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2051 +- Add extension storage by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2069 +- Separate drags from drops in stopEvent by @thatsjonsense in https://github.com/ueberdosis/tiptap/pull/2070 +- Add editor to items prop in suggestion plugin by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2082 +- Check node type above custom update fn by @thatsjonsense in https://github.com/ueberdosis/tiptap/pull/2081 +- Add savvy example tests by @donovanglover in https://github.com/ueberdosis/tiptap/pull/2043 +- Add unit tests for demos/src/Examples/Minimal/Vue by @AlexandruValeanu in https://github.com/ueberdosis/tiptap/pull/2047 +- Added tests for Menus example by @alb in https://github.com/ueberdosis/tiptap/pull/2052 +- Docs: Fixing onUpdate example by @chris-sev in https://github.com/ueberdosis/tiptap/pull/2084 +- Fix menu example in doc by @phoenixgao in https://github.com/ueberdosis/tiptap/pull/2089 +- Replace `defaultOptions` with `addOptions` by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2088 +- docs: fix typo by @Deckluhm in https://github.com/ueberdosis/tiptap/pull/2093 +- Use the new storage feature for the `CollaborationCursor` extension by @hanspagel in https://github.com/ueberdosis/tiptap/pull/2096 +- Improve behavior when using insertContent by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2147 +- build(deps): bump actions/checkout from 2.3.5 to 2.4.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2145 +- Switch from hostic dom to zeed dom by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2151 +- fix typo in events.md by @millerrafi in https://github.com/ueberdosis/tiptap/pull/2152 +- update getJSON return type to JSONContent by @lecstor in https://github.com/ueberdosis/tiptap/pull/2153 +- Update image.md by @georgemandis in https://github.com/ueberdosis/tiptap/pull/2154 +- update zeed dom by @floriankrueger in https://github.com/ueberdosis/tiptap/pull/2155 +- Floating menu - remove composition check by @dkrym in https://github.com/ueberdosis/tiptap/pull/2137 +- Remove console.log statement from codeblock-lowlight-plugin file by @enriquecastl in https://github.com/ueberdosis/tiptap/pull/2168 +- Ignore iOS mutations when unfocused by @thatsjonsense in https://github.com/ueberdosis/tiptap/pull/2170 +- feat: Allow array of extensions for `enableInputRules` and `enablePasteRules` by @aguingand in https://github.com/ueberdosis/tiptap/pull/2119 +- Export type ColorOptions by @apaar97 in https://github.com/ueberdosis/tiptap/pull/2180 +- Split vue and react variant for interactivity demo by @svenadlung in https://github.com/ueberdosis/tiptap/pull/2186 +- Add `setEditable` to the Editor documentation by @floriankrueger in https://github.com/ueberdosis/tiptap/pull/2199 +- Bump actions/cache from 2.1.5 to 2.1.7 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2207 +- Bump actions/setup-node from 2.4.1 to 2.5.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2208 +- feat(ReactNodeViewRenderer): Add `as` option and pass through to ReactRenderer by @jessicalc in https://github.com/ueberdosis/tiptap/pull/2213 +- Add support for autolink by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2226 +- initialize autofocus selection in `createView` by @BrianHung in https://github.com/ueberdosis/tiptap/pull/2212 +- Use named exports instead of default exports by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2238 +- Svelte Example: remove wrong `type="context"` tag by @duruer in https://github.com/ueberdosis/tiptap/pull/2240 +- A brand new `CharacterCount` extension by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2256 +- join lists on toggleList by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2260 +- build(deps): bump actions/upload-artifact from 2.2.3 to 2.3.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2269 +- fix: show FloatingMenu by default only if focused by @jaulz in https://github.com/ueberdosis/tiptap/pull/2275 +- Improve backspace handling by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2284 +- Make sure editor is available on first render by @ryanto in https://github.com/ueberdosis/tiptap/pull/2282 +- fix typo in floating menu docs by @nucleartux in https://github.com/ueberdosis/tiptap/pull/2290 +- Add setup for plain js demos by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2288 +- build(deps): bump actions/upload-artifact from 2.3.0 to 2.3.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2300 +- Remove `element.current` from `useEffect` in `BubbleMenu` and `FloatingMenu` by @ValentaTomas in https://github.com/ueberdosis/tiptap/pull/2297 +- Using vue 2 and 3 when passing props to VueRenderer in Mention plugin by @domstrueboy in https://github.com/ueberdosis/tiptap/pull/2319 +- Fix typo in readme by @stijndcl in https://github.com/ueberdosis/tiptap/pull/2333 +- Fix typos in typescript.md by @hatefrad in https://github.com/ueberdosis/tiptap/pull/2339 +- typo in docs/api/editor.md by @milahu in https://github.com/ueberdosis/tiptap/pull/2338 +- Added setup script syntax to Vue 3 install docs by @NuroDev in https://github.com/ueberdosis/tiptap/pull/2324 +- build(deps): bump actions/setup-node from 2.5.0 to 2.5.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2343 +- change reactrenderer component type definition by @lukesmurray in https://github.com/ueberdosis/tiptap/pull/2327 +- Export type FontFamilyOptions by @apaar97 in https://github.com/ueberdosis/tiptap/pull/2345 +- Update vue3.md Grammar Error In Docs by @Aiyush-G in https://github.com/ueberdosis/tiptap/pull/2349 +- Fix typo in contributing.md by @webri in https://github.com/ueberdosis/tiptap/pull/2352 +- Vue3 CLI doesn't have "npm run dev" by @Aiyush-G in https://github.com/ueberdosis/tiptap/pull/2350 +- fix: export type `Level` for external use by @webri in https://github.com/ueberdosis/tiptap/pull/2354 +- add way to cancel inputrules and pasterules by @philippkuehn in https://github.com/ueberdosis/tiptap/pull/2368 +- Mark `@tiptap/react` and `@tiptap/core` as side effect free by @dcastil in https://github.com/ueberdosis/tiptap/pull/2361 +- Nuxt specific corrections by @gsqrt2 in https://github.com/ueberdosis/tiptap/pull/2410 +- build(deps): bump nanoid from 3.1.30 to 3.2.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2419 +- build(deps): bump node-fetch from 2.6.6 to 2.6.7 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2424 +- fix: use toggleHeader from prosemirror-tables by @jpobley in https://github.com/ueberdosis/tiptap/pull/2412 +- docs(nodes/image/react): remove v-if by @strdr4605 in https://github.com/ueberdosis/tiptap/pull/2461 +- Fix: Typo in Focus Command Documentation of Editor by @AngadSethi in https://github.com/ueberdosis/tiptap/pull/2476 +- expose hasAnchor to custom placeholder function by @YousefED in https://github.com/ueberdosis/tiptap/pull/2470 +- Add key bindings for uppercase letters for bold, italic and underline by @mejo- in https://github.com/ueberdosis/tiptap/pull/2478 +- Allow individual Typography rules to be disabled by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2449 +- Docs/toc undo fix by @codemzy in https://github.com/ueberdosis/tiptap/pull/2484 +- build(deps): bump nanoid from 3.1.30 to 3.2.0 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/2480 +- chore: added visual studio code debugging launch options by @bdbch in https://github.com/ueberdosis/tiptap/pull/2695 +- fix: don't override behaviour of Home / End in pc keymap by @scottsidwell in https://github.com/ueberdosis/tiptap/pull/2691 +- fix: Mark the bubble/floating menu extensions as side effect free by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2677 +- build(deps-dev): bump minimist from 1.2.5 to 1.2.6 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2667 +- build(deps): bump minimist from 1.2.5 to 1.2.6 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/2672 +- fix: prevent suggestions from being active when editor is readonly by @scottsidwell in https://github.com/ueberdosis/tiptap/pull/2692 +- fix: Allow tippyOptions.getReferenceClientRect in bubble menu to be overridden by @fleon in https://github.com/ueberdosis/tiptap/pull/2668 +- fix: allow [] as a prefix for task items by @bdbch in https://github.com/ueberdosis/tiptap/pull/2698 +- fix: improve Vue nodeViewProps typing by @DanSnow in https://github.com/ueberdosis/tiptap/pull/2681 +- fix: remove extension-text-style from character-cout peer dependencies by @pradel in https://github.com/ueberdosis/tiptap/pull/2696 +- fix(extension-link): prevent parsing `javascript:` pseudo-protocol by @phenax in https://github.com/ueberdosis/tiptap/pull/2646 +- build(deps): bump actions/cache from 2.1.7 to 3.0.2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2701 +- build(deps): bump actions/checkout from 2.4.0 to 3.0.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2699 +- build(deps): bump actions/upload-artifact from 2.3.1 to 3.0.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2700 +- build(deps): bump actions/setup-node from 2.5.1 to 3.1.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2705 +- Add support for React 18 by @dcastil in https://github.com/ueberdosis/tiptap/pull/2676 +- fix broken GuideContent demos not rendering because of unexpected use… by @bdbch in https://github.com/ueberdosis/tiptap/pull/2709 +- Docs: fix file names in PHP installation by @aguingand in https://github.com/ueberdosis/tiptap/pull/2644 +- Add support for CSS Modules by @XAHTEP26 in https://github.com/ueberdosis/tiptap/pull/2723 +- Use vitejs/plugin-react and include react dependencies by @svenadlung in https://github.com/ueberdosis/tiptap/pull/2732 +- build(deps-dev): bump minimist from 1.2.5 to 1.2.6 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2725 +- build(deps): bump actions/checkout from 3.0.0 to 3.0.2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2727 +- feat: Add `onBeforeStart` and `onBeforeUpdate` handlers to the render function by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2628 +- feat: Add a generic type for suggestion items by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2610 +- Reduce bundle size of @tiptap/extension-table package by @enriquecastl in https://github.com/ueberdosis/tiptap/pull/2622 +- Update Suggestion package.json by @dphuang2 in https://github.com/ueberdosis/tiptap/pull/2739 +- fix: Support inline nodes with content in @tiptap/suggestion by @thatsjonsense in https://github.com/ueberdosis/tiptap/pull/2648 +- Allow class attribute through setLink() by @Ken-vdE in https://github.com/ueberdosis/tiptap/pull/2758 +- update people by @patrickbaber in https://github.com/ueberdosis/tiptap/pull/2776 +- fix: properly calculate setDragImage position by @dilizarov in https://github.com/ueberdosis/tiptap/pull/2768 +- Ensure VueNodeViewRenderer will use Editor's Global Vue Instance by @ralphschindler in https://github.com/ueberdosis/tiptap/pull/2604 +- refactor(global): remove yarn in favor for npm by @bdbch in https://github.com/ueberdosis/tiptap/pull/2775 +- add support for CSP nonces in createStyleTag by @fekle in https://github.com/ueberdosis/tiptap/pull/2601 +- add validate option to link extension by @bdbch in https://github.com/ueberdosis/tiptap/pull/2781 +- Cypress tests for examples by @bdbch in https://github.com/ueberdosis/tiptap/pull/2777 +- build(deps): bump actions/setup-node from 3.1.1 to 3.2.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2793 +- fix: extendMarkRange doesn't work when cursor is at end of mark, despite isActive() returning true for that mark by @JDinABox in https://github.com/ueberdosis/tiptap/pull/2717 +- Expose "range" to textSerializer. Used in "getTextBetween" by @panta82 in https://github.com/ueberdosis/tiptap/pull/2684 +- Export `getTextSerializersFromSchema` helper, and fix typo in its name by @sjdemartini in https://github.com/ueberdosis/tiptap/pull/2750 +- fix: disable broken tests for experiements with further todo message by @bdbch in https://github.com/ueberdosis/tiptap/pull/2808 +- Add `className` option and pass through to ReactRenderer by @anton-liubushkin in https://github.com/ueberdosis/tiptap/pull/2794 +- Fix InputRule regex matcher ignoring non-text leaflets in textBefore by @bdbch in https://github.com/ueberdosis/tiptap/pull/2807 +- Add option to allow task items to be checkable (uncontrolled) by @kaspnilsson in https://github.com/ueberdosis/tiptap/pull/2474 +- feat: Required attributes by @thatsjonsense in https://github.com/ueberdosis/tiptap/pull/2640 +- Update team by @montapro in https://github.com/ueberdosis/tiptap/pull/2791 +- fix: Only trigger image input rule at the start or with a preceding space by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2830 +- In Vue 2 VueRenderer, only Vue.extend() non-VueConstructor arguments by @ralphschindler in https://github.com/ueberdosis/tiptap/pull/2824 +- fix(suggestion): :bug: make clientrect prop optional by @bdbch in https://github.com/ueberdosis/tiptap/pull/2813 +- build(deps): bump actions/cache from 3.0.2 to 3.0.3 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2851 +- Fixed(vue-2): `Avoid mutating a prop directly` error message to reproduce by @HondryTravis in https://github.com/ueberdosis/tiptap/pull/2834 +- Add support for custom protocols in extension-link by @shaunabanana in https://github.com/ueberdosis/tiptap/pull/2832 +- fix(textStyle): Null-safe parseHTML getting no color/fontFamily from HTMLElement styles by @d8vjork in https://github.com/ueberdosis/tiptap/pull/2825 +- build(deps): bump actions/upload-artifact from 3.0.0 to 3.1.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2820 +- Declare lowlight as a peerDependency in `@tiptap/extension-code-block-lowlight` by @enriquecastl in https://github.com/ueberdosis/tiptap/pull/2625 +- add precommit hook for linting and automatic eslint fixes + update eslint packages by @bdbch in https://github.com/ueberdosis/tiptap/pull/2862 +- Adding missing extensions to docs in https://tiptap.dev/api/extensions by @Lior539 in https://github.com/ueberdosis/tiptap/pull/2856 +- docs(docs): add missing documentation for commands by @bdbch in https://github.com/ueberdosis/tiptap/pull/2861 +- refactor: use index files for imports to simplify the export flow by @bdbch in https://github.com/ueberdosis/tiptap/pull/2870 +- feat(extension/youtube): :sparkles: new youtube embed extension by @bdbch in https://github.com/ueberdosis/tiptap/pull/2814 +- build(deps): bump actions/cache from 3.0.3 to 3.0.4 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2877 +- build(deps): bump actions/setup-node from 3.2.0 to 3.3.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2878 +- chore: migrate to new versions of prosemirror packages by @bdbch in https://github.com/ueberdosis/tiptap/pull/2854 +- docs: improve docs for youtube extension by @svenadlung in https://github.com/ueberdosis/tiptap/pull/2902 +- Allow setting `whiteSpace` style for `NodeViewWrapper` & `NodeViewContent` by @EvitanRelta in https://github.com/ueberdosis/tiptap/pull/2884 +- refactor(maintainment): set dependency versions for prosemirror and y… by @bdbch in https://github.com/ueberdosis/tiptap/pull/2904 +- feat: Allow multiple prefix characters to trigger a suggestion by @rfgamaral in https://github.com/ueberdosis/tiptap/pull/2896 +- fix: editor don't has contentComponent attribute when suggestion onUp… by @Young6118 in https://github.com/ueberdosis/tiptap/pull/2916 +- Fix state update after component unmounted by @SavKS in https://github.com/ueberdosis/tiptap/pull/2857 +- docs: fix livewire attribute by @ccchapman in https://github.com/ueberdosis/tiptap/pull/2928 +- build(deps): bump parse-url from 6.0.0 to 6.0.2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2961 +- fix(core): only respect text of node before current position (#2937) by @svenadlung in https://github.com/ueberdosis/tiptap/pull/2941 +- chore: lint only staged files by @ahhshm in https://github.com/ueberdosis/tiptap/pull/2957 +- fix(core): dont use selection for setContent replacement by @bdbch in https://github.com/ueberdosis/tiptap/pull/2934 +- refactor: remove duplicated function by @ahhshm in https://github.com/ueberdosis/tiptap/pull/2956 +- docs(figure): pass an object to `nodeInputRule` by @ahhshm in https://github.com/ueberdosis/tiptap/pull/2954 +- docs: update alpine installation by @patrickbaber in https://github.com/ueberdosis/tiptap/pull/3081 +- docs(extensions): mention community extensions and discussion thread by @sereneinserenade in https://github.com/ueberdosis/tiptap/pull/2991 +- build(deps-dev): bump svelte from 3.48.0 to 3.49.0 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/2992 +- build(deps-dev): bump svelte from 3.48.0 to 3.49.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2993 +- fix(core): isNodeSelection, isTextSelection not always false by @kivikakk in https://github.com/ueberdosis/tiptap/pull/3089 +- build(deps): bump actions/setup-node from 3.3.0 to 3.4.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/2998 +- build(deps): bump terser from 5.14.1 to 5.14.2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3009 +- build(deps): bump actions/cache from 3.0.4 to 3.0.7 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3087 +- Fix pasteRulesPlugin always adding one extra character to text range by @Billiam in https://github.com/ueberdosis/tiptap/pull/2968 +- fix: let StarterKit be imported as common js module via named import by @sipec in https://github.com/ueberdosis/tiptap/pull/2967 +- fix(core): createCan command props shouldn't try dispatch (#3025) by @kivikakk in https://github.com/ueberdosis/tiptap/pull/3026 +- build(deps): bump actions/cache from 3.0.7 to 3.0.8 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3112 +- fix(core): setNodeSelection should not clamp pos by Selection.atStart/atEnd by @kivikakk in https://github.com/ueberdosis/tiptap/pull/3091 +- Make Suggestion extension use view.dom instead of document by @Faleij in https://github.com/ueberdosis/tiptap/pull/3093 +- fix(core): make setEditable trigger onUpdate function by @bdbch in https://github.com/ueberdosis/tiptap/pull/2935 +- fix: fix React Node View render problem in React 18 by @Darmody in https://github.com/ueberdosis/tiptap/pull/2985 +- feature(core): add exit handling for marks by @bdbch in https://github.com/ueberdosis/tiptap/pull/2925 +- build(deps-dev): bump vite from 2.9.12 to 2.9.13 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/3141 +- build(deps-dev): bump vite from 2.9.12 to 2.9.13 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3145 +- fix: vue inject grammar warning by @zhxqc in https://github.com/ueberdosis/tiptap/pull/3144 +- fix(core): make setEditable trigger all 'update' listeners by @Rhys-T in https://github.com/ueberdosis/tiptap/pull/3140 +- fix: Typo by @NagariaHussain in https://github.com/ueberdosis/tiptap/pull/3132 +- docs: fix naming by @masl in https://github.com/ueberdosis/tiptap/pull/3151 +- Include bubble menu element when checking if the editor view still has focus by @StefKors in https://github.com/ueberdosis/tiptap/pull/3150 +- Fix typo in docs by @carlobeltrame in https://github.com/ueberdosis/tiptap/pull/3162 +- fix(extension-code-block-lowlight): Bump lowlight to 2.7.0, remove outdated @types by @tarngerine in https://github.com/ueberdosis/tiptap/pull/3002 +- fix(core): insert PasteRule Node at matched position (#2942) by @edlb in https://github.com/ueberdosis/tiptap/pull/2943 +- add-empty-editor-class-to-root-div by @BrianHung in https://github.com/ueberdosis/tiptap/pull/2665 +- build(deps): bump parse-path from 4.0.4 to 5.0.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3178 +- fix: move React `flushSync` to microtask by @sampi in https://github.com/ueberdosis/tiptap/pull/3188 +- Fix bubble menu and floating menu being available when editor is not editable by @bdbch in https://github.com/ueberdosis/tiptap/pull/3195 +- feat: Add alias condition to code-block-lowlight by @dngwoodo in https://github.com/ueberdosis/tiptap/pull/3155 +- feat(extension-typography): add servicemark input rule by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3220 +- fix(types): fix link and table type errors by @johnfraney in https://github.com/ueberdosis/tiptap/pull/3208 +- test: fix failing test by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3230 +- feat(extension-link): Change autolink to only apply after breaking a word by @C-Hess in https://github.com/ueberdosis/tiptap/pull/3232 +- chore(maintainment): :rocket: update prosemirror packages by @bdbch in https://github.com/ueberdosis/tiptap/pull/3237 +- fix(core): Can() does not work for setting marks by @C-Hess in https://github.com/ueberdosis/tiptap/pull/3223 +- Ensure text blocks exist before referencing them by @ScopeyNZ in https://github.com/ueberdosis/tiptap/pull/3251 +- fix(core): InputRules does not work for ranges containing multiple text nodes by @hamflx in https://github.com/ueberdosis/tiptap/pull/3205 +- fix(core) - support attributes being null/undefined by @albertogiunta in https://github.com/ueberdosis/tiptap/pull/3245 +- fix: set default allowedPrefixes null by @Matrixbirds in https://github.com/ueberdosis/tiptap/pull/3239 +- fix(extension/link): fix last word value being undefined by @bdbch in https://github.com/ueberdosis/tiptap/pull/3258 +- build(deps): bump d3-color from 3.0.1 to 3.1.0 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/3260 +- docs: link YouTube node docs to proper GitHub url by @nielslanting in https://github.com/ueberdosis/tiptap/pull/3283 +- fix: typo in docs by @danielyuenhx in https://github.com/ueberdosis/tiptap/pull/3265 +- Fixed dragged text not being deleted after drop on another editor by @LuchoCateura in https://github.com/ueberdosis/tiptap/pull/3279 +- Fixed using both color and highlight together by @nkonev in https://github.com/ueberdosis/tiptap/pull/3311 +- Cleanup linkifyjs when the editor is destroyed by @educastellano in https://github.com/ueberdosis/tiptap/pull/3316 +- Feature/youtube parameters by @LuchoCateura in https://github.com/ueberdosis/tiptap/pull/3307 +- Fix installation and examples link by @catalinmiron in https://github.com/ueberdosis/tiptap/pull/3298 +- fix(docs): typo by @Calvein in https://github.com/ueberdosis/tiptap/pull/3362 +- fix(extension/placeholder): Resolve placeholder performance issues by @C-Hess in https://github.com/ueberdosis/tiptap/pull/3361 +- build(deps): bump parse-url from 7.0.2 to 8.1.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3384 +- refactor(extension/bubble-menu): add debounce to bubble menu updates by @bdbch in https://github.com/ueberdosis/tiptap/pull/3385 +- build(deps): bump actions/setup-node from 3.4.1 to 3.5.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3318 +- docs: Fix typos in CHANGELOG.md by @rvrvrv in https://github.com/ueberdosis/tiptap/pull/3328 +- build(deps): bump actions/cache from 3.0.8 to 3.0.11 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3317 +- fix: remove blur event listener from tippy element (#3365) by @MihirGH in https://github.com/ueberdosis/tiptap/pull/3366 +- fixes typo in suggestion.ts by @alejandrogarciasalas in https://github.com/ueberdosis/tiptap/pull/3386 +- docs(svelte): fix link to get started with svelte by @taismassaro in https://github.com/ueberdosis/tiptap/pull/3396 +- build(deps): bump loader-utils from 2.0.2 to 2.0.3 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3395 +- Update jobs.md by @montapro in https://github.com/ueberdosis/tiptap/pull/3432 +- extension/table: Fix prosemirror-tables dependency not using a correct namespace by @bdbch in https://github.com/ueberdosis/tiptap/pull/3448 +- typo: custom-extensions.md completely by @williamsk91 in https://github.com/ueberdosis/tiptap/pull/3447 +- Fix #3435 - CommonJS and ESM loading confusion by @tomi-bigpi in https://github.com/ueberdosis/tiptap/pull/3436 +- build(deps): bump loader-utils from 2.0.3 to 2.0.4 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3426 +- Fix cursor not following to new node when using a react node view by @ruipserra in https://github.com/ueberdosis/tiptap/pull/3331 +- fix(core): implement deleteCurrentNode command & fix node joining on Delete key by @bdbch in https://github.com/ueberdosis/tiptap/pull/3192 +- fix(link): allow to unset target attribute by @dargmuesli in https://github.com/ueberdosis/tiptap/pull/3425 +- feat(commands): add joinUp and joinDown command & refactor join command code by @bdbch in https://github.com/ueberdosis/tiptap/pull/3455 +- docs: rotate demo rooms by @patrickbaber in https://github.com/ueberdosis/tiptap/pull/3475 +- Draft: Moves all prosemirror deps to peerDependencies & devDependencies by @janthurau in https://github.com/ueberdosis/tiptap/pull/3487 +- fix(extension-bubble-menu): don't debounce without valid selection by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3501 +- refactor(extension-youtube): rename utility function name by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3498 +- Check if url is valid before creating YouTube player by @umgustavo in https://github.com/ueberdosis/tiptap/pull/3484 +- Fix docs menus.md missing word by @kandros in https://github.com/ueberdosis/tiptap/pull/3457 +- build(deps): bump minimatch from 3.0.4 to 3.1.2 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/3489 +- Fix: custom text serializers should override text serializers defined in the schema by @tovaschreier in https://github.com/ueberdosis/tiptap/pull/3546 +- Update sink-list-item.md by @vuau in https://github.com/ueberdosis/tiptap/pull/3629 +- 🧹 Allow `editor.setEditable` to omit updates by @ZaymonFC in https://github.com/ueberdosis/tiptap/pull/3301 +- Change Build Process to Lerna + tsup & prepare for prosemirror-meta package by @bdbch in https://github.com/ueberdosis/tiptap/pull/3555 +- fix(typo): typescript.md by @N0N1m3 in https://github.com/ueberdosis/tiptap/pull/3657 +- Update schema.md by @matrei in https://github.com/ueberdosis/tiptap/pull/3645 +- New Feature: Prosemirror Meta Package by @bdbch in https://github.com/ueberdosis/tiptap/pull/3556 +- Added CSS Required for Setup by @james-william-r in https://github.com/ueberdosis/tiptap/pull/3711 +- Update installation guides by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3698 +- Make y-prosemirror a peer dependency (extension-collaboration) by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3697 +- Remove lodash types, replace pm deps (extension-bubble-menu) by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3696 +- Remove lodash dependencies in extension-floating-menu by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3695 +- build(deps): bump cypress-io/github-action from 4.2.0 to 5.0.8 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3707 +- build(deps): bump http-cache-semantics from 4.1.0 to 4.1.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3687 +- Move back from tsup/esbuild to rollup by @bdbch in https://github.com/ueberdosis/tiptap/pull/3720 +- fix: Draggable nodes should respect drag handles by @matthewmullin01 in https://github.com/ueberdosis/tiptap/pull/3677 +- build(deps): bump actions/cache from 3.0.11 to 3.2.5 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3741 +- build(deps): bump act10ns/slack from 1 to 2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3404 +- build(deps): bump json5 from 1.0.1 to 1.0.2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3605 +- build(deps): bump json5 from 2.2.1 to 2.2.3 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/3607 +- build(deps): bump actions/checkout from 3.0.2 to 3.3.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3609 +- build(deps): bump actions/upload-artifact from 3.1.0 to 3.1.2 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3610 +- build(deps): bump actions/setup-node from 3.5.1 to 3.6.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3613 +- Update regex to exclude channel URL unfurling by @JustMaier in https://github.com/ueberdosis/tiptap/pull/3750 +- Fix type for BubbleMenu prop pluginKey by @rumbcam in https://github.com/ueberdosis/tiptap/pull/3678 +- Extend `nodePasteRule` `find` type to most generic `PasteRuleFinder` by @jiegillet in https://github.com/ueberdosis/tiptap/pull/3759 +- fix(extension-link): Click handler opens selected link instead of clicked link by @jmtaber129 in https://github.com/ueberdosis/tiptap/pull/3732 +- fix(typography): dont create fractions in the middle of a string by @bdbch in https://github.com/ueberdosis/tiptap/pull/3762 +- Use Tailwind CDN direclty? by @RicoTrevisan in https://github.com/ueberdosis/tiptap/pull/3643 +- fix: override schema text serializers if provided in getText options by @harrisonlo in https://github.com/ueberdosis/tiptap/pull/3672 +- chore: add eslintcache by @Simon-He95 in https://github.com/ueberdosis/tiptap/pull/3525 +- document removing or overriding link attributes by @epelc in https://github.com/ueberdosis/tiptap/pull/3576 +- Add onFirstRender callback option by @Flamenco in https://github.com/ueberdosis/tiptap/pull/3600 +- Add Plugin Key to placeholder component. by @tazirahmb in https://github.com/ueberdosis/tiptap/pull/3652 +- Export `createNodeFromContent` and other missing helpers by @jacksleight in https://github.com/ueberdosis/tiptap/pull/3558 +- fix: Queue flushSync call by @kylealwyn in https://github.com/ueberdosis/tiptap/pull/3533 +- build(deps): bump cypress-io/github-action from 5.0.8 to 5.0.9 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3766 +- feat: #3540 Ability to preserve marks on lists by @gethari in https://github.com/ueberdosis/tiptap/pull/3541 +- Move y-prosemirror to peer-deps by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3763 +- fix: #3773 - Array for content breaks editor by @gethari in https://github.com/ueberdosis/tiptap/pull/3786 +- Docs Update for Installation instructions for PHP Livewire by @peterfox in https://github.com/ueberdosis/tiptap/pull/3618 +- add optionalSlashSlash to protocol options by @taras-turchenko-moc in https://github.com/ueberdosis/tiptap/pull/3675 +- fix(core): allow insertContentAt and insertContent text node arrays by @bdbch in https://github.com/ueberdosis/tiptap/pull/3790 +- chore: allow new ReactComponentContent components to be created by @bdbch in https://github.com/ueberdosis/tiptap/pull/3782 +- fix(react): reset initialized when editorcontent is unmounting by @bdbch in https://github.com/ueberdosis/tiptap/pull/3781 +- docs: add extension cli note to contributing docs by @bdbch in https://github.com/ueberdosis/tiptap/pull/3793 +- fix: update typings for node view decorations by @bdbch in https://github.com/ueberdosis/tiptap/pull/3783 +- build(deps): bump actions/cache from 3.2.5 to 3.2.6 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3795 +- Fix destroyed view causing errors on dispatchTransaction by @bdbch in https://github.com/ueberdosis/tiptap/pull/3799 +- Only allow left mouse button to open links by @thecodrr in https://github.com/ueberdosis/tiptap/pull/3777 +- Optimize empty document detection in `documentClear` plugin by @thecodrr in https://github.com/ueberdosis/tiptap/pull/3778 +- fix: use prose-base class for sm screens by @cstrnt in https://github.com/ueberdosis/tiptap/pull/3810 +- Adds attributes to toggleList by @katerlouis in https://github.com/ueberdosis/tiptap/pull/3776 +- fix(tests): add assertion for each valid/invalid link by @bdbch in https://github.com/ueberdosis/tiptap/pull/3815 +- feat(react): allow html attrs in react renderer by @bdbch in https://github.com/ueberdosis/tiptap/pull/3812 +- fix(react): allow updating event handlers on editor by @bdbch in https://github.com/ueberdosis/tiptap/pull/3811 +- Improve Cypress Test runner performance with parallelization by @bdbch in https://github.com/ueberdosis/tiptap/pull/3817 +- build(deps): bump cypress-io/github-action from 5.0.9 to 5.2.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3835 +- fix: Ordered list start support broke in #3541 by @gethari in https://github.com/ueberdosis/tiptap/pull/3833 +- Refactor typings (extension-youtube) by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3842 +- build(deps): bump actions/checkout from 3.3.0 to 3.4.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3864 +- build(deps): bump cypress-io/github-action from 5.2.0 to 5.5.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3863 +- build(deps-dev): bump webpack from 5.73.0 to 5.76.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3855 +- Docs: consistent naming of Tiptap by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3882 +- [PROPOSAL] dynamic default attributes by @mylesj in https://github.com/ueberdosis/tiptap/pull/3379 +- style(core): fix linting issues by @bdbch in https://github.com/ueberdosis/tiptap/pull/3884 +- Handle NodeViews in BubbleMenu positioning by @bdbch in https://github.com/ueberdosis/tiptap/pull/3881 +- chore: add Dev demo folder by @bdbch in https://github.com/ueberdosis/tiptap/pull/3887 +- CI: Remove slack notifications by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3885 +- Docs: Update nodes and extensions lists by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3886 +- Docs: Remove pro extension callout from collab docs by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3883 +- Fixing reoccurring issue #3331 and improving related PR #3533 by @KentoMoriwaki in https://github.com/ueberdosis/tiptap/pull/3862 +- Release Candidate Preparation by @bdbch in https://github.com/ueberdosis/tiptap/pull/3890 +- chore: add new release and prerelease actions by @bdbch in https://github.com/ueberdosis/tiptap/pull/3836 +- Updates @hocuspocus/provider, moves demo to TiptapCollab by @janthurau in https://github.com/ueberdosis/tiptap/pull/3895 +- Merge pull request #3895 from ueberdosis/feature/ttCollabProvider by @janthurau in https://github.com/ueberdosis/tiptap/pull/3897 +- Collaboration: Fix history after late-registering plugins by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3901 +- ci: remove slack notifications by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3898 +- build(deps): bump actions/checkout from 3.4.0 to 3.5.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3889 +- build(deps): bump cypress-io/github-action from 5.5.0 to 5.5.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3888 +- build(deps): bump actions/cache from 3.2.6 to 3.3.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3846 +- docs: prepare for stable release by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3892 +- New Issue & Discussion Templates by @bdbch in https://github.com/ueberdosis/tiptap/pull/3907 +- feat(core): add editor to this context in schema functions by @bdbch in https://github.com/ueberdosis/tiptap/pull/3909 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e59b86f408..a87a14cada 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,6 +16,10 @@ world that developers are civilized and selfless people. It's the duty of the maintainer to ensure that all submissions to the project are of sufficient quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used. +## Security + +If you discover a security vulnerability, please refer to our [Security Policy](SECURITY.md) for reporting instructions. + ## Viability When requesting or submitting new features, first consider whether it might be useful to others. Open @@ -26,7 +30,11 @@ whether or not your feature is likely to be used by other users of the project. Before filing an issue: -- Attempt to replicate the problem, to ensure that it wasn't a coincidental incident. +- Attempt to replicate the problem, to ensure that it wasn't a coincidental incident. Create a CodeSandbox to reproduce the issue. Use one of these templates to get started: + - [JavaScript template](https://codesandbox.io/s/tiptap-js-fv1lyo) + - [React template](https://codesandbox.io/s/tiptap-react-qidlsv) + - [Vue 2 template](https://codesandbox.io/s/tiptap-vue-2-25nq3g) + - [Vue 3 template](https://codesandbox.io/p/sandbox/tiptap-vue-3-ci7q9h) - Check to make sure your feature suggestion isn't already present within the project. - Check the pull requests tab to ensure that the bug doesn't have a fix in progress. - Check the pull requests tab to ensure that the feature isn't already in progress. @@ -41,6 +49,41 @@ Before committing: - Make sure to run the tests and linter before committing your changes. - If you are making changes to one of the packages, make sure to **always** include a [changeset](https://github.com/changesets/changesets) in your PR describing **what changed** with a **description** of the change. Those are responsible for changelog creation +## Create a new demo + +To make it easier to add new demos to the demos app we provide a small helper script via `pnpm run make:demo` that scaffolds a new demo directory from our default template. + +**What it does** + +- Prompts for a demo name and category. +- Validates the category is one of: `Dev`, `Examples`, `Extensions`, `Experiments`, `Marks`, `Nodes`. +- Copies the template `demos/src/Examples/Default` to `demos/src//`. + +**How to use** + +- From the repository root run: +- If the script is executable: +- Or with bash directly: +- Follow the interactive prompts for the demo name and category. + +**Notes and follow-up steps** + +- The script only copies the template. After the scaffold is created, update the demo's files (title, description, imports) to reflect your example. +- Make sure to review the generated demo in `demos/` and run the demos app (`pnpm dev`) to verify it appears and works as expected. +- If your demo changes package behaviour or exposes user-facing changes, follow the normal rule and add a changeset and tests as needed. +- If you don't want your demo to be included in the Git repository, use the `Dev` category. Demos in this category are ignored by git via `.gitignore`. + +## Publishing New Packages + +When adding a new package to the repository that does not yet exist on NPM, additional setup is required before the automated publish CI can release it: + +1. **Manual initial publish** - The package must be published manually to NPM for the first time using normal user authentication. This is required because trusted publishing can only be configured for packages that already exist on the registry. + - For a single package, run `pnpm run build && pnpm publish` from the package directory (e.g., `packages/extension-audio/`). + - Alternatively, run `pnpm run publish` from the root directory to publish all packages. +2. **Configure trusted publishing** - After the initial publish, set up [NPM trusted publishing](https://docs.npmjs.com/trusted-publishers) (also known as provenance) for the package on NPM. This allows the GitHub Actions workflow to publish subsequent versions automatically. + +Without this setup, the publish CI will fail when attempting to release a new package. + ## Requirements If the project maintainer has any additional requirements, you will find them listed here. diff --git a/README.md b/README.md index 739fe587f7..6535ab3f38 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ -# Tiptap Editor -The Tiptap Editor is a headless, framework-agnostic rich text editor that's customizable and extendable through extensions. Its headless nature means it comes without a set user interface, offering full design freedom (for a jumpstart, see linked [UI templates](#examples-codesandbox-and-ui-templates) below). Tiptap is based on the highly reliable [ProseMirror](https://github.com/ProseMirror/prosemirror) library. - -Tiptap Editor is complemented by the collaboration open-source backend [Hocuspocus](https://github.com/ueberdosis/hocuspocus). Both the Editor and Hocuspocus form the foundation of the [Tiptap Suite](https://tiptap.dev/). +![Tiptap Editor](.github/assets/cover.png) +[![LFX Health Score](https://insights.production.lfx.dev/api/badge/health-score?project=tiptap)](https://insights.linuxfoundation.org/project/tiptap) [![Build Status](https://github.com/ueberdosis/tiptap/actions/workflows/build.yml/badge.svg)](https://github.com/ueberdosis/tiptap/actions/workflows/build.yml) [![Version](https://img.shields.io/npm/v/@tiptap/core.svg?label=version)](https://www.npmjs.com/package/@tiptap/core) [![Downloads](https://img.shields.io/npm/dm/@tiptap/core.svg)](https://npmcharts.com/compare/@tiptap/core?minimal=true) @@ -10,44 +8,58 @@ Tiptap Editor is complemented by the collaboration open-source backend [Hocuspoc [![Chat](https://img.shields.io/badge/chat-on%20discord-7289da.svg?sanitize=true)](https://discord.gg/WtJ49jGshW) [![Sponsor](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub)](https://github.com/sponsors/ueberdosis) +# Tiptap Editor + +The Tiptap Editor is a headless, framework-agnostic rich text editor that's customizable and extendable through extensions. Its headless nature means it comes without a set user interface, offering full design freedom (for a jumpstart, see linked [UI templates](#examples-codesandbox-and-ui-templates) below). Tiptap is based on the highly reliable [ProseMirror](https://github.com/ProseMirror/prosemirror) library. + +Tiptap Editor is complemented by the collaboration open-source backend [Hocuspocus](https://github.com/ueberdosis/hocuspocus). Both the Editor and Hocuspocus form the foundation of the [Tiptap Suite](https://tiptap.dev/). + ### How does the Tiptap Editor work? - **Headless Framework:** Tiptap does not rely on a user interface. So there is no need for class overrides or code hacks. If you do need an example UI feel free to browse our [UI templates](#examples-codesandbox-and-ui-templates) linked below. -- **Framework-agnostic:** The Tiptap Editor is designed to work across different frontend frameworks. This means whether you're using Vue, React, or plain JavaScript, Tiptap integrates without compatibility issues. +- **Framework-agnostic:** The Tiptap Editor is designed to work across different frontend frameworks. This means whether you're using Vue, React, or plain JavaScript, Tiptap integrates without compatibility issues. - **Extension based:** Extensions in Tiptap allow for a tailored editing experience, from simple text styling to advanced features like drag-and-drop block editing. You have the option to choose from over 100 extensions available in the [documentation](https://tiptap.dev/docs/editor/extensions) and [community](https://github.com/ueberdosis/awesome-tiptap/#community-extensions) to enhance your editor's functionality. - **Customize your UX:** The editor was built to give you control to define your own [extensions](https://tiptap.dev/docs/editor/guide/custom-extensions) and [nodes](https://tiptap.dev/docs/editor/api/nodes). - ### Editor Pro Extensions + The **Pro Extensions** are a set of advanced functionalities that enhance the capabilities of the Tiptap Editor. They are additional features that can be integrated into the base editor to provide more sophisticated editing options. -Key functionalities include collaborative editing, which allows multiple users to edit documents simultaneously, drag-and-drop file management for easier handling of documents and media, and unique node ID assignment. Review the docs right [here](https://tiptap.dev/docs/editor/extensions). +Key functionalities include collaborative editing, commenting, versioning, document conversion and AI related features. +Review the docs right [here](https://tiptap.dev/docs/editor/extensions). -Pro Extensions are free with a [Tiptap account](https://cloud.tiptap.dev/pro-extensions). Once signed up, review the guide in your account. +Pro Extensions need a valid subscription. ### Make your editor collaborative + Interested in collaborative editing? Check out our open-source package [Hocuspocus](https://github.com/ueberdosis/hocuspocus) - a collaboration backend built around the CRDT power of [Yjs](https://github.com/yjs/yjs). Hocuspocus serves as the backbone for the [Tiptap Suite](https://tiptap.dev/). ## Documentation + For more detailed information, make sure to check out our [documentation](https://tiptap.dev/docs/editor/installation). If you encounter any problems or have suggestions for our system, please open an issue. ### Examples, CodeSandbox and UI Templates + Have a look at the [examples to see Tiptap in action](https://tiptap.dev/examples) or review and fork our codesandboxes. + - [Basic example of the Tiptap editor.](https://codesandbox.io/p/devbox/editor-9x9dkd?embed=1&file=%2Fsrc%2FApp.js) - [Collaboration ready Tiptap CodeSandbox](https://codesandbox.io/p/devbox/collaboration-4stk94) - React notion-like block editor template: [Demo](https://templates.tiptap.dev/) ## About Tiptap + Tiptap is a collection of developer components based on open-source technology, forming the basis of our advanced, paid features. It includes the open-source editor component, collaboration features, Content AI, and Tiptap Cloud. We are developing open-source products that also shape our paid features. We're committed to improving both, ensuring quality and reliability in every update. For more details, visit the Tiptap [documentation](https://tiptap.dev/docs/editor/introduction) or [website](https://tiptap.dev/). ### Community + For help, discussion about best practices, or any other conversation that would benefit from being searchable: [Discuss Tiptap on GitHub](https://github.com/ueberdosis/tiptap/discussions) ### Sponsors 💖 +
@@ -95,16 +107,14 @@ For help, discussion about best practices, or any other conversation that would
- - -
- [iFixit](https://www.ifixit.com/), [ApostropheCMS](https://apostrophecms.com/), [Novadiscovery](http://www.novadiscovery.com/), [Omics Data Automation](https://www.omicsautomation.com), [Flow Mobile](https://www.flowmobile.app/), [DocIQ](https://www.dociq.io/) and [hundreds of awesome individuals](https://github.com/sponsors/ueberdosis). ### Contributing + Feel like adding some magic of your own to Tiptap Editor Core? We welcome contributions! Please see our [CONTRIBUTING](CONTRIBUTING.md) guidelines for how to get started. ### Contributors + [Sam Willis](https://github.com/samwillis), [Brian Hung](https://github.com/BrianHung), [Dirk Holtwick](https://github.com/holtwick), @@ -118,4 +128,5 @@ Feel like adding some magic of your own to Tiptap Editor Core? We welcome contri [Gregor](https://github.com/gambolputty) and [many more](../../contributors). ## License + The MIT License (MIT). Please see [License File](LICENSE.md) for more information. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..b5ee8360b0 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,32 @@ +# Security Policy + +## Reporting Vulnerabilities + +If you discover a security vulnerability in Tiptap, please report it responsibly. We appreciate your help in keeping our users safe. + +### How to Report + +**Please do not report security vulnerabilities through public GitHub issues.** + +Send details to security@tiptap.dev. Include a description of the vulnerability, steps to reproduce, and any potential impact. + +We will acknowledge receipt within 48 hours and provide updates as we investigate. + +## Response Process + +Vulnerabilities are assessed and prioritized based on severity, exploitability, and business impact. Fixes are deployed according to the following timelines: + +- **Critical** (e.g., remote code execution, data breaches): Fixed and released within 24 hours. +- **High** (e.g., significant data exposure): Fixed and released within 72 hours. +- **Medium** (e.g., moderate leaks): Fixed and released within 14 days. +- **Low** (e.g., minor issues): Addressed in the next scheduled update. + +We follow responsible disclosure practices and will credit reporters unless requested otherwise. + +## Scope + +This policy applies to all Tiptap packages and related infrastructure. Reports are handled through our established vulnerability management process. + +## Contact + +For questions, email security@tiptap.dev or humans@tiptap.dev. diff --git a/babel.config.js b/babel.config.js index b519a4df87..0e1ce15a8f 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,10 +1,4 @@ module.exports = { - presets: [ - '@babel/preset-env', - '@babel/preset-react', - ], - plugins: [ - '@babel/plugin-proposal-nullish-coalescing-operator', - '@babel/plugin-proposal-optional-chaining', - ], + presets: ['@babel/preset-env', '@babel/preset-react'], + plugins: ['@babel/plugin-proposal-nullish-coalescing-operator', '@babel/plugin-proposal-optional-chaining'], } diff --git a/demos/CHANGELOG.md b/demos/CHANGELOG.md index 228075235b..ddafca802c 100644 --- a/demos/CHANGELOG.md +++ b/demos/CHANGELOG.md @@ -1,5 +1,40 @@ # Change Log +## 3.0.1 + +### Major Changes + +- a92f4a6: We are now building packages with tsup which does not support UMD builds, please repackage if you require UMD builds + +### Patch Changes + +- 89bd9c7: Enforce type imports so that the bundler ignores TypeScript type imports when generating the index.js file of the dist directory +- 8c69002: Synced beta with stable features + +## 3.0.0-beta.1 + +### Patch Changes + +- 8c69002: Synced beta with stable features + +## 3.0.0-next.2 + +### Patch Changes + +- 89bd9c7: Enforce type imports so that the bundler ignores TypeScript type imports when generating the index.js file of the dist directory + +## 3.0.0-next.1 + +### Major Changes + +- a92f4a6: We are now building packages with tsup which does not support UMD builds, please repackage if you require UMD builds + +## 3.0.0-next.0 + +### Major Changes + +- a92f4a6: We are now building packages with tsup which does not support UMD builds, please repackage if you require UMD builds + ## 2.5.2 ### Patch Changes diff --git a/demos/includeDependencies.txt b/demos/dedupeDeps.txt similarity index 75% rename from demos/includeDependencies.txt rename to demos/dedupeDeps.txt index 333720c698..e5c2daa5aa 100644 --- a/demos/includeDependencies.txt +++ b/demos/dedupeDeps.txt @@ -6,27 +6,34 @@ highlight.js/lib/languages/xml highlight.js/lib/core linkifyjs lowlight +react +react-dom +react-dom/client +use-sync-external-store/shim +use-sync-external-store/shim/with-selector +shiki +@floating-ui/dom +uuid +y-webrtc +yjs +prosemirror-changeset +prosemirror-collab prosemirror-commands prosemirror-dropcursor prosemirror-gapcursor prosemirror-history +prosemirror-inputrules prosemirror-keymap +prosemirror-markdown +prosemirror-menu prosemirror-model +prosemirror-schema-basic prosemirror-schema-list prosemirror-state prosemirror-tables +prosemirror-trailing-node prosemirror-transform prosemirror-view -react -react-dom -react-dom/client -use-sync-external-store/shim -use-sync-external-store/shim/with-selector -shiki -simplify-js -tippy.js -uuid -y-webrtc -yjs @hocuspocus/provider @lifeomic/attempt +@tiptap/y-tiptap diff --git a/demos/index.html b/demos/index.html index 95c50836bc..297cea7f19 100644 --- a/demos/index.html +++ b/demos/index.html @@ -1,10 +1,9 @@ - + - - + + - - + diff --git a/demos/package.json b/demos/package.json index 1f909464fd..60d2d264d4 100644 --- a/demos/package.json +++ b/demos/package.json @@ -1,51 +1,72 @@ { "name": "tiptap-demos", - "version": "2.5.2", + "version": "3.0.1", "private": true, "type": "module", "scripts": { "start": "vite --host", - "build:demos": "npm run ts && vite build", - "preview": "vite preview", - "ts": "tsc --project tsconfig.base.json --noEmit && tsc --project tsconfig.react.json --noEmit && tsc --project tsconfig.vue-2.json --noEmit && tsc --project tsconfig.vue-3.json --noEmit" + "build:demos": "vite build", + "preview": "vite preview" }, "dependencies": { - "@hocuspocus/provider": "2.13.5", - "@lexical/react": "^0.11.3", + "@floating-ui/dom": "^1.6.13", + "@hocuspocus/provider": "^2.15.0", + "@hocuspocus/transformer": "^2.15.0", + "@lexical/react": "^0.36.2", + "@lifeomic/attempt": "3.1.0", "@shikijs/core": "1.10.3", + "@tiptap/y-tiptap": "^3.0.0", "d3": "^7.9.0", "fast-glob": "^3.3.2", - "highlight.js": "^11.10.0", - "lexical": "^0.11.3", - "lowlight": "^3.1.0", + "highlight.js": "^11.11.1", + "katex": "^0.16.4", + "lexical": "^0.36.2", + "linkifyjs": "^4.3.2", + "lowlight": "^3.3.0", + "prosemirror-changeset": "^2.3.0", + "prosemirror-collab": "^1.3.1", + "prosemirror-commands": "^1.6.2", + "prosemirror-dropcursor": "^1.8.1", + "prosemirror-gapcursor": "^1.3.2", + "prosemirror-history": "^1.4.1", + "prosemirror-inputrules": "^1.4.0", + "prosemirror-keymap": "^1.2.2", + "prosemirror-markdown": "^1.13.1", + "prosemirror-menu": "^1.2.4", + "prosemirror-model": "^1.24.1", + "prosemirror-schema-basic": "^1.2.3", + "prosemirror-schema-list": "^1.5.0", + "prosemirror-state": "^1.4.3", + "prosemirror-tables": "^1.6.2", + "prosemirror-trailing-node": "^3.0.0", + "prosemirror-transform": "^1.10.2", + "prosemirror-view": "^1.38.1", "remixicon": "^2.5.0", - "shiki": "^1.23.1", - "simplify-js": "^1.2.4", - "y-prosemirror": "1.2.11", - "y-webrtc": "^10.3.0", - "yjs": "13.6.18" + "shiki": "^1.25.1", + "y-webrtc": "10.3.0", + "yjs": "13.6.23" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "3.1.2", + "@types/node": "22.10.3", "@types/uuid": "^8.3.4", "@vitejs/plugin-react": "^1.3.2", - "@vitejs/plugin-vue": "^5.2.0", + "@vitejs/plugin-vue": "^5.2.1", "autoprefixer": "^10.4.20", "esbuild": "0.25.0", "iframe-resizer": "^4.4.5", "postcss": "^8.4.49", "postcss-import": "^15.1.0", - "prosemirror-dev-tools": "^4.1.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "sass": "^1.81.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "sass": "^1.83.0", "svelte": "^4.2.19", - "tailwindcss": "^3.4.15", - "typescript": "^5.6.3", + "tailwindcss": "^3.4.17", + "typescript": "^5.7.2", "uuid": "^8.3.2", - "vite": "^5.4.15", + "vite": "^5.4.20", "vite-plugin-checker": "^0.6.4", "vue": "^3.5.13", - "vue-router": "^4.4.5" + "vue-router": "^4.5.0" } } diff --git a/demos/preview/Demo.vue b/demos/preview/Demo.vue index 5c99902302..15df8cb2fe 100644 --- a/demos/preview/Demo.vue +++ b/demos/preview/Demo.vue @@ -6,23 +6,18 @@ :key="index" @click="setTab(language.name)" class="px-3 py-2 text-sm text-white leading-[125%] font-semibold rounded-[0.625rem] transition-all" - :class="[currentTab === language.name - ? 'opacity-100 bg-[#1C1917]' - : 'opacity-50 bg-transparent hover:opacity-100 hover:bg-[#1C1917]' + :class="[ + currentTab === language.name + ? 'opacity-100 bg-[#1C1917]' + : 'opacity-50 bg-transparent hover:opacity-100 hover:bg-[#1C1917]', ]" > {{ language.name }}
-
- +
+
@@ -128,9 +119,7 @@ export default { }, query() { - return Object.fromEntries(Object - .entries(this.$route.query) - .map(([key, value]) => [key, this.fromString(value)])) + return Object.fromEntries(Object.entries(this.$route.query).map(([key, value]) => [key, this.fromString(value)])) }, inline() { @@ -220,9 +209,10 @@ export default { mounted() { // TODO: load language from url params - const intitialTab = localStorage.tab && this.tabs.some(tab => tab.name === localStorage.tab) - ? localStorage.tab - : this.sortedTabs[0]?.name + const intitialTab = + localStorage.tab && this.tabs.some(tab => tab.name === localStorage.tab) + ? localStorage.tab + : this.sortedTabs[0]?.name this.setTab(intitialTab, false) diff --git a/demos/preview/DemoFrame.vue b/demos/preview/DemoFrame.vue index ca9358b8c6..11f104d5f8 100644 --- a/demos/preview/DemoFrame.vue +++ b/demos/preview/DemoFrame.vue @@ -1,21 +1,16 @@ + + diff --git a/demos/src/Extensions/TableOfContents/React/ToC.jsx b/demos/src/Extensions/TableOfContents/React/ToC.jsx new file mode 100644 index 0000000000..4a3d05257e --- /dev/null +++ b/demos/src/Extensions/TableOfContents/React/ToC.jsx @@ -0,0 +1,67 @@ +import { TextSelection } from '@tiptap/pm/state' + +export const ToCItem = ({ item, onItemClick }) => { + return ( + + ) +} + +export const ToCEmptyState = () => { + return ( +
+

Start editing your document to see the outline.

+
+ ) +} + +export const ToC = ({ items = [], editor }) => { + if (items.length === 0) { + return + } + + const onItemClick = (e, id) => { + e.preventDefault() + + if (editor) { + const element = editor.view.dom.querySelector(`[data-toc-id="${id}"`) + const pos = editor.view.posAtDOM(element, 0) + + // set focus + const tr = editor.view.state.tr + + tr.setSelection(new TextSelection(tr.doc.resolve(pos))) + + editor.view.dispatch(tr) + + editor.view.focus() + + // eslint-disable-next-line + if (history.pushState) { + // eslint-disable-next-line + history.pushState(null, null, `#${id}`) + } + + window.scrollTo({ + top: element.getBoundingClientRect().top + window.scrollY, + behavior: 'smooth', + }) + } + } + + return ( + <> + {items.map((item, i) => ( + + ))} + + ) +} diff --git a/demos/src/Extensions/TableOfContents/React/index.html b/demos/src/Extensions/TableOfContents/React/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/Extensions/TableOfContents/React/index.jsx b/demos/src/Extensions/TableOfContents/React/index.jsx new file mode 100644 index 0000000000..3927551dd4 --- /dev/null +++ b/demos/src/Extensions/TableOfContents/React/index.jsx @@ -0,0 +1,48 @@ +import './styles.scss' + +import { getHierarchicalIndexes, TableOfContents } from '@tiptap/extension-table-of-contents' +import { EditorContent, useEditor } from '@tiptap/react' +import StarterKit from '@tiptap/starter-kit' +import React, { useState } from 'react' + +import { content as bookContent } from '../content.js' +import { ToC } from './ToC.jsx' + +const MemorizedToC = React.memo(ToC) + +export default () => { + const [items, setItems] = useState([]) + + const editor = useEditor({ + extensions: [ + StarterKit, + TableOfContents.configure({ + getIndex: getHierarchicalIndexes, + onUpdate(content) { + setItems(content) + }, + }), + ], + content: bookContent, + }) + + if (!editor) { + return null + } + + return ( +
+
+ +
+
+
+
Table of contents
+
+ +
+
+
+
+ ) +} diff --git a/demos/src/Extensions/TableOfContents/React/styles.scss b/demos/src/Extensions/TableOfContents/React/styles.scss new file mode 100644 index 0000000000..6c034bc6d2 --- /dev/null +++ b/demos/src/Extensions/TableOfContents/React/styles.scss @@ -0,0 +1,100 @@ +/* Basic editor styles */ +.tiptap { + :first-child { + margin-top: 0; + } +} + +.col-group { + display: flex; + flex-direction: row; + + @media (max-width: 540px) { + flex-direction: column-reverse; + } +} + +.main { + display: flex; + flex-direction: column; + width: 100%; + height: 100%; + overflow: auto; +} + +.sidebar { + border-left: 1px solid var(--gray-3); + flex-grow: 0; + flex-shrink: 0; + padding: 1rem; + width: 15rem; + position: sticky; + height: 100vh; + top: 0; + + @media (min-width: 800px) { + width: 20rem; + } + + @media (max-width: 540px) { + border-bottom: 1px solid var(--gray-3); + border-left: unset; + width: 100%; + height: auto; + position: unset; + padding: 1.5rem; + } +} + +.sidebar-options { + align-items: flex-start; + display: flex; + flex-direction: column; + height: 100%; + gap: 1rem; + position: sticky; + top: 1rem; +} + +.table-of-contents { + display: flex; + flex-direction: column; + font-size: 0.875rem; + gap: 0.25rem; + overflow: auto; + text-decoration: none; + + > div { + border-radius: 0.25rem; + padding-left: calc(0.875rem * (var(--level) - 1)); + transition: all 0.2s cubic-bezier(0.65, 0.05, 0.36, 1); + + &:hover { + background-color: var(--gray-2); + } + } + + .empty-state { + color: var(--gray-5); + user-select: none; + } + + .is-active a { + color: var(--purple); + } + + .is-scrolled-over a { + color: var(--gray-5); + } + + a { + color: var(--black); + display: flex; + gap: 0.25rem; + text-decoration: none; + + &::before { + content: attr(data-item-index) '.'; + } + } +} diff --git a/demos/src/Extensions/TableOfContents/Vue/ToC.vue b/demos/src/Extensions/TableOfContents/Vue/ToC.vue new file mode 100644 index 0000000000..2ed098ae2b --- /dev/null +++ b/demos/src/Extensions/TableOfContents/Vue/ToC.vue @@ -0,0 +1,63 @@ + + + diff --git a/demos/src/Extensions/TableOfContents/Vue/ToCEmptyState.vue b/demos/src/Extensions/TableOfContents/Vue/ToCEmptyState.vue new file mode 100644 index 0000000000..2236ab8e31 --- /dev/null +++ b/demos/src/Extensions/TableOfContents/Vue/ToCEmptyState.vue @@ -0,0 +1,5 @@ + diff --git a/demos/src/Extensions/TableOfContents/Vue/ToCItem.vue b/demos/src/Extensions/TableOfContents/Vue/ToCItem.vue new file mode 100644 index 0000000000..e5a722763c --- /dev/null +++ b/demos/src/Extensions/TableOfContents/Vue/ToCItem.vue @@ -0,0 +1,38 @@ + + + diff --git a/demos/src/Extensions/TableOfContents/Vue/index.html b/demos/src/Extensions/TableOfContents/Vue/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/Extensions/TableOfContents/Vue/index.spec.js b/demos/src/Extensions/TableOfContents/Vue/index.spec.js new file mode 100644 index 0000000000..839eb83420 --- /dev/null +++ b/demos/src/Extensions/TableOfContents/Vue/index.spec.js @@ -0,0 +1,7 @@ +context('/src/Extensions/TableOfContents/Vue', () => { + before(() => { + cy.visit('/src/Extensions/TableOfContents/Vue') + }) + + // TODO: Write tests +}) diff --git a/demos/src/Extensions/TableOfContents/Vue/index.vue b/demos/src/Extensions/TableOfContents/Vue/index.vue new file mode 100644 index 0000000000..9650fc4d85 --- /dev/null +++ b/demos/src/Extensions/TableOfContents/Vue/index.vue @@ -0,0 +1,163 @@ + + + + + diff --git a/demos/src/Extensions/TableOfContents/content.js b/demos/src/Extensions/TableOfContents/content.js new file mode 100644 index 0000000000..a22dbcac61 --- /dev/null +++ b/demos/src/Extensions/TableOfContents/content.js @@ -0,0 +1,27 @@ +export const content = ` +

Text editor

+

A text editor is a type of computer program that edits plain text. Such programs are sometimes known as "notepad" software (e.g. Windows Notepad). Text editors are provided with operating systems and software development packages, and can be used to change files such as configuration files, documentation files and programming language source code.

+ +

Plain text and rich text

+

There are important differences between plain text (created and edited by text editors) and rich text (such as that created by word processors or desktop publishing software).

+

Plain text exclusively consists of character representation. Each character is represented by a fixed-length sequence of one, two, or four bytes, or as a variable-length sequence of one to four bytes, in accordance to specific character encoding conventions, such as ASCII, ISO/IEC 2022, Shift JIS, UTF-8, or UTF-16. These conventions define many printable characters, but also non-printing characters that control the flow of the text, such as space, line break, and page break. Plain text contains no other information about the text itself, not even the character encoding convention employed. Plain text is stored in text files, although text files do not exclusively store plain text. Since the early days of computers, plain text was (once by necessity and now by convention) generally displayed using a monospace font, such that horizontal alignment and columnar formatting were sometimes done using whitespace characters.

+

Rich text, on the other hand, may contain metadata, character formatting data (e.g. typeface, size, weight and style), paragraph formatting data (e.g. indentation, alignment, letter and word distribution, and space between lines or other paragraphs), and page specification data (e.g. size, margin and reading direction). Rich text can be very complex. Rich text can be saved in binary format (e.g. DOC), text files adhering to a markup language (e.g. RTF or HTML), or in a hybrid form of both (e.g. Office Open XML).

+

Text editors are intended to open and save text files containing either plain text or anything that can be interpreted as plain text, including the markup for rich text or the markup for something else (e.g. SVG).

+ +

History

+ +

Before text editors existed, computer text was punched into cards with keypunch machines. Physical boxes of these thin cardboard cards were then inserted into a card reader. Magnetic tape, drum and disk card image files created from such card decks often had no line-separation characters at all, and assumed fixed-length 80- or 90-character records. An alternative to cards was Punched tape. It could be created by some teleprinters (such as the Teletype), which used special characters to indicate ends of records. Some early operating systems included batch text editors, either integrated with language processors or as separate utility programs; one early example was the ability to edit SQUOZE source files for SCAT in SHARE Operating System.

+

The first interactive text editors were "line editors" oriented to teleprinter- or typewriter-style terminals without displays. Commands (often a single keystroke) effected edits to a file at an imaginary insertion point called the "cursor". Edits were verified by typing a command to print a small section of the file, and periodically by printing the entire file. In some line editors, the cursor could be moved by commands that specified the line number in the file, text strings (context) for which to search, and eventually regular expressions. Line editors were major improvements over keypunching. Some line editors could be used by keypunch; editing commands could be taken from a deck of cards and applied to a specified file. Some common line editors supported a "verify" mode in which change commands displayed the altered lines.

+ +
Weird h5 headline
+

When computer terminals with video screens became available, screen-based text editors (sometimes called just "screen editors") became common. One of the earliest full-screen editors was O26, which was written for the operator console of the CDC 6000 series computers in 1967. Another early full-screen editor was vi. Written in the 1970s, it is still a standard editor on Unix and Linux operating systems. Also written in the 1970s was the UCSD Pascal Screen Oriented Editor, which was optimized both for indented source code and general text. Emacs, one of the first free and open-source software projects, is another early full-screen or real-time editor, one that was ported to many systems. A full-screen editor's ease-of-use and speed (compared to the line-based editors) motivated many early purchases of video terminals.

+ +

Types of text editors

+ +

Simple text editors

+

Some text editors are small and simple, while others offer broad and complex functions. For example, Unix and Unix-like operating systems have the pico editor (or a variant), but many also include the vi and Emacs editors. Microsoft Windows systems come with the simple Notepad, though many people—especially programmers—prefer other editors with more features. Under Apple Macintosh's classic Mac OS there was the native TeachText later replaced by SimpleText in 1994, which was replaced in Mac OS X by TextEdit, which combines features of a text editor with those typical of a word processor such as rulers, margins and multiple font selection. These features are not available simultaneously, but must be switched by user command, or through the program automatically determining the file type.

+ +

Word editors

+ +

Most word processors can read and write files in plain text format, allowing them to open files saved from text editors. Saving these files from a word processor, however, requires ensuring the file is written in plain text format, and that any text encoding or BOM settings won't obscure the file for its intended use. Non-WYSIWYG word processors, such as WordStar, are more easily pressed into service as text editors, and in fact were commonly used as such during the 1980s. The default file format of these word processors often resembles a markup language, with the basic format being plain text and visual formatting achieved using non-printing control characters or escape sequences. Later word processors like Microsoft Word store their files in a binary format and are almost never used to edit plain text files.

+` diff --git a/demos/src/Extensions/TextAlign/React/index.jsx b/demos/src/Extensions/TextAlign/React/index.jsx index 77971b4ae5..a9d5b0f93f 100644 --- a/demos/src/Extensions/TextAlign/React/index.jsx +++ b/demos/src/Extensions/TextAlign/React/index.jsx @@ -58,8 +58,18 @@ export default () => { > Justify - + + - - - - + +
diff --git a/demos/src/Extensions/TrailingNode/React/index.html b/demos/src/Extensions/TrailingNode/React/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/Extensions/TrailingNode/React/index.tsx b/demos/src/Extensions/TrailingNode/React/index.tsx new file mode 100644 index 0000000000..bc11c2cdd9 --- /dev/null +++ b/demos/src/Extensions/TrailingNode/React/index.tsx @@ -0,0 +1,23 @@ +import './styles.scss' + +import Code from '@tiptap/extension-code' +import CodeBlock from '@tiptap/extension-code-block' +import Document from '@tiptap/extension-document' +import { BulletList, ListItem } from '@tiptap/extension-list' +import Paragraph from '@tiptap/extension-paragraph' +import Text from '@tiptap/extension-text' +import { TrailingNode } from '@tiptap/extensions' +import { EditorContent, useEditor } from '@tiptap/react' +import React from 'react' + +export default () => { + const editor = useEditor({ + extensions: [Document, Paragraph, Text, TrailingNode, Code, BulletList, ListItem, CodeBlock], + content: ` +

A paragraph

+
There should be a paragraph right after this one, because it is a code-block
+ `, + }) + + return +} diff --git a/demos/src/Extensions/TrailingNode/React/styles.scss b/demos/src/Extensions/TrailingNode/React/styles.scss new file mode 100644 index 0000000000..15283b15a5 --- /dev/null +++ b/demos/src/Extensions/TrailingNode/React/styles.scss @@ -0,0 +1,91 @@ +/* Basic editor styles */ +.tiptap { + :first-child { + margin-top: 0; + } + + /* List styles */ + ul, + ol { + padding: 0 1rem; + margin: 1.25rem 1rem 1.25rem 0.4rem; + + li p { + margin-top: 0.25em; + margin-bottom: 0.25em; + } + } + + /* Heading styles */ + h1, + h2, + h3, + h4, + h5, + h6 { + line-height: 1.1; + margin-top: 2.5rem; + text-wrap: pretty; + } + + h1, + h2 { + margin-top: 3.5rem; + margin-bottom: 1.5rem; + } + + h1 { + font-size: 1.4rem; + } + + h2 { + font-size: 1.2rem; + } + + h3 { + font-size: 1.1rem; + } + + h4, + h5, + h6 { + font-size: 1rem; + } + + /* Code and preformatted text styles */ + code { + background-color: var(--purple-light); + border-radius: 0.4rem; + color: var(--black); + font-size: 0.85rem; + padding: 0.25em 0.3em; + } + + pre { + background: var(--black); + border-radius: 0.5rem; + color: var(--white); + font-family: 'JetBrainsMono', monospace; + margin: 1.5rem 0; + padding: 0.75rem 1rem; + + code { + background: none; + color: inherit; + font-size: 0.8rem; + padding: 0; + } + } + + blockquote { + border-left: 3px solid var(--gray-3); + margin: 1.5rem 0; + padding-left: 1rem; + } + + hr { + border: none; + border-top: 1px solid var(--gray-2); + margin: 2rem 0; + } +} diff --git a/demos/src/Extensions/TrailingNode/Vue/index.html b/demos/src/Extensions/TrailingNode/Vue/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/Extensions/TrailingNode/Vue/index.vue b/demos/src/Extensions/TrailingNode/Vue/index.vue new file mode 100644 index 0000000000..fdf5414b42 --- /dev/null +++ b/demos/src/Extensions/TrailingNode/Vue/index.vue @@ -0,0 +1,136 @@ + + + + + diff --git a/demos/src/Extensions/Typography/React/index.jsx b/demos/src/Extensions/Typography/React/index.jsx index 37c7a68077..3a9b04efb4 100644 --- a/demos/src/Extensions/Typography/React/index.jsx +++ b/demos/src/Extensions/Typography/React/index.jsx @@ -9,12 +9,7 @@ import React from 'react' export default () => { const editor = useEditor({ - extensions: [ - Document, - Paragraph, - Text, - Typography, - ], + extensions: [Document, Paragraph, Text, Typography], content: `

“I have been suffering from Typomania all my life, a sickness that is incurable but not lethal.”

— Erik Spiekermann, December 2008

diff --git a/demos/src/Extensions/Typography/React/index.spec.js b/demos/src/Extensions/Typography/React/index.spec.js index b99b282236..3c1b474202 100644 --- a/demos/src/Extensions/Typography/React/index.spec.js +++ b/demos/src/Extensions/Typography/React/index.spec.js @@ -1,5 +1,5 @@ context('/src/Extensions/Typography/React/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Extensions/Typography/React/') }) @@ -55,9 +55,7 @@ context('/src/Extensions/Typography/React/', () => { }) it('should make a registered trademark sign', () => { - cy.get('.tiptap') - .type('(r) registeredTrademark') - .should('contain', '® registeredTrademark') + cy.get('.tiptap').type('(r) registeredTrademark').should('contain', '® registeredTrademark') }) it('should make a trademark sign', () => { diff --git a/demos/src/Extensions/Typography/Vue/index.spec.js b/demos/src/Extensions/Typography/Vue/index.spec.js index 2cba19876c..b251d92a67 100644 --- a/demos/src/Extensions/Typography/Vue/index.spec.js +++ b/demos/src/Extensions/Typography/Vue/index.spec.js @@ -1,5 +1,5 @@ context('/src/Extensions/Typography/Vue/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Extensions/Typography/Vue/') }) @@ -10,122 +10,82 @@ context('/src/Extensions/Typography/Vue/', () => { }) it('should make an em dash from two dashes', () => { - cy.get('.tiptap') - .type('-- emDash') - .should('contain', '— emDash') + cy.get('.tiptap').type('-- emDash').should('contain', '— emDash') }) it('should make an ellipsis from three dots', () => { - cy.get('.tiptap') - .type('... ellipsis') - .should('contain', '… ellipsis') + cy.get('.tiptap').type('... ellipsis').should('contain', '… ellipsis') }) it('should make a correct open double quote', () => { - cy.get('.tiptap') - .type('"openDoubleQuote"') - .should('contain', '“openDoubleQuote') + cy.get('.tiptap').type('"openDoubleQuote"').should('contain', '“openDoubleQuote') }) it('should make a correct close double quote', () => { - cy.get('.tiptap') - .type('"closeDoubleQuote"') - .should('contain', 'closeDoubleQuote”') + cy.get('.tiptap').type('"closeDoubleQuote"').should('contain', 'closeDoubleQuote”') }) it('should make a correct open single quote', () => { - cy.get('.tiptap') - .type("'openSingleQuote'") - .should('contain', '‘openSingleQuote’') + cy.get('.tiptap').type("'openSingleQuote'").should('contain', '‘openSingleQuote’') }) it('should make a correct close single quote', () => { - cy.get('.tiptap') - .type("'closeSingleQuote'") - .should('contain', 'closeSingleQuote’') + cy.get('.tiptap').type("'closeSingleQuote'").should('contain', 'closeSingleQuote’') }) it('should make a left arrow', () => { - cy.get('.tiptap') - .type('<- leftArrow') - .should('contain', '← leftArrow') + cy.get('.tiptap').type('<- leftArrow').should('contain', '← leftArrow') }) it('should make a right arrow', () => { - cy.get('.tiptap') - .type('-> rightArrow') - .should('contain', '→ rightArrow') + cy.get('.tiptap').type('-> rightArrow').should('contain', '→ rightArrow') }) it('should make a copyright sign', () => { - cy.get('.tiptap') - .type('(c) copyright') - .should('contain', '© copyright') + cy.get('.tiptap').type('(c) copyright').should('contain', '© copyright') }) it('should make a registered trademark sign', () => { - cy.get('.tiptap') - .type('(r) registeredTrademark') - .should('contain', '® registeredTrademark') + cy.get('.tiptap').type('(r) registeredTrademark').should('contain', '® registeredTrademark') }) it('should make a trademark sign', () => { - cy.get('.tiptap') - .type('(tm) trademark') - .should('contain', '™ trademark') + cy.get('.tiptap').type('(tm) trademark').should('contain', '™ trademark') }) it('should make a one half', () => { - cy.get('.tiptap') - .type('1/2 oneHalf') - .should('contain', '½ oneHalf') + cy.get('.tiptap').type('1/2 oneHalf').should('contain', '½ oneHalf') }) it('should make a plus/minus sign', () => { - cy.get('.tiptap') - .type('+/- plusMinus') - .should('contain', '± plusMinus') + cy.get('.tiptap').type('+/- plusMinus').should('contain', '± plusMinus') }) it('should make a not equal sign', () => { - cy.get('.tiptap') - .type('!= notEqual') - .should('contain', '≠ notEqual') + cy.get('.tiptap').type('!= notEqual').should('contain', '≠ notEqual') }) it('should make a laquo', () => { - cy.get('.tiptap') - .type('<< laquorow') - .should('contain', '« laquo') + cy.get('.tiptap').type('<< laquorow').should('contain', '« laquo') }) it('should make a raquo', () => { - cy.get('.tiptap') - .type('>> raquorow') - .should('contain', '» raquo') + cy.get('.tiptap').type('>> raquorow').should('contain', '» raquo') }) it('should make a multiplication sign from an asterisk', () => { - cy.get('.tiptap') - .type('1*1 multiplication') - .should('contain', '1×1 multiplication') + cy.get('.tiptap').type('1*1 multiplication').should('contain', '1×1 multiplication') }) it('should make a multiplication sign from an x', () => { - cy.get('.tiptap') - .type('1x1 multiplication') - .should('contain', '1×1 multiplication') + cy.get('.tiptap').type('1x1 multiplication').should('contain', '1×1 multiplication') }) it('should make a multiplication sign from an asterisk with spaces', () => { - cy.get('.tiptap') - .type('1 * 1 multiplication') - .should('contain', '1 × 1 multiplication') + cy.get('.tiptap').type('1 * 1 multiplication').should('contain', '1 × 1 multiplication') }) it('should make a multiplication sign from an x with spaces', () => { - cy.get('.tiptap') - .type('1 x 1 multiplication') - .should('contain', '1 × 1 multiplication') + cy.get('.tiptap').type('1 x 1 multiplication').should('contain', '1 × 1 multiplication') }) }) diff --git a/demos/src/Extensions/Typography/Vue/index.vue b/demos/src/Extensions/Typography/Vue/index.vue index 63d585ba72..0e4dd5c437 100644 --- a/demos/src/Extensions/Typography/Vue/index.vue +++ b/demos/src/Extensions/Typography/Vue/index.vue @@ -22,12 +22,7 @@ export default { mounted() { this.editor = new Editor({ - extensions: [ - Document, - Paragraph, - Text, - Typography, - ], + extensions: [Document, Paragraph, Text, Typography], content: `

“I have been suffering from Typomania all my life, a sickness that is incurable but not lethal.”

— Erik Spiekermann, December 2008

diff --git a/demos/src/Extensions/TypographyWithOverrides/React/index.spec.js b/demos/src/Extensions/TypographyWithOverrides/React/index.spec.js index 8f3f99625a..ea453e16a8 100644 --- a/demos/src/Extensions/TypographyWithOverrides/React/index.spec.js +++ b/demos/src/Extensions/TypographyWithOverrides/React/index.spec.js @@ -1,5 +1,5 @@ context('/src/Extensions/TypographyWithOverrides/React/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Extensions/TypographyWithOverrides/React/') }) diff --git a/demos/src/Extensions/TypographyWithOverrides/Vue/index.spec.js b/demos/src/Extensions/TypographyWithOverrides/Vue/index.spec.js index ec4851792a..2382399c09 100644 --- a/demos/src/Extensions/TypographyWithOverrides/Vue/index.spec.js +++ b/demos/src/Extensions/TypographyWithOverrides/Vue/index.spec.js @@ -1,5 +1,5 @@ context('/src/Extensions/TypographyWithOverrides/Vue/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Extensions/TypographyWithOverrides/Vue/') }) diff --git a/demos/src/Extensions/UndoRedo/React/index.html b/demos/src/Extensions/UndoRedo/React/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/Extensions/History/React/index.jsx b/demos/src/Extensions/UndoRedo/React/index.jsx similarity index 55% rename from demos/src/Extensions/History/React/index.jsx rename to demos/src/Extensions/UndoRedo/React/index.jsx index ee32463b0b..1b9a6c2798 100644 --- a/demos/src/Extensions/History/React/index.jsx +++ b/demos/src/Extensions/UndoRedo/React/index.jsx @@ -1,18 +1,18 @@ import './styles.scss' import Document from '@tiptap/extension-document' -import History from '@tiptap/extension-history' import Paragraph from '@tiptap/extension-paragraph' import Text from '@tiptap/extension-text' -import { EditorContent, useEditor } from '@tiptap/react' +import { UndoRedo } from '@tiptap/extensions' +import { EditorContent, useEditor, useEditorState } from '@tiptap/react' import React from 'react' export default () => { const editor = useEditor({ - extensions: [Document, Paragraph, Text, History], + extensions: [Document, Paragraph, Text, UndoRedo], content: `

- With the History extension the Editor will keep track of your changes. And if you think you made a mistake, you can redo your changes. Try it out, change the content and hit the undo button! + With the UndoRedo extension the Editor will keep track of your changes. And if you think you made a mistake, you can redo your changes. Try it out, change the content and hit the undo button!

And yes, you can also use a keyboard shortcut to undo changes (Control/Cmd Z) or redo changes (Control/Cmd Shift Z). @@ -20,6 +20,16 @@ export default () => { `, }) + const { canUndo, canRedo } = useEditorState({ + editor, + selector: ctx => { + return { + canUndo: ctx.editor.can().chain().focus().undo().run(), + canRedo: ctx.editor.can().chain().focus().redo().run(), + } + }, + }) + if (!editor) { return null } @@ -28,10 +38,10 @@ export default () => { <>

- -
diff --git a/demos/src/Extensions/UndoRedo/React/index.spec.js b/demos/src/Extensions/UndoRedo/React/index.spec.js new file mode 100644 index 0000000000..cf433e018f --- /dev/null +++ b/demos/src/Extensions/UndoRedo/React/index.spec.js @@ -0,0 +1,90 @@ +context('/src/Extensions/UndoRedo/React/', () => { + beforeEach(() => { + cy.visit('/src/Extensions/UndoRedo/React/') + cy.get('.tiptap').then(([{ editor }]) => { + editor.commands.setContent('

Mistake

') + }) + }) + + it('should make the last change undone', () => { + cy.get('.tiptap').should('contain', 'Mistake') + + cy.get('button:first').should('not.have.attr', 'disabled') + + cy.get('button:first').click() + + cy.get('.tiptap').should('not.contain', 'Mistake') + }) + + it('should make the last change undone with the keyboard shortcut', () => { + cy.get('.tiptap').trigger('keydown', { modKey: true, key: 'z' }) + + cy.get('.tiptap').should('not.contain', 'Mistake') + }) + + it('should make the last change undone with the keyboard shortcut (russian)', () => { + cy.get('.tiptap').should('contain', 'Mistake') + + cy.get('.tiptap').trigger('keydown', { modKey: true, key: 'я' }) + + cy.get('.tiptap').should('not.contain', 'Mistake') + }) + + it('should apply the last undone change again with the keyboard shortcut', () => { + cy.get('.tiptap').trigger('keydown', { modKey: true, key: 'z' }) + + cy.get('.tiptap').should('not.contain', 'Mistake') + + cy.get('.tiptap').trigger('keydown', { modKey: true, shiftKey: true, key: 'z' }) + + cy.get('.tiptap').should('contain', 'Mistake') + }) + + it('should apply the last undone change again with the keyboard shortcut (russian)', () => { + cy.get('.tiptap').trigger('keydown', { modKey: true, key: 'я' }) + + cy.get('.tiptap').should('not.contain', 'Mistake') + + cy.get('.tiptap').trigger('keydown', { modKey: true, shiftKey: true, key: 'я' }) + + cy.get('.tiptap').should('contain', 'Mistake') + }) + + it('should apply the last undone change again', () => { + cy.get('.tiptap').should('contain', 'Mistake') + + cy.get('button:first').should('not.have.attr', 'disabled') + + cy.get('button:first').click() + + cy.get('.tiptap').should('not.contain', 'Mistake') + + cy.get('button:first').should('have.attr', 'disabled') + + cy.get('button:nth-child(2)').click() + + cy.get('.tiptap').should('contain', 'Mistake') + }) + + it('should disable undo button when there are no more changes to undo', () => { + cy.get('.tiptap').should('contain', 'Mistake') + + cy.get('button:first').should('not.have.attr', 'disabled') + + cy.get('button:first').click() + + cy.get('button:first').should('have.attr', 'disabled') + }) + + it('should disable redo button when there are no more changes to redo', () => { + cy.get('.tiptap').should('contain', 'Mistake') + + cy.get('button:nth-child(2)').should('have.attr', 'disabled') + + cy.get('button:first').should('not.have.attr', 'disabled') + + cy.get('button:first').click() + + cy.get('button:nth-child(2)').should('not.have.attr', 'disabled') + }) +}) diff --git a/demos/src/Extensions/UndoRedo/React/styles.scss b/demos/src/Extensions/UndoRedo/React/styles.scss new file mode 100644 index 0000000000..afd5ba2145 --- /dev/null +++ b/demos/src/Extensions/UndoRedo/React/styles.scss @@ -0,0 +1,6 @@ +/* Basic editor styles */ +.tiptap { + :first-child { + margin-top: 0; + } +} diff --git a/demos/src/Extensions/UndoRedo/Vue/index.html b/demos/src/Extensions/UndoRedo/Vue/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/Extensions/History/React/index.spec.js b/demos/src/Extensions/UndoRedo/Vue/index.spec.js similarity index 96% rename from demos/src/Extensions/History/React/index.spec.js rename to demos/src/Extensions/UndoRedo/Vue/index.spec.js index b358de7fbc..09cf592395 100644 --- a/demos/src/Extensions/History/React/index.spec.js +++ b/demos/src/Extensions/UndoRedo/Vue/index.spec.js @@ -1,6 +1,6 @@ -context('/src/Extensions/History/React/', () => { +context('/src/Extensions/UndoRedo/Vue/', () => { beforeEach(() => { - cy.visit('/src/Extensions/History/React/') + cy.visit('/src/Extensions/UndoRedo/Vue/') cy.get('.tiptap').then(([{ editor }]) => { editor.commands.setContent('

Mistake

') }) diff --git a/demos/src/Extensions/History/Vue/index.vue b/demos/src/Extensions/UndoRedo/Vue/index.vue similarity index 59% rename from demos/src/Extensions/History/Vue/index.vue rename to demos/src/Extensions/UndoRedo/Vue/index.vue index 33ec10b185..5f38ecc01c 100644 --- a/demos/src/Extensions/History/Vue/index.vue +++ b/demos/src/Extensions/UndoRedo/Vue/index.vue @@ -2,18 +2,8 @@
- - + +
@@ -22,9 +12,9 @@ + + diff --git a/demos/src/Extensions/UniqueIDWithYdoc/React/index.html b/demos/src/Extensions/UniqueIDWithYdoc/React/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/Extensions/UniqueIDWithYdoc/React/index.jsx b/demos/src/Extensions/UniqueIDWithYdoc/React/index.jsx new file mode 100644 index 0000000000..1a700b6337 --- /dev/null +++ b/demos/src/Extensions/UniqueIDWithYdoc/React/index.jsx @@ -0,0 +1,50 @@ +import './styles.scss' + +import { TiptapTransformer } from '@hocuspocus/transformer' +import Collaboration from '@tiptap/extension-collaboration' +import Document from '@tiptap/extension-document' +import Heading from '@tiptap/extension-heading' +import Paragraph from '@tiptap/extension-paragraph' +import Text from '@tiptap/extension-text' +import UniqueID from '@tiptap/extension-unique-id' +import { EditorContent, useEditor } from '@tiptap/react' +import React from 'react' + +const doc = TiptapTransformer.toYdoc({ + type: 'doc', + content: [ + { + type: 'heading', + attrs: { level: 1 }, + content: [{ type: 'text', text: 'This is a predefined, collaborative ydoc' }], + }, + { + type: 'paragraph', + content: [{ type: 'text', text: "Let's see how this works out." }], + }, + { + type: 'paragraph', + content: [{ type: 'text', text: 'This should now generate unique IDs correctly' }], + }, + ], +}) + +export default () => { + const editor = useEditor({ + extensions: [ + Document, + Heading, + Paragraph, + Text, + Collaboration.configure({ + document: doc, + }), + UniqueID.configure({ + types: ['heading', 'paragraph'], + filterTransaction: () => true, + }), + ], + }) + + return +} diff --git a/demos/src/Extensions/UniqueIDWithYdoc/React/index.spec.js b/demos/src/Extensions/UniqueIDWithYdoc/React/index.spec.js new file mode 100644 index 0000000000..c550baf264 --- /dev/null +++ b/demos/src/Extensions/UniqueIDWithYdoc/React/index.spec.js @@ -0,0 +1,13 @@ +context('/src/Extensions/UniqueID/React/', () => { + beforeEach(() => { + cy.visit('/src/Extensions/UniqueID/React/') + }) + + it('has a heading with an unique ID', () => { + cy.get('.ProseMirror h1').should('have.attr', 'data-id') + }) + + it('has a paragraph with an unique ID', () => { + cy.get('.ProseMirror p').should('have.attr', 'data-id') + }) +}) diff --git a/demos/src/Extensions/UniqueIDWithYdoc/React/styles.scss b/demos/src/Extensions/UniqueIDWithYdoc/React/styles.scss new file mode 100644 index 0000000000..80811178c1 --- /dev/null +++ b/demos/src/Extensions/UniqueIDWithYdoc/React/styles.scss @@ -0,0 +1,55 @@ +/* Basic editor styles */ +.tiptap { + :first-child { + margin-top: 0; + } + + /* Unique data id */ + [data-id] { + border: 2px solid var(--black); + border-radius: 0.5rem; + padding: 2.5rem 1rem 1rem; + position: relative; + + &::before { + background-color: var(--black); + border-radius: 0 0 0.5rem 0; + color: var(--white); + content: attr(data-id); + font-size: 0.75rem; + font-weight: bold; + left: 0; + line-height: 1.5; + padding: 0.25rem 0.5rem; + position: absolute; + top: 0; + } + } + + /* Give a remote user a caret */ + .collaboration-carets__caret { + border-left: 1px solid #0d0d0d; + border-right: 1px solid #0d0d0d; + margin-left: -1px; + margin-right: -1px; + pointer-events: none; + position: relative; + word-break: normal; + } + + /* Render the username above the caret */ + .collaboration-carets__label { + border-radius: 3px 3px 3px 0; + color: #0d0d0d; + font-size: 12px; + font-style: normal; + font-weight: 600; + left: -1px; + line-height: normal; + padding: 0.1rem 0.3rem; + position: absolute; + top: -1.4em; + user-select: none; + white-space: nowrap; + } +} diff --git a/demos/src/GuideContent/ExportHTML/React/index.jsx b/demos/src/GuideContent/ExportHTML/React/index.jsx index 05af0d91b0..96e1b6ba09 100644 --- a/demos/src/GuideContent/ExportHTML/React/index.jsx +++ b/demos/src/GuideContent/ExportHTML/React/index.jsx @@ -37,7 +37,6 @@ export default () => { It’s 19871. You can’t turn on a radio, or go to a mall without hearing Olivia Newton-John’s hit song, Physical.

`, - true, ) // It’s likely that you’d like to focus the Editor after most commands. diff --git a/demos/src/GuideContent/ExportHTML/React/index.spec.js b/demos/src/GuideContent/ExportHTML/React/index.spec.js index f216a5bde8..6bd49a9bb7 100644 --- a/demos/src/GuideContent/ExportHTML/React/index.spec.js +++ b/demos/src/GuideContent/ExportHTML/React/index.spec.js @@ -1,5 +1,5 @@ context('/src/GuideContent/ExportHTML/React/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/GuideContent/ExportHTML/React/') }) diff --git a/demos/src/GuideContent/ExportHTML/React/styles.scss b/demos/src/GuideContent/ExportHTML/React/styles.scss index 7694d7322a..15283b15a5 100644 --- a/demos/src/GuideContent/ExportHTML/React/styles.scss +++ b/demos/src/GuideContent/ExportHTML/React/styles.scss @@ -5,11 +5,11 @@ } /* List styles */ - ul, + ul, ol { padding: 0 1rem; margin: 1.25rem 1rem 1.25rem 0.4rem; - + li p { margin-top: 0.25em; margin-bottom: 0.25em; @@ -17,39 +17,39 @@ } /* Heading styles */ - h1, - h2, - h3, - h4, - h5, + h1, + h2, + h3, + h4, + h5, h6 { line-height: 1.1; margin-top: 2.5rem; text-wrap: pretty; } - h1, + h1, h2 { margin-top: 3.5rem; margin-bottom: 1.5rem; } - h1 { - font-size: 1.4rem; + h1 { + font-size: 1.4rem; } - h2 { - font-size: 1.2rem; + h2 { + font-size: 1.2rem; } - h3 { - font-size: 1.1rem; + h3 { + font-size: 1.1rem; } - h4, - h5, - h6 { - font-size: 1rem; + h4, + h5, + h6 { + font-size: 1rem; } /* Code and preformatted text styles */ diff --git a/demos/src/GuideContent/ExportHTML/Vue/index.spec.js b/demos/src/GuideContent/ExportHTML/Vue/index.spec.js index 1bb8ae6f4e..25d8bd7bd9 100644 --- a/demos/src/GuideContent/ExportHTML/Vue/index.spec.js +++ b/demos/src/GuideContent/ExportHTML/Vue/index.spec.js @@ -1,5 +1,5 @@ context('/src/GuideContent/ExportHTML/Vue/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/GuideContent/ExportHTML/Vue/') }) diff --git a/demos/src/GuideContent/ExportHTML/Vue/index.vue b/demos/src/GuideContent/ExportHTML/Vue/index.vue index 25e6104d08..27a9a26034 100644 --- a/demos/src/GuideContent/ExportHTML/Vue/index.vue +++ b/demos/src/GuideContent/ExportHTML/Vue/index.vue @@ -2,16 +2,15 @@
- - + + -
@@ -49,9 +48,7 @@ export default { Wow, this editor instance exports its content as HTML.

`, - extensions: [ - StarterKit, - ], + extensions: [StarterKit], }) // Get the initial content … @@ -66,22 +63,21 @@ export default { methods: { setContent() { // You can pass a HTML document to the editor. - this.editor.commands.setContent(` + this.editor.commands.setContent( + `

It’s 19871. You can’t turn on a radio, or go to a mall without hearing Olivia Newton-John’s hit song, Physical.

- `, true) + `, + true, + ) // It’s likely that you’d like to focus the Editor after most commands. this.editor.commands.focus() }, clearContent() { - this.editor - .chain() - .clearContent(true) - .focus() - .run() + this.editor.chain().clearContent(true).focus().run() }, }, diff --git a/demos/src/GuideContent/ExportJSON/React/index.jsx b/demos/src/GuideContent/ExportJSON/React/index.jsx index c2a0fcd3d4..0a2304c9d2 100644 --- a/demos/src/GuideContent/ExportJSON/React/index.jsx +++ b/demos/src/GuideContent/ExportJSON/React/index.jsx @@ -31,23 +31,20 @@ export default () => { const setContent = useCallback(() => { // You can pass a JSON document to the editor. - editor.commands.setContent( - { - type: 'doc', - content: [ - { - type: 'paragraph', - content: [ - { - type: 'text', - text: 'It’s 19871. You can’t turn on a radio, or go to a mall without hearing Olivia Newton-John’s hit song, Physical.', - }, - ], - }, - ], - }, - true, - ) + editor.commands.setContent({ + type: 'doc', + content: [ + { + type: 'paragraph', + content: [ + { + type: 'text', + text: 'It’s 19871. You can’t turn on a radio, or go to a mall without hearing Olivia Newton-John’s hit song, Physical.', + }, + ], + }, + ], + }) // It’s likely that you’d like to focus the Editor after most commands. editor.commands.focus() diff --git a/demos/src/GuideContent/ExportJSON/React/index.spec.js b/demos/src/GuideContent/ExportJSON/React/index.spec.js index 3fecf28a74..617a2f2fa9 100644 --- a/demos/src/GuideContent/ExportJSON/React/index.spec.js +++ b/demos/src/GuideContent/ExportJSON/React/index.spec.js @@ -1,5 +1,5 @@ context('/src/GuideContent/ExportJSON/React/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/GuideContent/ExportJSON/React/') }) diff --git a/demos/src/GuideContent/ExportJSON/React/styles.scss b/demos/src/GuideContent/ExportJSON/React/styles.scss index 7694d7322a..15283b15a5 100644 --- a/demos/src/GuideContent/ExportJSON/React/styles.scss +++ b/demos/src/GuideContent/ExportJSON/React/styles.scss @@ -5,11 +5,11 @@ } /* List styles */ - ul, + ul, ol { padding: 0 1rem; margin: 1.25rem 1rem 1.25rem 0.4rem; - + li p { margin-top: 0.25em; margin-bottom: 0.25em; @@ -17,39 +17,39 @@ } /* Heading styles */ - h1, - h2, - h3, - h4, - h5, + h1, + h2, + h3, + h4, + h5, h6 { line-height: 1.1; margin-top: 2.5rem; text-wrap: pretty; } - h1, + h1, h2 { margin-top: 3.5rem; margin-bottom: 1.5rem; } - h1 { - font-size: 1.4rem; + h1 { + font-size: 1.4rem; } - h2 { - font-size: 1.2rem; + h2 { + font-size: 1.2rem; } - h3 { - font-size: 1.1rem; + h3 { + font-size: 1.1rem; } - h4, - h5, - h6 { - font-size: 1rem; + h4, + h5, + h6 { + font-size: 1rem; } /* Code and preformatted text styles */ diff --git a/demos/src/GuideContent/ExportJSON/Vue/index.spec.js b/demos/src/GuideContent/ExportJSON/Vue/index.spec.js index 876ea5a173..56facb0d7e 100644 --- a/demos/src/GuideContent/ExportJSON/Vue/index.spec.js +++ b/demos/src/GuideContent/ExportJSON/Vue/index.spec.js @@ -1,5 +1,5 @@ context('/src/GuideContent/ExportJSON/Vue/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/GuideContent/ExportJSON/Vue/') }) diff --git a/demos/src/GuideContent/ExportJSON/Vue/index.vue b/demos/src/GuideContent/ExportJSON/Vue/index.vue index 9b7162ccff..f71681382d 100644 --- a/demos/src/GuideContent/ExportJSON/Vue/index.vue +++ b/demos/src/GuideContent/ExportJSON/Vue/index.vue @@ -2,16 +2,15 @@
- - + + -
@@ -49,9 +48,7 @@ export default { Wow, this editor instance exports its content as JSON.

`, - extensions: [ - StarterKit, - ], + extensions: [StarterKit], }) // Get the initial content … @@ -68,27 +65,25 @@ export default { // You can pass a JSON document to the editor. this.editor.commands.setContent({ type: 'doc', - content: [{ - type: 'paragraph', - content: [ - { - type: 'text', - text: 'It’s 19871. You can’t turn on a radio, or go to a mall without hearing Olivia Newton-John’s hit song, Physical.', - }, - ], - }], - }, true) + content: [ + { + type: 'paragraph', + content: [ + { + type: 'text', + text: 'It’s 19871. You can’t turn on a radio, or go to a mall without hearing Olivia Newton-John’s hit song, Physical.', + }, + ], + }, + ], + }) // It’s likely that you’d like to focus the Editor after most commands. this.editor.commands.focus() }, clearContent() { - this.editor - .chain() - .clearContent(true) - .focus() - .run() + this.editor.chain().clearContent(true).focus().run() }, }, diff --git a/demos/src/GuideContent/GenerateHTML/React/index.spec.js b/demos/src/GuideContent/GenerateHTML/React/index.spec.js index ffed7d1244..e30b536e97 100644 --- a/demos/src/GuideContent/GenerateHTML/React/index.spec.js +++ b/demos/src/GuideContent/GenerateHTML/React/index.spec.js @@ -1,7 +1,11 @@ context('/src/GuideContent/GenerateHTML/React/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/GuideContent/GenerateHTML/React/') }) - // TODO: Write tests + it('should render the content as an HTML string', () => { + cy.get('pre code').should('exist') + + cy.get('pre code').should('contain', '

Example Text

') + }) }) diff --git a/demos/src/GuideContent/GenerateHTML/React/index.jsx b/demos/src/GuideContent/GenerateHTML/React/index.tsx similarity index 98% rename from demos/src/GuideContent/GenerateHTML/React/index.jsx rename to demos/src/GuideContent/GenerateHTML/React/index.tsx index ce2d844a22..f3122aa15b 100644 --- a/demos/src/GuideContent/GenerateHTML/React/index.jsx +++ b/demos/src/GuideContent/GenerateHTML/React/index.tsx @@ -41,7 +41,7 @@ export default () => { Bold, // other extensions … ]) - }, [json]) + }, []) return (
diff --git a/demos/src/GuideContent/GenerateHTML/Vue/index.spec.js b/demos/src/GuideContent/GenerateHTML/Vue/index.spec.js
index 7138866540..de101cb11d 100644
--- a/demos/src/GuideContent/GenerateHTML/Vue/index.spec.js
+++ b/demos/src/GuideContent/GenerateHTML/Vue/index.spec.js
@@ -1,7 +1,11 @@
 context('/src/GuideContent/GenerateHTML/Vue/', () => {
-  before(() => {
+  beforeEach(() => {
     cy.visit('/src/GuideContent/GenerateHTML/Vue/')
   })
 
-  // TODO: Write tests
+  it('should render the content as an HTML string', () => {
+    cy.get('pre code').should('exist')
+
+    cy.get('pre code').should('contain', '

Example Text

') + }) }) diff --git a/demos/src/GuideContent/GenerateJSON/React/index.jsx b/demos/src/GuideContent/GenerateJSON/React/index.jsx index cc5e12f434..fd6c7c309b 100644 --- a/demos/src/GuideContent/GenerateJSON/React/index.jsx +++ b/demos/src/GuideContent/GenerateJSON/React/index.jsx @@ -19,7 +19,7 @@ export default () => { Bold, // other extensions … ]) - }, [html]) + }, []) return (
diff --git a/demos/src/GuideContent/GenerateJSON/React/index.spec.js b/demos/src/GuideContent/GenerateJSON/React/index.spec.js
index 20a7040996..b84b11b592 100644
--- a/demos/src/GuideContent/GenerateJSON/React/index.spec.js
+++ b/demos/src/GuideContent/GenerateJSON/React/index.spec.js
@@ -1,7 +1,36 @@
 context('/src/GuideContent/GenerateJSON/React/', () => {
-  before(() => {
+  beforeEach(() => {
     cy.visit('/src/GuideContent/GenerateJSON/React/')
   })
 
-  // TODO: Write tests
+  it('should render the content as an HTML string', () => {
+    cy.get('pre code').should('exist')
+
+    cy.get('pre code').should(
+      'contain',
+      `{
+  "type": "doc",
+  "content": [
+    {
+      "type": "paragraph",
+      "content": [
+        {
+          "type": "text",
+          "text": "Example "
+        },
+        {
+          "type": "text",
+          "marks": [
+            {
+              "type": "bold"
+            }
+          ],
+          "text": "Text"
+        }
+      ]
+    }
+  ]
+}`,
+    )
+  })
 })
diff --git a/demos/src/GuideContent/GenerateJSON/Vue/index.spec.js b/demos/src/GuideContent/GenerateJSON/Vue/index.spec.js
index 6c9caed2ad..90a0678c54 100644
--- a/demos/src/GuideContent/GenerateJSON/Vue/index.spec.js
+++ b/demos/src/GuideContent/GenerateJSON/Vue/index.spec.js
@@ -1,7 +1,36 @@
 context('/src/GuideContent/GenerateJSON/Vue/', () => {
-  before(() => {
+  beforeEach(() => {
     cy.visit('/src/GuideContent/GenerateJSON/Vue/')
   })
 
-  // TODO: Write tests
+  it('should render the content as an HTML string', () => {
+    cy.get('pre code').should('exist')
+
+    cy.get('pre code').should(
+      'contain',
+      `{
+  "type": "doc",
+  "content": [
+    {
+      "type": "paragraph",
+      "content": [
+        {
+          "type": "text",
+          "text": "Example "
+        },
+        {
+          "type": "text",
+          "marks": [
+            {
+              "type": "bold"
+            }
+          ],
+          "text": "Text"
+        }
+      ]
+    }
+  ]
+}`,
+    )
+  })
 })
diff --git a/demos/src/GuideContent/GenerateText/React/index.jsx b/demos/src/GuideContent/GenerateText/React/index.jsx
index cc4b35e121..ba95ed6b60 100644
--- a/demos/src/GuideContent/GenerateText/React/index.jsx
+++ b/demos/src/GuideContent/GenerateText/React/index.jsx
@@ -52,7 +52,7 @@ export default () => {
         blockSeparator: '\n\n',
       },
     )
-  }, [json])
+  }, [])
 
   return (
     
diff --git a/demos/src/GuideContent/GenerateText/React/index.spec.js b/demos/src/GuideContent/GenerateText/React/index.spec.js
index 91e29475d3..5e4f805a64 100644
--- a/demos/src/GuideContent/GenerateText/React/index.spec.js
+++ b/demos/src/GuideContent/GenerateText/React/index.spec.js
@@ -1,5 +1,5 @@
 context('/src/GuideContent/GenerateText/React/', () => {
-  before(() => {
+  beforeEach(() => {
     cy.visit('/src/GuideContent/GenerateText/React/')
   })
 
diff --git a/demos/src/GuideContent/GenerateText/Vue/index.spec.js b/demos/src/GuideContent/GenerateText/Vue/index.spec.js
index af2cc5edd3..e63003cce4 100644
--- a/demos/src/GuideContent/GenerateText/Vue/index.spec.js
+++ b/demos/src/GuideContent/GenerateText/Vue/index.spec.js
@@ -1,5 +1,5 @@
 context('/src/GuideContent/GenerateText/Vue/', () => {
-  before(() => {
+  beforeEach(() => {
     cy.visit('/src/GuideContent/GenerateText/Vue/')
   })
 
diff --git a/demos/src/GuideContent/GenerateText/Vue/index.vue b/demos/src/GuideContent/GenerateText/Vue/index.vue
index 73f851f0e5..6afc1c1a7c 100644
--- a/demos/src/GuideContent/GenerateText/Vue/index.vue
+++ b/demos/src/GuideContent/GenerateText/Vue/index.vue
@@ -43,16 +43,20 @@ const json = {
 export default {
   computed: {
     output() {
-      return generateText(json, [
-        Document,
-        Paragraph,
-        Text,
-        HardBreak,
-        // other extensions …
-      ], {
-        // define a custom block separator if you want to
-        blockSeparator: '\n\n',
-      })
+      return generateText(
+        json,
+        [
+          Document,
+          Paragraph,
+          Text,
+          HardBreak,
+          // other extensions …
+        ],
+        {
+          // define a custom block separator if you want to
+          blockSeparator: '\n\n',
+        },
+      )
     },
   },
 }
diff --git a/demos/src/GuideContent/ReadOnly/React/index.jsx b/demos/src/GuideContent/ReadOnly/React/index.jsx
index 095d3540c1..f14b97d097 100644
--- a/demos/src/GuideContent/ReadOnly/React/index.jsx
+++ b/demos/src/GuideContent/ReadOnly/React/index.jsx
@@ -36,12 +36,7 @@ export default () => {
     <>
       
- setEditable(event.target.checked)} - /> + setEditable(event.target.checked)} />
diff --git a/demos/src/GuideContent/ReadOnly/React/index.spec.js b/demos/src/GuideContent/ReadOnly/React/index.spec.js index c2448d7a1e..711805b5f7 100644 --- a/demos/src/GuideContent/ReadOnly/React/index.spec.js +++ b/demos/src/GuideContent/ReadOnly/React/index.spec.js @@ -1,5 +1,5 @@ context('/src/GuideContent/ReadOnly/React/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/GuideContent/ReadOnly/React/') }) @@ -16,24 +16,18 @@ context('/src/GuideContent/ReadOnly/React/', () => { cy.get('.tiptap p:first').should('not.contain', 'Edited: ') - cy - .get('.tiptap') - .invoke('attr', 'tabindex') - .should('not.exist') + cy.get('.tiptap').invoke('attr', 'tabindex').should('not.exist') }) }) it('should be editable', () => { - cy.get('.tiptap').then(([{ editor }]) => { - editor.setEditable(true) + cy.get('#editable').click() + cy.get('.tiptap').then(() => { cy.get('.tiptap').type('Edited: ') cy.get('.tiptap p:first').should('contain', 'Edited: ') - cy - .get('.tiptap') - .invoke('attr', 'tabindex') - .should('eq', '0') + cy.get('.tiptap').invoke('attr', 'tabindex').should('eq', '0') }) }) }) diff --git a/demos/src/GuideContent/ReadOnly/React/styles.scss b/demos/src/GuideContent/ReadOnly/React/styles.scss index 5d986479e7..74c06e46aa 100644 --- a/demos/src/GuideContent/ReadOnly/React/styles.scss +++ b/demos/src/GuideContent/ReadOnly/React/styles.scss @@ -5,11 +5,11 @@ } /* List styles */ - ul, + ul, ol { padding: 0 1rem; margin: 1.25rem 1rem 1.25rem 0.4rem; - + li p { margin-top: 0.25em; margin-bottom: 0.25em; @@ -17,39 +17,39 @@ } /* Heading styles */ - h1, - h2, - h3, - h4, - h5, + h1, + h2, + h3, + h4, + h5, h6 { line-height: 1.1; margin-top: 2.5rem; text-wrap: pretty; } - h1, + h1, h2 { margin-top: 3.5rem; margin-bottom: 1.5rem; } - h1 { - font-size: 1.4rem; + h1 { + font-size: 1.4rem; } - h2 { - font-size: 1.2rem; + h2 { + font-size: 1.2rem; } - h3 { - font-size: 1.1rem; + h3 { + font-size: 1.1rem; } - h4, - h5, - h6 { - font-size: 1rem; + h4, + h5, + h6 { + font-size: 1rem; } /* Code and preformatted text styles */ @@ -88,9 +88,8 @@ border-top: 1px solid var(--gray-2); margin: 2rem 0; } - - &[contenteditable="false"] { + &[contenteditable='false'] { cursor: not-allowed; opacity: 0.6; } diff --git a/demos/src/GuideContent/ReadOnly/Vue/index.spec.js b/demos/src/GuideContent/ReadOnly/Vue/index.spec.js index 0cd7e47957..c031076fa7 100644 --- a/demos/src/GuideContent/ReadOnly/Vue/index.spec.js +++ b/demos/src/GuideContent/ReadOnly/Vue/index.spec.js @@ -1,5 +1,5 @@ context('/src/GuideContent/ReadOnly/Vue/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/GuideContent/ReadOnly/Vue/') }) @@ -19,8 +19,8 @@ context('/src/GuideContent/ReadOnly/Vue/', () => { }) it('should be editable', () => { - cy.get('.tiptap').then(([{ editor }]) => { - editor.setEditable(true) + cy.get('#editable').click() + cy.get('.tiptap').then(() => { cy.get('.tiptap').type('Edited: ') cy.get('.tiptap p:first').should('contain', 'Edited: ') diff --git a/demos/src/GuideContent/ReadOnly/Vue/index.vue b/demos/src/GuideContent/ReadOnly/Vue/index.vue index d4e185d11d..77995e132f 100644 --- a/demos/src/GuideContent/ReadOnly/Vue/index.vue +++ b/demos/src/GuideContent/ReadOnly/Vue/index.vue @@ -2,7 +2,7 @@
- +
@@ -37,9 +37,7 @@ export default { If you want to check the state, you can call editor.isEditable().

`, - extensions: [ - StarterKit, - ], + extensions: [StarterKit], }) }, @@ -147,7 +145,7 @@ export default { margin: 2rem 0; } - &[contenteditable="false"] { + &[contenteditable='false'] { color: #999; opacity: 0.6; } diff --git a/demos/src/GuideContent/StaticRenderHTML/React/index.html b/demos/src/GuideContent/StaticRenderHTML/React/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/GuideContent/StaticRenderHTML/React/index.spec.js b/demos/src/GuideContent/StaticRenderHTML/React/index.spec.js new file mode 100644 index 0000000000..075f3832b1 --- /dev/null +++ b/demos/src/GuideContent/StaticRenderHTML/React/index.spec.js @@ -0,0 +1,11 @@ +context('/src/GuideContent/StaticRenderHTML/React/', () => { + beforeEach(() => { + cy.visit('/src/GuideContent/StaticRenderHTML/React/') + }) + + it('should render the content as an HTML string', () => { + cy.get('pre code').should('exist') + + cy.get('pre code').should('contain', '

Example Text

') + }) +}) diff --git a/demos/src/GuideContent/StaticRenderHTML/React/index.tsx b/demos/src/GuideContent/StaticRenderHTML/React/index.tsx new file mode 100644 index 0000000000..3cc024e095 --- /dev/null +++ b/demos/src/GuideContent/StaticRenderHTML/React/index.tsx @@ -0,0 +1,58 @@ +import Bold from '@tiptap/extension-bold' +import Document from '@tiptap/extension-document' +import Paragraph from '@tiptap/extension-paragraph' +import Text from '@tiptap/extension-text' +import { renderToHTMLString } from '@tiptap/static-renderer' +import React, { useMemo } from 'react' + +const json = { + type: 'doc', + content: [ + { + type: 'paragraph', + content: [ + { + type: 'text', + text: 'Example ', + }, + { + type: 'text', + marks: [ + { + type: 'bold', + }, + ], + text: 'Text', + }, + ], + }, + ], +} + +/** + * This example demonstrates how to render a Prosemirror Node (or JSON Content) to an HTML string. + * It will use your extensions to render the content based on each Node's/Mark's `renderHTML` method. + * This can be useful if you want to render content to HTML without having an actual editor instance. + * + * You have complete control over the rendering process. And can replace how each Node/Mark is rendered. + */ +export default () => { + const output = useMemo(() => { + return renderToHTMLString({ + content: json, + extensions: [ + Document, + Paragraph, + Text, + Bold, + // other extensions … + ], + }) + }, []) + + return ( +
+      {output}
+    
+ ) +} diff --git a/demos/src/GuideContent/StaticRenderHTML/Vue/index.html b/demos/src/GuideContent/StaticRenderHTML/Vue/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/GuideContent/StaticRenderHTML/Vue/index.spec.js b/demos/src/GuideContent/StaticRenderHTML/Vue/index.spec.js new file mode 100644 index 0000000000..34bde8cc54 --- /dev/null +++ b/demos/src/GuideContent/StaticRenderHTML/Vue/index.spec.js @@ -0,0 +1,11 @@ +context('/src/GuideContent/StaticRenderHTML/Vue/', () => { + beforeEach(() => { + cy.visit('/src/GuideContent/StaticRenderHTML/Vue/') + }) + + it('should render the content as an HTML string', () => { + cy.get('pre code').should('exist') + + cy.get('pre code').should('contain', '

Example Text

') + }) +}) diff --git a/demos/src/GuideContent/StaticRenderHTML/Vue/index.vue b/demos/src/GuideContent/StaticRenderHTML/Vue/index.vue new file mode 100644 index 0000000000..0142eb4bbb --- /dev/null +++ b/demos/src/GuideContent/StaticRenderHTML/Vue/index.vue @@ -0,0 +1,59 @@ + + + diff --git a/demos/src/GuideContent/StaticRenderReact/React/index.html b/demos/src/GuideContent/StaticRenderReact/React/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/GuideContent/StaticRenderReact/React/index.spec.js b/demos/src/GuideContent/StaticRenderReact/React/index.spec.js new file mode 100644 index 0000000000..9b7e582ffd --- /dev/null +++ b/demos/src/GuideContent/StaticRenderReact/React/index.spec.js @@ -0,0 +1,13 @@ +context('/src/GuideContent/StaticRenderReact/React/', () => { + beforeEach(() => { + cy.visit('/src/GuideContent/StaticRenderReact/React/') + }) + + it('should render the content as HTML', () => { + cy.get('p').should('exist') + cy.get('p').should('contain', 'Example') + + cy.get('p strong').should('exist') + cy.get('p strong').should('contain', 'Text') + }) +}) diff --git a/demos/src/GuideContent/StaticRenderReact/React/index.tsx b/demos/src/GuideContent/StaticRenderReact/React/index.tsx new file mode 100644 index 0000000000..7c2ea82cc5 --- /dev/null +++ b/demos/src/GuideContent/StaticRenderReact/React/index.tsx @@ -0,0 +1,54 @@ +import Bold from '@tiptap/extension-bold' +import Document from '@tiptap/extension-document' +import Paragraph from '@tiptap/extension-paragraph' +import Text from '@tiptap/extension-text' +import { renderToReactElement } from '@tiptap/static-renderer' +import React, { useMemo } from 'react' + +const json = { + type: 'doc', + content: [ + { + type: 'paragraph', + content: [ + { + type: 'text', + text: 'Example ', + }, + { + type: 'text', + marks: [ + { + type: 'bold', + }, + ], + text: 'Text', + }, + ], + }, + ], +} + +/** + * This example demonstrates how to render a Prosemirror Node (or JSON Content) to a React Element. + * It will use your extensions to render the content based on each Node's/Mark's `renderHTML` method. + * This can be useful if you want to render content to React without having an actual editor instance. + * + * You have complete control over the rendering process. And can replace how each Node/Mark is rendered. + */ +export default () => { + const output = useMemo(() => { + return renderToReactElement({ + content: json, + extensions: [ + Document, + Paragraph, + Text, + Bold, + // other extensions … + ], + }) + }, []) + + return
{output}
+} diff --git a/demos/src/GuideGettingStarted/VModel/Vue/Editor.vue b/demos/src/GuideGettingStarted/VModel/Vue/Editor.vue index ea5d31a2f8..2ee7426689 100644 --- a/demos/src/GuideGettingStarted/VModel/Vue/Editor.vue +++ b/demos/src/GuideGettingStarted/VModel/Vue/Editor.vue @@ -38,15 +38,13 @@ export default { return } - this.editor.commands.setContent(value, false) + this.editor.commands.setContent(value) }, }, mounted() { this.editor = new Editor({ - extensions: [ - StarterKit, - ], + extensions: [StarterKit], content: this.modelValue, onUpdate: () => { // HTML diff --git a/demos/src/GuideGettingStarted/VModel/Vue/index.spec.js b/demos/src/GuideGettingStarted/VModel/Vue/index.spec.js index 6a849f450f..8565a14cfa 100644 --- a/demos/src/GuideGettingStarted/VModel/Vue/index.spec.js +++ b/demos/src/GuideGettingStarted/VModel/Vue/index.spec.js @@ -1,5 +1,5 @@ context('/src/GuideGettingStarted/VModel/Vue/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/GuideGettingStarted/VModel/Vue/') }) diff --git a/demos/src/GuideMarkViews/ReactComponent/React/Component.tsx b/demos/src/GuideMarkViews/ReactComponent/React/Component.tsx new file mode 100644 index 0000000000..f63dfaa83a --- /dev/null +++ b/demos/src/GuideMarkViews/ReactComponent/React/Component.tsx @@ -0,0 +1,30 @@ +import type { MarkViewRendererProps } from '@tiptap/react' +import { MarkViewContent } from '@tiptap/react' +import React from 'react' + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export default (props: MarkViewRendererProps) => { + const [count, setCount] = React.useState(props.HTMLAttributes['data-count'] ?? 0) + + return ( + + + + + + + ) +} diff --git a/demos/src/GuideMarkViews/ReactComponent/React/Extension.ts b/demos/src/GuideMarkViews/ReactComponent/React/Extension.ts new file mode 100644 index 0000000000..f8bfb0ccb5 --- /dev/null +++ b/demos/src/GuideMarkViews/ReactComponent/React/Extension.ts @@ -0,0 +1,30 @@ +import { Mark } from '@tiptap/core' +import { ReactMarkViewRenderer } from '@tiptap/react' + +import Component from './Component.js' + +export default Mark.create({ + name: 'reactComponent', + + addAttributes() { + return { + 'data-count': { default: 0 }, + } + }, + + parseHTML() { + return [ + { + tag: 'react-component', + }, + ] + }, + + renderHTML({ HTMLAttributes }) { + return ['react-component', HTMLAttributes] + }, + + addMarkView() { + return ReactMarkViewRenderer(Component) + }, +}) diff --git a/demos/src/GuideMarkViews/ReactComponent/React/index.html b/demos/src/GuideMarkViews/ReactComponent/React/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/GuideMarkViews/ReactComponent/React/index.spec.js b/demos/src/GuideMarkViews/ReactComponent/React/index.spec.js new file mode 100644 index 0000000000..dc02ef282e --- /dev/null +++ b/demos/src/GuideMarkViews/ReactComponent/React/index.spec.js @@ -0,0 +1,46 @@ +/// + +context('/src/GuideMarkViews/ReactComponent/React/', () => { + beforeEach(() => { + cy.visit('/src/GuideMarkViews/ReactComponent/React/') + cy.get('.tiptap').then(([{ editor }]) => { + editor.commands.setContent('

Example Text

Mark View Text') + }) + cy.get('.tiptap').type('{selectall}') + }) + + it('should show the markview', () => { + cy.get('.tiptap').find('[data-test-id="mark-view"]').should('exist') + }) + + it('should show the markview content in the markview', () => { + cy.get('.tiptap').find('[data-test-id="mark-view-content-wrapper"]').should('exist') + cy.get('.tiptap').find('[data-test-id="mark-view-content-wrapper"]').should('contain', 'Mark View Text') + }) + + it('should allow clicking the button', () => { + cy.get('.tiptap').find('[data-test-id="count-button"]').should('contain', 'This button has been clicked 0 times.') + cy.get('.tiptap') + .find('[data-test-id="count-button"]') + .click() + .then(() => { + cy.get('.tiptap') + .find('[data-test-id="count-button"]') + .should('contain', 'This button has been clicked 1 times.') + }) + }) + + it('should update the attributes of the mark on button click', () => { + cy.get('.tiptap').find('[data-test-id="mark-view').should('have.attr', 'data-count', '0') + + // click on the button + cy.get('.tiptap') + .find('[data-test-id="update-attributes-button"]') + .click() + .then(() => { + requestAnimationFrame(() => { + cy.get('.tiptap').find('[data-test-id="mark-view"]').should('have.attr', 'data-count', '1') + }) + }) + }) +}) diff --git a/demos/src/GuideMarkViews/ReactComponent/React/index.tsx b/demos/src/GuideMarkViews/ReactComponent/React/index.tsx new file mode 100644 index 0000000000..9ae9ee908f --- /dev/null +++ b/demos/src/GuideMarkViews/ReactComponent/React/index.tsx @@ -0,0 +1,24 @@ +import './styles.scss' + +import { EditorContent, useEditor } from '@tiptap/react' +import StarterKit from '@tiptap/starter-kit' +import React from 'react' + +import ReactComponent from './Extension.js' + +export default () => { + const editor = useEditor({ + extensions: [StarterKit, ReactComponent], + content: ` +

+ This is still the text editor you’re used to, but enriched with node views. +

+ Sub-text +

+ Did you see that? That’s a React component. We are really living in the future. +

+ `, + }) + + return +} diff --git a/demos/src/GuideMarkViews/ReactComponent/React/styles.scss b/demos/src/GuideMarkViews/ReactComponent/React/styles.scss new file mode 100644 index 0000000000..bb941cc97b --- /dev/null +++ b/demos/src/GuideMarkViews/ReactComponent/React/styles.scss @@ -0,0 +1,121 @@ +/* Basic editor styles */ +.tiptap { + :first-child { + margin-top: 0; + } + + /* List styles */ + ul, + ol { + padding: 0 1rem; + margin: 1.25rem 1rem 1.25rem 0.4rem; + + li p { + margin-top: 0.25em; + margin-bottom: 0.25em; + } + } + + /* Heading styles */ + h1, + h2, + h3, + h4, + h5, + h6 { + line-height: 1.1; + margin-top: 2.5rem; + text-wrap: pretty; + } + + h1, + h2 { + margin-top: 3.5rem; + margin-bottom: 1.5rem; + } + + h1 { + font-size: 1.4rem; + } + + h2 { + font-size: 1.2rem; + } + + h3 { + font-size: 1.1rem; + } + + h4, + h5, + h6 { + font-size: 1rem; + } + + /* Code and preformatted text styles */ + code { + background-color: var(--purple-light); + border-radius: 0.4rem; + color: var(--black); + font-size: 0.85rem; + padding: 0.25em 0.3em; + } + + pre { + background: var(--black); + border-radius: 0.5rem; + color: var(--white); + font-family: 'JetBrainsMono', monospace; + margin: 1.5rem 0; + padding: 0.75rem 1rem; + + code { + background: none; + color: inherit; + font-size: 0.8rem; + padding: 0; + } + } + + blockquote { + border-left: 3px solid var(--gray-3); + margin: 1.5rem 0; + padding-left: 1rem; + } + + hr { + border: none; + border-top: 1px solid var(--gray-2); + margin: 2rem 0; + } + + /* React component */ + .react-component { + background-color: var(--purple-light); + border: 2px solid var(--purple); + border-radius: 0.5rem; + margin: 2rem 0; + position: relative; + + label { + background-color: var(--purple); + border-radius: 0 0 0.5rem 0; + color: var(--white); + font-size: 0.75rem; + font-weight: bold; + padding: 0.25rem 0.5rem; + position: absolute; + top: 0; + } + + .content { + margin-top: 1.5rem; + padding: 1rem; + } + } + + .mark-view-content-wrapper { + background-color: var(--gray-3); + padding: 0.25rem 0.5rem; + } +} diff --git a/demos/src/GuideMarkViews/VueComponent/Vue/Component.vue b/demos/src/GuideMarkViews/VueComponent/Vue/Component.vue new file mode 100644 index 0000000000..67bb7a1682 --- /dev/null +++ b/demos/src/GuideMarkViews/VueComponent/Vue/Component.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/demos/src/GuideMarkViews/VueComponent/Vue/Extension.ts b/demos/src/GuideMarkViews/VueComponent/Vue/Extension.ts new file mode 100644 index 0000000000..210b743f1f --- /dev/null +++ b/demos/src/GuideMarkViews/VueComponent/Vue/Extension.ts @@ -0,0 +1,30 @@ +import { Mark } from '@tiptap/core' +import { VueMarkViewRenderer } from '@tiptap/vue-3' + +import Component from './Component.vue' + +export default Mark.create({ + name: 'vueComponent', + + addAttributes() { + return { + 'data-count': { default: 0 }, + } + }, + + parseHTML() { + return [ + { + tag: 'vue-component', + }, + ] + }, + + renderHTML({ HTMLAttributes }) { + return ['vue-component', HTMLAttributes] + }, + + addMarkView() { + return VueMarkViewRenderer(Component) + }, +}) diff --git a/demos/src/GuideMarkViews/VueComponent/Vue/index.html b/demos/src/GuideMarkViews/VueComponent/Vue/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/GuideMarkViews/VueComponent/Vue/index.spec.js b/demos/src/GuideMarkViews/VueComponent/Vue/index.spec.js new file mode 100644 index 0000000000..40760a1025 --- /dev/null +++ b/demos/src/GuideMarkViews/VueComponent/Vue/index.spec.js @@ -0,0 +1,41 @@ +/// + +context('/src/GuideMarkViews/VueComponent/Vue/', () => { + beforeEach(() => { + cy.visit('/src/GuideMarkViews/VueComponent/Vue/') + cy.get('.tiptap').then(([{ editor }]) => { + editor.commands.setContent('

Example Text

Mark View Text') + }) + cy.get('.tiptap').type('{selectall}') + }) + + it('should show the markview', () => { + cy.get('.tiptap').find('[data-test-id="mark-view"]').should('exist') + }) + + it('should allow clicking the button', () => { + cy.get('.tiptap').find('[data-test-id="count-button"]').should('contain', 'This button has been clicked 0 times.') + cy.get('.tiptap') + .find('[data-test-id="count-button"]') + .click() + .then(() => { + cy.get('.tiptap') + .find('[data-test-id="count-button"]') + .should('contain', 'This button has been clicked 1 times.') + }) + }) + + it('should update the attributes of the mark on button click', () => { + cy.get('.tiptap').find('[data-test-id="mark-view').should('have.attr', 'data-count', '0') + + // click on the button + cy.get('.tiptap') + .find('[data-test-id="update-attributes-button"]') + .click() + .then(() => { + requestAnimationFrame(() => { + cy.get('.tiptap').find('[data-test-id="mark-view"]').should('have.attr', 'data-count', '1') + }) + }) + }) +}) diff --git a/demos/src/Experiments/TrailingNode/Vue/index.vue b/demos/src/GuideMarkViews/VueComponent/Vue/index.vue similarity index 81% rename from demos/src/Experiments/TrailingNode/Vue/index.vue rename to demos/src/GuideMarkViews/VueComponent/Vue/index.vue index 5576c58df8..b9e1f41d02 100644 --- a/demos/src/Experiments/TrailingNode/Vue/index.vue +++ b/demos/src/GuideMarkViews/VueComponent/Vue/index.vue @@ -1,14 +1,12 @@ + + diff --git a/demos/src/Nodes/Blockquote/React/index.jsx b/demos/src/Nodes/Blockquote/React/index.jsx index e474aba481..7af0a49c2f 100644 --- a/demos/src/Nodes/Blockquote/React/index.jsx +++ b/demos/src/Nodes/Blockquote/React/index.jsx @@ -9,12 +9,7 @@ import React from 'react' export default () => { const editor = useEditor({ - extensions: [ - Document, - Paragraph, - Text, - Blockquote, - ], + extensions: [Document, Paragraph, Text, Blockquote], content: `
Nothing is impossible, the word itself says “I’m possible!” @@ -37,10 +32,7 @@ export default () => { > Toggle blockquote - - - -
@@ -21,9 +33,8 @@ + + diff --git a/demos/src/Nodes/Document/React/index.spec.js b/demos/src/Nodes/Document/React/index.spec.js index d058c779e7..05450741f5 100644 --- a/demos/src/Nodes/Document/React/index.spec.js +++ b/demos/src/Nodes/Document/React/index.spec.js @@ -1,5 +1,5 @@ context('/src/Nodes/Document/React/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Nodes/Document/React/') }) diff --git a/demos/src/Nodes/Document/Vue/index.spec.js b/demos/src/Nodes/Document/Vue/index.spec.js index de1b748924..fcd67954f5 100644 --- a/demos/src/Nodes/Document/Vue/index.spec.js +++ b/demos/src/Nodes/Document/Vue/index.spec.js @@ -1,5 +1,5 @@ context('/src/Nodes/Document/Vue/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Nodes/Document/Vue/') }) diff --git a/demos/src/Nodes/Document/Vue/index.vue b/demos/src/Nodes/Document/Vue/index.vue index b80a42fbf0..91effce31d 100644 --- a/demos/src/Nodes/Document/Vue/index.vue +++ b/demos/src/Nodes/Document/Vue/index.vue @@ -23,11 +23,7 @@ export default { mounted() { this.editor = new Editor({ - extensions: [ - Document, - Paragraph, - Text, - ], + extensions: [Document, Paragraph, Text], content: `

The Document extension is required. Though, you can write your own implementation, e. g. to give it custom name.

`, diff --git a/demos/src/Nodes/Emoji/React/EmojiList.jsx b/demos/src/Nodes/Emoji/React/EmojiList.jsx new file mode 100644 index 0000000000..aadc6a7b6f --- /dev/null +++ b/demos/src/Nodes/Emoji/React/EmojiList.jsx @@ -0,0 +1,62 @@ +import './EmojiList.scss' + +import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'react' + +export const EmojiList = forwardRef((props, ref) => { + const [selectedIndex, setSelectedIndex] = useState(0) + + const selectItem = index => { + const item = props.items[index] + + if (item) { + props.command({ name: item.name }) + } + } + + const upHandler = () => { + setSelectedIndex((selectedIndex + props.items.length - 1) % props.items.length) + } + + const downHandler = () => { + setSelectedIndex((selectedIndex + 1) % props.items.length) + } + + const enterHandler = () => { + selectItem(selectedIndex) + } + + useEffect(() => setSelectedIndex(0), [props.items]) + + useImperativeHandle(ref, () => { + return { + onKeyDown: x => { + if (x.event.key === 'ArrowUp') { + upHandler() + return true + } + + if (x.event.key === 'ArrowDown') { + downHandler() + return true + } + + if (x.event.key === 'Enter') { + enterHandler() + return true + } + + return false + }, + } + }, [upHandler, downHandler, enterHandler]) + + return ( +
+ {props.items.map((item, index) => ( + + ))} +
+ ) +}) diff --git a/demos/src/Nodes/Emoji/React/EmojiList.scss b/demos/src/Nodes/Emoji/React/EmojiList.scss new file mode 100644 index 0000000000..a873e9e897 --- /dev/null +++ b/demos/src/Nodes/Emoji/React/EmojiList.scss @@ -0,0 +1,36 @@ +/* Dropdown menu */ +.dropdown-menu { + background: var(--white); + border: 1px solid var(--gray-1); + border-radius: 0.7rem; + box-shadow: var(--shadow); + display: flex; + flex-direction: column; + gap: 0.1rem; + overflow: auto; + padding: 0.4rem; + position: relative; + + button { + align-items: center; + background-color: transparent; + display: flex; + gap: 0.25rem; + text-align: left; + width: 100%; + + &:hover, + &:hover.is-selected { + background-color: var(--gray-3); + } + + &.is-selected { + background-color: var(--gray-2); + } + + img { + height: 1em; + width: 1em; + } + } +} diff --git a/demos/src/Nodes/Emoji/React/index.html b/demos/src/Nodes/Emoji/React/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/Nodes/Emoji/React/index.jsx b/demos/src/Nodes/Emoji/React/index.jsx new file mode 100644 index 0000000000..18b70dfb8a --- /dev/null +++ b/demos/src/Nodes/Emoji/React/index.jsx @@ -0,0 +1,61 @@ +import './styles.scss' + +import Emoji, { gitHubEmojis } from '@tiptap/extension-emoji' +import { EditorContent, useEditor } from '@tiptap/react' +import StarterKit from '@tiptap/starter-kit' +import React from 'react' + +import suggestion from './suggestion.js' + +export default () => { + const editor = useEditor({ + extensions: [ + StarterKit, + Emoji.configure({ + emojis: gitHubEmojis, + enableEmoticons: true, + suggestion, + }), + ], + content: ` +

+ These + are + some + emojis + rendered + as + inline + nodes. +

+

+ Type : to open the autocomplete. +

+

+ Even + custom + emojis + are + supported. +

+

+ And unsupported emojis (without a fallback image) are rendered as just the shortcode . +

+
In code blocks all emojis are rendered as plain text. 👩‍💻👨‍💻
+

+ There is also support for emoticons. Try typing <3. +

+ `, + }) + + return ( + <> +
+
+ +
+
+ + + ) +} diff --git a/demos/src/Nodes/Emoji/React/index.spec.js b/demos/src/Nodes/Emoji/React/index.spec.js new file mode 100644 index 0000000000..a8be64f4c4 --- /dev/null +++ b/demos/src/Nodes/Emoji/React/index.spec.js @@ -0,0 +1,36 @@ +context('/src/Nodes/Emoji/React/', () => { + beforeEach(() => { + cy.visit('/src/Nodes/Emoji/React/') + }) + + beforeEach(() => { + cy.get('.tiptap').then(([{ editor }]) => { + editor.commands.setContent('

') + }) + cy.get('.tiptap').click() + }) + + it('insert :smile: via typing', () => { + cy.get('.tiptap').type(':smile:') + // after typing the shortcode the emoji should be rendered as a node + cy.get('.tiptap').find('[data-type="emoji"][data-name="smile"]').should('exist') + }) + + it('insert button inserts an emoji node', () => { + cy.get('button').contains('Insert ⚡').click() + cy.get('.tiptap').find('[data-type="emoji"][data-name="zap"]').should('exist') + }) + + it('pasting a URL containing :x: does not convert the shortcode', () => { + const url = 'https://example-url.com/:x:/sub' + cy.get('.tiptap').paste({ paste: url }) + + cy.get('.tiptap').contains(url) + cy.get('.tiptap').find('[data-type="emoji"]').should('not.exist') + }) + + it('pasting a standalone shortcode converts to an emoji node', () => { + cy.get('.tiptap').paste({ paste: ':smile:' }) + cy.get('.tiptap').find('[data-type="emoji"]').should('exist') + }) +}) diff --git a/demos/src/Nodes/Emoji/React/styles.scss b/demos/src/Nodes/Emoji/React/styles.scss new file mode 100644 index 0000000000..7508761213 --- /dev/null +++ b/demos/src/Nodes/Emoji/React/styles.scss @@ -0,0 +1,14 @@ +/* Basic editor styles */ +.tiptap { + :first-child { + margin-top: 0; + } + + // Emoji extension styles + [data-type='emoji'] { + img { + height: 1em; + width: 1em; + } + } +} diff --git a/demos/src/Nodes/Emoji/React/suggestion.js b/demos/src/Nodes/Emoji/React/suggestion.js new file mode 100644 index 0000000000..259d159d8f --- /dev/null +++ b/demos/src/Nodes/Emoji/React/suggestion.js @@ -0,0 +1,80 @@ +import { computePosition } from '@floating-ui/dom' +import { ReactRenderer } from '@tiptap/react' + +import { EmojiList } from './EmojiList.jsx' + +export default { + items: ({ editor, query }) => { + return editor.storage.emoji.emojis + .filter(({ shortcodes, tags }) => { + return ( + shortcodes.find(shortcode => shortcode.startsWith(query.toLowerCase())) || + tags.find(tag => tag.startsWith(query.toLowerCase())) + ) + }) + .slice(0, 5) + }, + + allowSpaces: false, + + render: () => { + let component + + function repositionComponent(clientRect) { + if (!component || !component.element) { + return + } + + const virtualElement = { + getBoundingClientRect() { + return clientRect + }, + } + + computePosition(virtualElement, component.element, { + placement: 'bottom-start', + }).then(pos => { + Object.assign(component.element.style, { + left: `${pos.x}px`, + top: `${pos.y}px`, + position: pos.strategy === 'fixed' ? 'fixed' : 'absolute', + }) + }) + } + + return { + onStart: props => { + component = new ReactRenderer(EmojiList, { + props, + editor: props.editor, + }) + + document.body.appendChild(component.element) + repositionComponent(props.clientRect()) + }, + + onUpdate(props) { + component.updateProps(props) + repositionComponent(props.clientRect()) + }, + + onKeyDown(props) { + if (props.event.key === 'Escape') { + document.body.removeChild(component.element) + component.destroy() + + return true + } + + return component.ref?.onKeyDown(props) + }, + + onExit() { + if (document.body.contains(component.element)) { + document.body.removeChild(component.element) + } + component.destroy() + }, + } + }, +} diff --git a/demos/src/Nodes/Emoji/Vue/EmojiList.vue b/demos/src/Nodes/Emoji/Vue/EmojiList.vue new file mode 100644 index 0000000000..0121bb5208 --- /dev/null +++ b/demos/src/Nodes/Emoji/Vue/EmojiList.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/demos/src/Nodes/Emoji/Vue/index.html b/demos/src/Nodes/Emoji/Vue/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/Nodes/Emoji/Vue/index.vue b/demos/src/Nodes/Emoji/Vue/index.vue new file mode 100644 index 0000000000..859322be08 --- /dev/null +++ b/demos/src/Nodes/Emoji/Vue/index.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/demos/src/Nodes/Emoji/Vue/suggestion.js b/demos/src/Nodes/Emoji/Vue/suggestion.js new file mode 100644 index 0000000000..b7c6f52a12 --- /dev/null +++ b/demos/src/Nodes/Emoji/Vue/suggestion.js @@ -0,0 +1,78 @@ +import { computePosition } from '@floating-ui/dom' +import { VueRenderer } from '@tiptap/vue-3' + +import EmojiList from './EmojiList.vue' + +export default { + items: ({ editor, query }) => { + return editor.storage.emoji.emojis + .filter(({ shortcodes, tags }) => { + return ( + shortcodes.find(shortcode => shortcode.startsWith(query.toLowerCase())) || + tags.find(tag => tag.startsWith(query.toLowerCase())) + ) + }) + .slice(0, 5) + }, + + render: () => { + let component + + function repositionComponent(clientRect) { + if (!component || !component.element) { + return + } + + const virtualElement = { + getBoundingClientRect() { + return clientRect + }, + } + + computePosition(virtualElement, component.element, { + placement: 'bottom-start', + }).then(pos => { + Object.assign(component.element.style, { + left: `${pos.x}px`, + top: `${pos.y}px`, + position: pos.strategy === 'fixed' ? 'fixed' : 'absolute', + }) + }) + } + + return { + onStart: props => { + component = new VueRenderer(EmojiList, { + props, + editor: props.editor, + }) + + document.body.appendChild(component.element) + repositionComponent(props.clientRect()) + }, + + onUpdate(props) { + component.updateProps(props) + repositionComponent(props.clientRect()) + }, + + onKeyDown(props) { + if (props.event.key === 'Escape') { + document.body.removeChild(component.element) + component.destroy() + + return true + } + + return component.ref?.onKeyDown(props) + }, + + onExit() { + if (document.body.contains(component.element)) { + document.body.removeChild(component.element) + } + component.destroy() + }, + } + }, +} diff --git a/demos/src/Nodes/HardBreak/React/index.spec.js b/demos/src/Nodes/HardBreak/React/index.spec.js index c08eb60a5f..7dcc598c1a 100644 --- a/demos/src/Nodes/HardBreak/React/index.spec.js +++ b/demos/src/Nodes/HardBreak/React/index.spec.js @@ -1,5 +1,5 @@ context('/src/Nodes/HardBreak/React/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Nodes/HardBreak/React/') }) diff --git a/demos/src/Nodes/HardBreak/Vue/index.spec.js b/demos/src/Nodes/HardBreak/Vue/index.spec.js index e6a98f1387..eb05a096d7 100644 --- a/demos/src/Nodes/HardBreak/Vue/index.spec.js +++ b/demos/src/Nodes/HardBreak/Vue/index.spec.js @@ -1,5 +1,5 @@ context('/src/Nodes/HardBreak/Vue/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Nodes/HardBreak/Vue/') }) @@ -24,35 +24,26 @@ context('/src/Nodes/HardBreak/Vue/', () => { }) it('the button should add a line break', () => { - cy.get('.tiptap br') - .should('not.exist') + cy.get('.tiptap br').should('not.exist') - cy.get('button:first') - .click() + cy.get('button:first').click() - cy.get('.tiptap br') - .should('exist') + cy.get('.tiptap br').should('exist') }) it('the default keyboard shortcut should add a line break', () => { - cy.get('.tiptap br') - .should('not.exist') + cy.get('.tiptap br').should('not.exist') - cy.get('.tiptap') - .trigger('keydown', { shiftKey: true, key: 'Enter' }) + cy.get('.tiptap').trigger('keydown', { shiftKey: true, key: 'Enter' }) - cy.get('.tiptap br') - .should('exist') + cy.get('.tiptap br').should('exist') }) it('the alternative keyboard shortcut should add a line break', () => { - cy.get('.tiptap br') - .should('not.exist') + cy.get('.tiptap br').should('not.exist') - cy.get('.tiptap') - .trigger('keydown', { modKey: true, key: 'Enter' }) + cy.get('.tiptap').trigger('keydown', { modKey: true, key: 'Enter' }) - cy.get('.tiptap br') - .should('exist') + cy.get('.tiptap br').should('exist') }) }) diff --git a/demos/src/Nodes/HardBreak/Vue/index.vue b/demos/src/Nodes/HardBreak/Vue/index.vue index 5a2b0f981e..c37852194c 100644 --- a/demos/src/Nodes/HardBreak/Vue/index.vue +++ b/demos/src/Nodes/HardBreak/Vue/index.vue @@ -2,9 +2,7 @@
- +
@@ -31,12 +29,7 @@ export default { mounted() { this.editor = new Editor({ - extensions: [ - Document, - Paragraph, - Text, - HardBreak, - ], + extensions: [Document, Paragraph, Text, HardBreak], content: `

This
diff --git a/demos/src/Nodes/Heading/React/index.spec.js b/demos/src/Nodes/Heading/React/index.spec.js index 58dcf9f186..2f18053c77 100644 --- a/demos/src/Nodes/Heading/React/index.spec.js +++ b/demos/src/Nodes/Heading/React/index.spec.js @@ -1,5 +1,5 @@ context('/src/Nodes/Heading/React/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Nodes/Heading/React/') }) diff --git a/demos/src/Nodes/Heading/React/styles.scss b/demos/src/Nodes/Heading/React/styles.scss index ec1db90574..4655151f75 100644 --- a/demos/src/Nodes/Heading/React/styles.scss +++ b/demos/src/Nodes/Heading/React/styles.scss @@ -5,38 +5,38 @@ } /* Heading styles */ - h1, - h2, - h3, - h4, - h5, + h1, + h2, + h3, + h4, + h5, h6 { line-height: 1.1; margin-top: 2.5rem; text-wrap: pretty; } - h1, + h1, h2 { margin-top: 3.5rem; margin-bottom: 1.5rem; } - h1 { - font-size: 1.4rem; + h1 { + font-size: 1.4rem; } - h2 { - font-size: 1.2rem; + h2 { + font-size: 1.2rem; } - h3 { - font-size: 1.1rem; + h3 { + font-size: 1.1rem; } - h4, - h5, - h6 { - font-size: 1rem; + h4, + h5, + h6 { + font-size: 1rem; } } diff --git a/demos/src/Nodes/Heading/Vue/index.spec.js b/demos/src/Nodes/Heading/Vue/index.spec.js index 2d49d09898..b17ce5efc1 100644 --- a/demos/src/Nodes/Heading/Vue/index.spec.js +++ b/demos/src/Nodes/Heading/Vue/index.spec.js @@ -1,5 +1,5 @@ context('/src/Nodes/Heading/Vue/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Nodes/Heading/Vue/') }) @@ -10,11 +10,7 @@ context('/src/Nodes/Heading/Vue/', () => { }) }) - const headings = [ - '

Example Text

', - '

Example Text

', - '

Example Text

', - ] + const headings = ['

Example Text

', '

Example Text

', '

Example Text

'] headings.forEach(html => { it(`should parse headings correctly (${html})`, () => { @@ -33,57 +29,39 @@ context('/src/Nodes/Heading/Vue/', () => { }) it('the button should make the selected line a h1', () => { - cy.get('.tiptap h1') - .should('not.exist') + cy.get('.tiptap h1').should('not.exist') - cy.get('button:nth-child(1)') - .click() + cy.get('button:nth-child(1)').click() - cy.get('.tiptap') - .find('h1') - .should('contain', 'Example Text') + cy.get('.tiptap').find('h1').should('contain', 'Example Text') }) it('the button should make the selected line a h2', () => { - cy.get('.tiptap h2') - .should('not.exist') + cy.get('.tiptap h2').should('not.exist') - cy.get('button:nth-child(2)') - .click() + cy.get('button:nth-child(2)').click() - cy.get('.tiptap') - .find('h2') - .should('contain', 'Example Text') + cy.get('.tiptap').find('h2').should('contain', 'Example Text') }) it('the button should make the selected line a h3', () => { - cy.get('.tiptap h3') - .should('not.exist') + cy.get('.tiptap h3').should('not.exist') - cy.get('button:nth-child(3)') - .click() + cy.get('button:nth-child(3)').click() - cy.get('.tiptap') - .find('h3') - .should('contain', 'Example Text') + cy.get('.tiptap').find('h3').should('contain', 'Example Text') }) it('the button should toggle the heading', () => { - cy.get('.tiptap h1') - .should('not.exist') + cy.get('.tiptap h1').should('not.exist') - cy.get('button:nth-child(1)') - .click() + cy.get('button:nth-child(1)').click() - cy.get('.tiptap') - .find('h1') - .should('contain', 'Example Text') + cy.get('.tiptap').find('h1').should('contain', 'Example Text') - cy.get('button:nth-child(1)') - .click() + cy.get('button:nth-child(1)').click() - cy.get('.tiptap h1') - .should('not.exist') + cy.get('.tiptap h1').should('not.exist') }) it('should make the paragraph a h1 keyboard shortcut is pressed', () => { @@ -112,10 +90,7 @@ context('/src/Nodes/Heading/Vue/', () => { editor.commands.clearContent() }) - cy.get('.tiptap') - .type('# Headline') - .find('h1') - .should('contain', 'Headline') + cy.get('.tiptap').type('# Headline').find('h1').should('contain', 'Headline') }) it('should make a h2 from the default markdown shortcut', () => { @@ -123,10 +98,7 @@ context('/src/Nodes/Heading/Vue/', () => { editor.commands.clearContent() }) - cy.get('.tiptap') - .type('## Headline') - .find('h2') - .should('contain', 'Headline') + cy.get('.tiptap').type('## Headline').find('h2').should('contain', 'Headline') }) it('should make a h3 from the default markdown shortcut', () => { @@ -134,9 +106,6 @@ context('/src/Nodes/Heading/Vue/', () => { editor.commands.clearContent() }) - cy.get('.tiptap') - .type('### Headline') - .find('h3') - .should('contain', 'Headline') + cy.get('.tiptap').type('### Headline').find('h3').should('contain', 'Headline') }) }) diff --git a/demos/src/Nodes/Heading/Vue/index.vue b/demos/src/Nodes/Heading/Vue/index.vue index 227b546b8f..aa4aa6db52 100644 --- a/demos/src/Nodes/Heading/Vue/index.vue +++ b/demos/src/Nodes/Heading/Vue/index.vue @@ -2,13 +2,22 @@
- - -
diff --git a/demos/src/Nodes/HorizontalRule/React/index.jsx b/demos/src/Nodes/HorizontalRule/React/index.jsx index a7cbed7c1e..627a9a91c4 100644 --- a/demos/src/Nodes/HorizontalRule/React/index.jsx +++ b/demos/src/Nodes/HorizontalRule/React/index.jsx @@ -27,9 +27,7 @@ export default () => { <>
- +
diff --git a/demos/src/Nodes/HorizontalRule/React/index.spec.js b/demos/src/Nodes/HorizontalRule/React/index.spec.js index 051182cef2..30478b311c 100644 --- a/demos/src/Nodes/HorizontalRule/React/index.spec.js +++ b/demos/src/Nodes/HorizontalRule/React/index.spec.js @@ -1,5 +1,5 @@ context('/src/Nodes/HorizontalRule/React/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Nodes/HorizontalRule/React/') }) @@ -71,9 +71,7 @@ context('/src/Nodes/HorizontalRule/React/', () => { editor.commands.setTextSelection({ from: 13, to: 15 }) editor.commands.setHorizontalRule() - expect(editor.getHTML()).to.eq( - '

Example Text


Example Text

', - ) + expect(editor.getHTML()).to.eq('

Example Text


Example Text

') }) }) }) diff --git a/demos/src/Nodes/HorizontalRule/React/styles.scss b/demos/src/Nodes/HorizontalRule/React/styles.scss index a0198be1b1..4f89805bc1 100644 --- a/demos/src/Nodes/HorizontalRule/React/styles.scss +++ b/demos/src/Nodes/HorizontalRule/React/styles.scss @@ -13,4 +13,4 @@ border-top: 1px solid var(--purple); } } -} \ No newline at end of file +} diff --git a/demos/src/Nodes/HorizontalRule/Vue/index.spec.js b/demos/src/Nodes/HorizontalRule/Vue/index.spec.js index 69d1707b96..2a495a6ba5 100644 --- a/demos/src/Nodes/HorizontalRule/Vue/index.spec.js +++ b/demos/src/Nodes/HorizontalRule/Vue/index.spec.js @@ -1,5 +1,5 @@ context('/src/Nodes/HorizontalRule/Vue/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Nodes/HorizontalRule/Vue/') }) @@ -24,28 +24,22 @@ context('/src/Nodes/HorizontalRule/Vue/', () => { }) it('the button should add a horizontal rule', () => { - cy.get('.tiptap hr') - .should('not.exist') + cy.get('.tiptap hr').should('not.exist') - cy.get('button:first') - .click() + cy.get('button:first').click() - cy.get('.tiptap hr') - .should('exist') + cy.get('.tiptap hr').should('exist') }) it('the default markdown shortcut should add a horizontal rule', () => { cy.get('.tiptap').then(([{ editor }]) => { editor.commands.clearContent() - cy.get('.tiptap hr') - .should('not.exist') + cy.get('.tiptap hr').should('not.exist') - cy.get('.tiptap') - .type('---') + cy.get('.tiptap').type('---') - cy.get('.tiptap hr') - .should('exist') + cy.get('.tiptap hr').should('exist') }) }) @@ -53,14 +47,11 @@ context('/src/Nodes/HorizontalRule/Vue/', () => { cy.get('.tiptap').then(([{ editor }]) => { editor.commands.clearContent() - cy.get('.tiptap hr') - .should('not.exist') + cy.get('.tiptap hr').should('not.exist') - cy.get('.tiptap') - .type('___ ') + cy.get('.tiptap').type('___ ') - cy.get('.tiptap hr') - .should('exist') + cy.get('.tiptap hr').should('exist') }) }) @@ -80,9 +71,7 @@ context('/src/Nodes/HorizontalRule/Vue/', () => { editor.commands.setTextSelection({ from: 13, to: 15 }) editor.commands.setHorizontalRule() - expect(editor.getHTML()).to.eq( - '

Example Text


Example Text

', - ) + expect(editor.getHTML()).to.eq('

Example Text


Example Text

') }) }) }) diff --git a/demos/src/Nodes/HorizontalRule/Vue/index.vue b/demos/src/Nodes/HorizontalRule/Vue/index.vue index 190b1fc5b1..caa7b7da2e 100644 --- a/demos/src/Nodes/HorizontalRule/Vue/index.vue +++ b/demos/src/Nodes/HorizontalRule/Vue/index.vue @@ -2,9 +2,7 @@
- +
@@ -31,12 +29,7 @@ export default { mounted() { this.editor = new Editor({ - extensions: [ - Document, - Paragraph, - Text, - HorizontalRule, - ], + extensions: [Document, Paragraph, Text, HorizontalRule], content: `

This is a paragraph.


@@ -53,7 +46,8 @@ export default { } - diff --git a/demos/src/Nodes/Youtube/React/index.jsx b/demos/src/Nodes/Youtube/React/index.jsx index f6bd4e9620..ec2ad3d96c 100644 --- a/demos/src/Nodes/Youtube/React/index.jsx +++ b/demos/src/Nodes/Youtube/React/index.jsx @@ -48,7 +48,9 @@ const MenuBar = ({ editor }) => { value={height} onChange={event => setHeight(event.target.value)} /> - +
) diff --git a/demos/src/Nodes/Youtube/React/index.spec.js b/demos/src/Nodes/Youtube/React/index.spec.js index d928621cc0..ed27b0b533 100644 --- a/demos/src/Nodes/Youtube/React/index.spec.js +++ b/demos/src/Nodes/Youtube/React/index.spec.js @@ -1,5 +1,5 @@ context('/src/Nodes/Youtube/React/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Nodes/Youtube/React/') }) @@ -9,7 +9,7 @@ context('/src/Nodes/Youtube/React/', () => { it('adds a video', () => { cy.window().then(win => { - cy.stub(win, 'prompt', () => 'https://music.youtube.com/watch?v=hBp4dgE7Bho&feature=share') + cy.stub(win, 'prompt').returns('https://music.youtube.com/watch?v=hBp4dgE7Bho&feature=share') cy.get('#add').eq(0).click() cy.get('.tiptap div[data-youtube-video] iframe') .should('have.length', 1) @@ -27,11 +27,12 @@ context('/src/Nodes/Youtube/React/', () => { it('adds a video with 320 width and 240 height', () => { cy.window().then(win => { - cy.stub(win, 'prompt', () => 'https://music.youtube.com/watch?v=hBp4dgE7Bho&feature=share') + cy.stub(win, 'prompt').returns('https://music.youtube.com/watch?v=hBp4dgE7Bho&feature=share') cy.get('#width').type('{selectall}{backspace}320') cy.get('#height').type('{selectall}{backspace}240') cy.get('#add').eq(0).click() - cy.get('.tiptap div[data-youtube-video] iframe').should('have.length', 1) + cy.get('.tiptap div[data-youtube-video] iframe') + .should('have.length', 1) .should('have.css', 'width', '320px') .should('have.css', 'height', '240px') .invoke('attr', 'src') @@ -48,15 +49,9 @@ context('/src/Nodes/Youtube/React/', () => { it('replaces a video', () => { cy.window().then(win => { - let runs = 0 - - cy.stub(win, 'prompt', () => { - runs += 1 - if (runs === 1) { - return 'https://music.youtube.com/watch?v=hBp4dgE7Bho&feature=share' - } - return 'https://music.youtube.com/watch?v=wRakoMYVHm8' - }) + const promptStub = cy.stub(win, 'prompt') + promptStub.onFirstCall().returns('https://music.youtube.com/watch?v=hBp4dgE7Bho&feature=share') + promptStub.onSecondCall().returns('https://music.youtube.com/watch?v=wRakoMYVHm8') cy.get('#add').eq(0).click() cy.get('.tiptap div[data-youtube-video] iframe') @@ -71,8 +66,7 @@ context('/src/Nodes/Youtube/React/', () => { expect(url.searchParams.get('rel')).to.eq('1') }) - cy.get('.tiptap div[data-youtube-video] iframe') - .click() + cy.get('.tiptap div[data-youtube-video] iframe').click() cy.get('#add').eq(0).click() diff --git a/demos/src/Nodes/Youtube/Vue/index.spec.js b/demos/src/Nodes/Youtube/Vue/index.spec.js index af6b2fedaf..5a3a350b90 100644 --- a/demos/src/Nodes/Youtube/Vue/index.spec.js +++ b/demos/src/Nodes/Youtube/Vue/index.spec.js @@ -1,5 +1,5 @@ context('/src/Nodes/Youtube/Vue/', () => { - before(() => { + beforeEach(() => { cy.visit('/src/Nodes/Youtube/Vue/') }) @@ -9,7 +9,7 @@ context('/src/Nodes/Youtube/Vue/', () => { it('adds a video', () => { cy.window().then(win => { - cy.stub(win, 'prompt', () => 'https://music.youtube.com/watch?v=hBp4dgE7Bho&feature=share') + cy.stub(win, 'prompt').returns('https://music.youtube.com/watch?v=hBp4dgE7Bho&feature=share') cy.get('#add').eq(0).click() cy.get('.tiptap div[data-youtube-video] iframe') .should('have.length', 1) @@ -27,11 +27,12 @@ context('/src/Nodes/Youtube/Vue/', () => { it('adds a video with 320 width and 240 height', () => { cy.window().then(win => { - cy.stub(win, 'prompt', () => 'https://music.youtube.com/watch?v=hBp4dgE7Bho&feature=share') + cy.stub(win, 'prompt').returns('https://music.youtube.com/watch?v=hBp4dgE7Bho&feature=share') cy.get('#width').type('{selectall}{backspace}320') cy.get('#height').type('{selectall}{backspace}240') cy.get('#add').eq(0).click() - cy.get('.tiptap div[data-youtube-video] iframe').should('have.length', 1) + cy.get('.tiptap div[data-youtube-video] iframe') + .should('have.length', 1) .should('have.css', 'width', '320px') .should('have.css', 'height', '240px') .invoke('attr', 'src') @@ -48,15 +49,9 @@ context('/src/Nodes/Youtube/Vue/', () => { it('replaces a video', () => { cy.window().then(win => { - let runs = 0 - - cy.stub(win, 'prompt', () => { - runs += 1 - if (runs === 1) { - return 'https://music.youtube.com/watch?v=hBp4dgE7Bho&feature=share' - } - return 'https://music.youtube.com/watch?v=wRakoMYVHm8' - }) + const promptStub = cy.stub(win, 'prompt') + promptStub.onFirstCall().returns('https://music.youtube.com/watch?v=hBp4dgE7Bho&feature=share') + promptStub.onSecondCall().returns('https://music.youtube.com/watch?v=wRakoMYVHm8') cy.get('#add').eq(0).click() cy.get('.tiptap div[data-youtube-video] iframe') @@ -71,8 +66,7 @@ context('/src/Nodes/Youtube/Vue/', () => { expect(url.searchParams.get('rel')).to.eq('1') }) - cy.get('.tiptap div[data-youtube-video] iframe') - .click() + cy.get('.tiptap div[data-youtube-video] iframe').click() cy.get('#add').eq(0).click() diff --git a/demos/src/Nodes/Youtube/Vue/index.vue b/demos/src/Nodes/Youtube/Vue/index.vue index e7b146292a..f44858454f 100644 --- a/demos/src/Nodes/Youtube/Vue/index.vue +++ b/demos/src/Nodes/Youtube/Vue/index.vue @@ -2,25 +2,9 @@
- - - + + +
diff --git a/demos/src/Overview/Installation/Vue/index.vue b/demos/src/Overview/Installation/Vue/index.vue index 997a864d26..0b4dfa9928 100644 --- a/demos/src/Overview/Installation/Vue/index.vue +++ b/demos/src/Overview/Installation/Vue/index.vue @@ -20,9 +20,7 @@ export default { mounted() { this.editor = new Editor({ content: '

Hello World! 🌎️

', - extensions: [ - StarterKit, - ], + extensions: [StarterKit], }) }, diff --git a/demos/src/Tutorials/1-1-textarea/React/Note.tsx b/demos/src/Tutorials/1-1-textarea/React/Note.tsx index 6bca53bd26..368b678aa0 100644 --- a/demos/src/Tutorials/1-1-textarea/React/Note.tsx +++ b/demos/src/Tutorials/1-1-textarea/React/Note.tsx @@ -1,11 +1,9 @@ import React, { useState } from 'react' -import { TNote } from './types.js' +import type { TNote } from './types.js' export default ({ note }: { note: TNote }) => { const [modelValue, setModelValue] = useState(note.content) - return ( - - ) + return } diff --git a/demos/src/Tutorials/1-1-textarea/React/index.tsx b/demos/src/Tutorials/1-1-textarea/React/index.tsx index f90613a0c0..ab06a56a48 100644 --- a/demos/src/Tutorials/1-1-textarea/React/index.tsx +++ b/demos/src/Tutorials/1-1-textarea/React/index.tsx @@ -3,7 +3,7 @@ import './styles.scss' import React from 'react' import Note from './Note.jsx' -import { TNote } from './types.js' +import type { TNote } from './types.js' const notes: TNote[] = [ { @@ -19,7 +19,9 @@ const notes: TNote[] = [ export default () => { return ( <> - {notes.map(note => )} + {notes.map(note => ( + + ))} ) } diff --git a/demos/src/Tutorials/1-1-textarea/React/styles.scss b/demos/src/Tutorials/1-1-textarea/React/styles.scss index a6e586fa87..99f7e4f4d0 100644 --- a/demos/src/Tutorials/1-1-textarea/React/styles.scss +++ b/demos/src/Tutorials/1-1-textarea/React/styles.scss @@ -14,9 +14,9 @@ textarea, font-size: 0.875rem; font-weight: 500; line-height: 1.15; - margin: 0; + margin: 0; padding: 0.375rem 0.625rem; - transition: all .2s cubic-bezier(0.65,0.05,0.36,1); + transition: all 0.2s cubic-bezier(0.65, 0.05, 0.36, 1); &:hover { border-color: var(--gray-4); @@ -36,7 +36,7 @@ textarea, color: var(--gray-4); } - &:focus-visible, + &:focus-visible, &:focus { border-color: var(--purple); outline: none; diff --git a/demos/src/Tutorials/1-1-textarea/React/types.ts b/demos/src/Tutorials/1-1-textarea/React/types.ts index 9d53cf5755..b6318bd98b 100644 --- a/demos/src/Tutorials/1-1-textarea/React/types.ts +++ b/demos/src/Tutorials/1-1-textarea/React/types.ts @@ -1,4 +1,4 @@ export type TNote = { - id: string; - content: string; -}; + id: string + content: string +} diff --git a/demos/src/Tutorials/1-1-textarea/Vue/Note.vue b/demos/src/Tutorials/1-1-textarea/Vue/Note.vue index 82c4fba433..20a16f1059 100644 --- a/demos/src/Tutorials/1-1-textarea/Vue/Note.vue +++ b/demos/src/Tutorials/1-1-textarea/Vue/Note.vue @@ -1,17 +1,15 @@