Skip to content

Extension, Mark, and Node classes allow functions for creation #6301

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: next
Choose a base branch
from

Conversation

bdbch
Copy link
Member

@bdbch bdbch commented Apr 25, 2025

Changes Overview

This pull request enhances the flexibility of the create and extend methods in the Extension, Mark, and Node classes by allowing configuration objects to be provided as functions. It also improves code readability by adding detailed comments and JSDoc annotations.

Enhancements to create methods:

  • Updated the create method in the Extension class to accept either a configuration object or a function that returns a configuration object. Added JSDoc annotations for better documentation. (packages/core/src/Extension.ts, packages/core/src/Extension.tsL18-R27)
  • Applied the same enhancement to the create method in the Mark class, allowing for functional configuration and adding comments for clarity. (packages/core/src/Mark.ts, packages/core/src/Mark.tsL149-R156)
  • Similarly updated the create method in the Node class to support functional configuration and added JSDoc annotations. (packages/core/src/Node.ts, packages/core/src/Node.tsL343-R350)

Enhancements to extend methods:

  • Modified the extend method in the Extension class to handle functional configurations, improving flexibility. (packages/core/src/Extension.ts, packages/core/src/Extension.tsL30-R41)
  • Updated the extend methods in both the Mark and Node classes to support functional configurations, maintaining consistency across the codebase. (packages/core/src/Mark.ts, [1]; packages/core/src/Node.ts, [2]

This change allows developers to create extensions like this:

const MyCustomNode = Node.create(() => {
  // this encapsulated scope can be used for extension internal utility functions, variables and more

  return {
    name: 'my-custom-node',
    content: 'block+',
    // ... and your further configuration
  }
})

Checklist

  • I have created a changeset 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.

@bdbch bdbch requested a review from Copilot April 25, 2025 17:39
Copy link

changeset-bot bot commented Apr 25, 2025

🦋 Changeset detected

Latest commit: 7863bf6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 57 packages
Name Type
@tiptap/core Major
@tiptap/extension-blockquote Major
@tiptap/extension-bold Major
@tiptap/extension-bubble-menu Major
@tiptap/extension-code-block-lowlight Major
@tiptap/extension-code-block Major
@tiptap/extension-code Major
@tiptap/extension-collaboration-caret Major
@tiptap/extension-collaboration Major
@tiptap/extension-document Major
@tiptap/extension-floating-menu Major
@tiptap/extension-hard-break Major
@tiptap/extension-heading Major
@tiptap/extension-highlight Major
@tiptap/extension-horizontal-rule Major
@tiptap/extension-image Major
@tiptap/extension-italic Major
@tiptap/extension-link Major
@tiptap/extension-list Major
@tiptap/extension-mention Major
@tiptap/extension-paragraph Major
@tiptap/extension-strike Major
@tiptap/extension-subscript Major
@tiptap/extension-superscript Major
@tiptap/extension-table Major
@tiptap/extension-text-align Major
@tiptap/extension-text-style Major
@tiptap/extension-text Major
@tiptap/extension-typography Major
@tiptap/extension-underline Major
@tiptap/extension-youtube Major
@tiptap/extensions Major
@tiptap/html Major
@tiptap/react Major
@tiptap/starter-kit Major
@tiptap/static-renderer Major
@tiptap/suggestion Major
@tiptap/vue-2 Major
@tiptap/vue-3 Major
@tiptap/extension-bullet-list Major
@tiptap/extension-ordered-list Major
@tiptap/extension-list-item Major
@tiptap/extension-list-keymap Major
@tiptap/extension-task-item Major
@tiptap/extension-task-list Major
@tiptap/extension-table-cell Major
@tiptap/extension-table-header Major
@tiptap/extension-table-row Major
@tiptap/extension-color Major
@tiptap/extension-font-family Major
@tiptap/extension-character-count Major
@tiptap/extension-dropcursor Major
@tiptap/extension-focus Major
@tiptap/extension-gapcursor Major
@tiptap/extension-history Major
@tiptap/extension-placeholder Major
@tiptap/pm Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@bdbch bdbch self-assigned this Apr 25, 2025
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds flexibility by allowing the create and extend methods in the Extension, Mark, and Node classes to accept either a configuration object or a function that returns a configuration object. It also improves code documentation through additional JSDoc comments and changeset updates.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
packages/core/src/Node.ts Updated create and extend methods to resolve configuration functions and added corresponding comments.
packages/core/src/Mark.ts Revised create and extend methods for functional configuration support and added JSDoc annotations.
packages/core/src/Extension.ts Updated create and extend methods to handle configuration functions and enhanced documentation.
.changeset/silly-plants-sin.md Added a changeset file describing the functional configuration support in extension creation.

Copy link

netlify bot commented Apr 25, 2025

Deploy Preview for tiptap-embed ready!

Name Link
🔨 Latest commit b3cab43
🔍 Latest deploy log https://app.netlify.com/sites/tiptap-embed/deploys/680c1ae74e89240008628875
😎 Deploy Preview https://deploy-preview-6301--tiptap-embed.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

pkg-pr-new bot commented Apr 25, 2025

Open in StackBlitz

@tiptap/core

npm i https://pkg.pr.new/@tiptap/core@6301

@tiptap/extension-blockquote

npm i https://pkg.pr.new/@tiptap/extension-blockquote@6301

@tiptap/extension-bubble-menu

npm i https://pkg.pr.new/@tiptap/extension-bubble-menu@6301

@tiptap/extension-bullet-list

npm i https://pkg.pr.new/@tiptap/extension-bullet-list@6301

@tiptap/extension-bold

npm i https://pkg.pr.new/@tiptap/extension-bold@6301

@tiptap/extension-code

npm i https://pkg.pr.new/@tiptap/extension-code@6301

@tiptap/extension-code-block

npm i https://pkg.pr.new/@tiptap/extension-code-block@6301

@tiptap/extension-code-block-lowlight

npm i https://pkg.pr.new/@tiptap/extension-code-block-lowlight@6301

@tiptap/extension-collaboration

npm i https://pkg.pr.new/@tiptap/extension-collaboration@6301

@tiptap/extension-collaboration-caret

npm i https://pkg.pr.new/@tiptap/extension-collaboration-caret@6301

@tiptap/extension-color

npm i https://pkg.pr.new/@tiptap/extension-color@6301

@tiptap/extension-document

npm i https://pkg.pr.new/@tiptap/extension-document@6301

@tiptap/extension-floating-menu

npm i https://pkg.pr.new/@tiptap/extension-floating-menu@6301

@tiptap/extension-font-family

npm i https://pkg.pr.new/@tiptap/extension-font-family@6301

@tiptap/extension-hard-break

npm i https://pkg.pr.new/@tiptap/extension-hard-break@6301

@tiptap/extension-heading

npm i https://pkg.pr.new/@tiptap/extension-heading@6301

@tiptap/extension-highlight

npm i https://pkg.pr.new/@tiptap/extension-highlight@6301

@tiptap/extension-horizontal-rule

npm i https://pkg.pr.new/@tiptap/extension-horizontal-rule@6301

@tiptap/extension-image

npm i https://pkg.pr.new/@tiptap/extension-image@6301

@tiptap/extension-italic

npm i https://pkg.pr.new/@tiptap/extension-italic@6301

@tiptap/extension-link

npm i https://pkg.pr.new/@tiptap/extension-link@6301

@tiptap/extension-list

npm i https://pkg.pr.new/@tiptap/extension-list@6301

@tiptap/extension-mention

npm i https://pkg.pr.new/@tiptap/extension-mention@6301

@tiptap/extension-ordered-list

npm i https://pkg.pr.new/@tiptap/extension-ordered-list@6301

@tiptap/extension-paragraph

npm i https://pkg.pr.new/@tiptap/extension-paragraph@6301

@tiptap/extension-strike

npm i https://pkg.pr.new/@tiptap/extension-strike@6301

@tiptap/extension-subscript

npm i https://pkg.pr.new/@tiptap/extension-subscript@6301

@tiptap/extension-superscript

npm i https://pkg.pr.new/@tiptap/extension-superscript@6301

@tiptap/extension-table

npm i https://pkg.pr.new/@tiptap/extension-table@6301

@tiptap/extension-text

npm i https://pkg.pr.new/@tiptap/extension-text@6301

@tiptap/extension-text-align

npm i https://pkg.pr.new/@tiptap/extension-text-align@6301

@tiptap/extension-text-style

npm i https://pkg.pr.new/@tiptap/extension-text-style@6301

@tiptap/extension-typography

npm i https://pkg.pr.new/@tiptap/extension-typography@6301

@tiptap/extension-underline

npm i https://pkg.pr.new/@tiptap/extension-underline@6301

@tiptap/extension-youtube

npm i https://pkg.pr.new/@tiptap/extension-youtube@6301

@tiptap/extensions

npm i https://pkg.pr.new/@tiptap/extensions@6301

@tiptap/html

npm i https://pkg.pr.new/@tiptap/html@6301

@tiptap/pm

npm i https://pkg.pr.new/@tiptap/pm@6301

@tiptap/react

npm i https://pkg.pr.new/@tiptap/react@6301

@tiptap/starter-kit

npm i https://pkg.pr.new/@tiptap/starter-kit@6301

@tiptap/static-renderer

npm i https://pkg.pr.new/@tiptap/static-renderer@6301

@tiptap/suggestion

npm i https://pkg.pr.new/@tiptap/suggestion@6301

@tiptap/vue-2

npm i https://pkg.pr.new/@tiptap/vue-2@6301

@tiptap/vue-3

npm i https://pkg.pr.new/@tiptap/vue-3@6301

commit: b3cab43

@bdbch bdbch changed the title feat: Extension, Mark, and Node classes allow functions for creation Extension, Mark, and Node classes allow functions for creation Apr 25, 2025
@bdbch
Copy link
Member Author

bdbch commented Apr 25, 2025

Added the documentation for this new option here:
ueberdosis/tiptap-docs#176

Copy link
Contributor

@arnaugomez arnaugomez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea. Before we merge, I'd like to point out that this solution does have some limitations. It's not possible to access the extension options and storage from the method. So the amount of helper functions, variables and methods you can initialize there is fairly limited. Most of them, you will need to initialize in the onBeforeCreate lifecycle method, where you have access to the editor state, extension options and storage (via the this object).

So, although this initializer function is a good step forward, I think the developer ergonomics can still be improved.

Perhaps a successful outcome would be to:

  • Be able to define an internal storage object of the extension, which includes helper functions that are not exposed externally.
  • Make the internal storage straightforward to initialize/update.

@bdbch
Copy link
Member Author

bdbch commented Apr 30, 2025

I like the idea. Before we merge, I'd like to point out that this solution does have some limitations. It's not possible to access the extension options and storage from the method. So the amount of helper functions, variables and methods you can initialize there is fairly limited. Most of them, you will need to initialize in the onBeforeCreate lifecycle method, where you have access to the editor state, extension options and storage (via the this object).

So, although this initializer function is a good step forward, I think the developer ergonomics can still be improved.

Perhaps a successful outcome would be to:

* Be able to define an internal storage object of the extension, which includes helper functions that are not exposed externally.

* Make the internal storage straightforward to initialize/update.

The problem with accessing storage in that callback is that the logic is happening before any extension is even registered to the editor (and therefore no storages to access).

I think it would still be possible to access storage in functions defined in the Create callback - you'd basically pass through storage values as arguments in your normal event lifecycles and other extension related configuration option.

const MyExtension = Extension.create(() => {
  const initialName = 'Jane Doe'

  function sayHello(name) {
    console.log(name)
  }

  // writing into storage wouldn't really work here - but you could split up logic into smaller chunks of methods that you could use below
  function createInitials(name) {
    return name.split(' ')
      .map(s => s[0].toUpperCase())
      .join('')
  }

  return {
    name: 'myExtension',

    addStorage() {
      name: initialName,
      initials: createInitials(initialName),
    },
    
    onUpdate() {
      sayHello(this.storage.name)
    },
  }
})

To me those are two separated things.

  1. The creation callback function - A closure that can be used to organize logic that your extension will reuse later
  2. The extension itself - The extension after being created via the ExtensionManager - which will at that point have inputRules, storage, options, etc.

Both are separated to me, 2 can reuse logic from 1 but 1 can't access 2s state because it can't assume it before anything is created yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants