Skip to content
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

feature: v0.10: tables, custom inline content, custom styles, better copy / paste handling #426

Merged
merged 27 commits into from
Dec 4, 2023

Conversation

YousefED
Copy link
Collaborator

@YousefED YousefED commented Nov 29, 2023

This PR is a major overhaul of BlockNote and brings in several new features.

The following PRs are part of this:

(note that these PRs have been merged into each other, so the code change view will not be ideal)

Features

Some nice new stuff now possible with BlockNote!

Tables

ezgif-2-fd6034a112

Closes #194

Custom Inline Content and Custom Styles

Until now, it was only possible to create your own custom Blocks. Now, you can also create custom Styles and Inline Content. Styles are markup that can be enabled on text (think bold, italic, etc.). Custom Inline Content can be used for "inline blocks", for example for Mentions.

Closes #267

Better copy paste handling

The copy / paste and Blocks to / from Markdown / HTML system has been overhauled and should be more robust. Copying and pasting of custom blocks is now also supported!

Closes #221 #69 #361 #381 #282 #226 #249

Breaking changes:

Custom Block API

If you're using Custom Blocks (createReactBlockSpec), there are 3 major changes:

  • The "schema" of your block and the "implementation" are now separated
  • The <InlineContent /> element has been removed in favor of contentRef
  • Use content: "inline" | "none" instead of containsInlineContent: boolean

Old (deprecated) code example:

const ImageBlock = createReactBlockSpec({
  type: "image",
  propSchema: {
    src: {
      default: "https://via.placeholder.com/1000",
    },
  },
  containsInlineContent: true,
  render: ({ block }) => (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
      }}>
      <img
        style={{
          width: "100%",
        }}
        src={block.props.src}
        alt={"Image"}
        contentEditable={false}
      />
      <InlineContent />
    </div>
  ),
});

New version:

const ImageBlock = createReactBlockSpec({
  type: "image",
  propSchema: {
    src: {
      default: "https://via.placeholder.com/1000",
    },
  },
  content: "inline"
}, {
  render: ({ block, contentRef }) => (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
      }}>
      <img
        style={{
          width: "100%",
        }}
        src={block.props.src}
        alt={"Image"}
        contentEditable={false}
      />
      <span ref={contentRef} />
    </div>
  ),
});

Additionally, blockSchemas are now blockSpecs, so to pass in the blocks that you want the editor to use:

const editor = useBlockNote({
  blockSpecs: {
    ...defaultBlockSpecs,
    image: ImageBlock
  }
});

In functions that still require a BlockSchema type, you can use the getBlockSchemaFromSpecs function, e.g. for getDefaultReactSlashMenuItems:

const blockSpecs = {
  ...defaultBlockSpecs,
  image: ImageBlock
}

const blockSchema = getBlockSchemaFromSpecs(blockSpecs);

const editor = useBlockNote({
  blockSpecs: blockSpecs,
  slashMenuItems: {
    ...getDefaultReactSlashMenuItems(blockSchema),
    insertImageBlock
  }
});

Naming of export / parse functions

To better indicate the conversion to / from Markdown and HTML is lossy, the following functions have been renamed:

  • editor.blocksToHTML -> editor.blocksToHTMLLossy
  • editor.HTMLToBlocks -> editor.tryParseHTMLToBlocks
  • editor.blocksToMarkdown -> editor.blocksToMarkdownLossy
  • editor.markdownToBlocks -> editor.tryParseMarkdownToBlocks

Vanilla (non-react) constructor usage

Instead of new BlockNoteEditor(...), now use BlockNoteEditor.create(...)

TODO (before merging)

TODO (separately, can be done after merging)

Docs:

  • Maybe it makes sense to revisit docs + examples + playground completely, but at least:
  • Add custom styles and inline content to docs
  • Add Table to docs
  • Add serialization related information to docs
  • Figure out what to do with theming now that the CSS classes are accessible

Tests:

  • Add test for this Commit
  • Add more tests for tables (e2e + unit)
  • @YousefED : Add "typescript tests" that enforce strict typing of schemas
  • Add tests for creating custom blocks / IC / Styles that can parse "external HTML"
  • Add copy / paste tests with examples from copying from gdocs / notion / other websites
  • Add playwright test for custom blocks / ic / styles? (and keyhandling)

Other:

  • Create an API for mentions (similar to slash menu)
  • lowprio: make sure "external" HTML is sanitized from unnecessary classes & attributes?
  • Now we've deprecated CSS Modules, we might want to document the possibility of styling via CSS directly

* Added serialization for vanilla custom blocks

* Added serialization for React custom blocks

* Cleaned up serializer implementation - no longer uses function override

* Revert "Cleaned up serializer implementation - no longer uses function override"

This reverts commit b4f3fb6.

* Removed comment

* Added ability to set custom serialization and parse functions for custom blocks (parse still WIP)

* Fixed build and most runtime issues

* Added `react-dom` dependency

* Added PoC copy/paste handling

* Small changes & fixes

* Added serialization tests

* Changed copy/paste implementation

* Small fix

* Implemented PR feedback

* Converted styles from modules to regular CSS

* Implemented PR feedback

* Updated serialization test snapshots

* Updated serialization tests to use BlockNote API

* Commented out custom block parsing code (out of scope for this PR)

* Improved `nodeToBlock` typing

* Small fixes

* Fixed `destroy` function not getting passed to TipTap node view

* Updated comment regarding clipboard issues

* Major restructure of copy/paste code

* Reduced code duplication for HTML serializer & exporter

* Implemented PR feedback & cleaned up CSS class names

* Updated serialization unit test snapshots

* Changed `DOMOutputSpec` implementation for default blocks

* Fixed some CSS issues

* Implemented PR feedback

* Reverted `nodeToBlock` typing

* Made external HTML conversions no longer `async` and fixed Firefox clipboard reading

* Fixed image test issues and small changes

* Fixed remaining image test issues

* Updated serialization unit test snapshots

* Excluded `formatConversions` test

* Fixed HTML export for custom blocks with inline content

* Fixed duplicate `blockContainer` attributes getting added to custom blocks' `blockContent` nodes from color default props and changed `toExternalHTML` typing for React custom blocks

* Added React serialization unit tests and extra vanilla tests

* Updated image e2e snapshots

* Small e2e test fix

* Added comments

* Fixed error when copying only nested blocks

* refactor types for blocks (#412)

* refactor types for blocks

* remove unused comment

* fix test

* run tests on all branches

* fix build

* change BlockFromBlockConfig to Block

* simplify customblockconfig

* rename BlockImplementation to TiptapBlockImplementation

* fix build

* add comment

* feat: tables (#413)

* fix table types

* add tablecontent

* clean BNUpdateBlock

* add partial inline content

* add contentNodeToTableContent

* first draft of tablehandles

* implement table functions

* fix styles

* fix imports

* create separate TableExtension

* improve types

* test some types

* Fixed setting selection for table blocks

* Fixed backspace deleting table if at start of cell

* small code fixes

* Implemented PR feedback

* Improved table row/column drag & drop UX

* Fixed table menus moving around, drag indicator flakiness, menu z-index issues, and drag preview

* Implemented PR feedback

* Implemented PR feedback

* Fixed drag handles sometimes not showing

* Fixed scrolling behaviour

* Small fixes

* Fixed table handles UI

* Fixed remaining UX/UI issues

* Removed redundant state from table handles plugin

* Implemented table drag & drop logic

* Added table enter handling

* Small fix

* feat: custom styles and custom inline content (#418)

* wip custom styles

* fix

* fix tests

* simplify PartialInlineContent

* custom inline content

* clean nodeconversions test

* streamline tests

* update tests

* move schema files

* add custom style test

* inline content + tests

* misc

* clean imports

* fix react tests

* add react nodeconversions tests

* move tests and add test for ReactStyles

* fix react tests

* basis of new examples

* add react examples

* fix bug

* misc fixes

* wip

* clean

* small cleanup

* add comments

* move funcs

* fix tests

* address PR feedback

* fix inline content types

* feat: HTML paste handling (#422)

* refactor parse

* fix parse-divsc

* add test case

* add extra test (that should be fixed)

* readd markdown functions

* fix tests

* remove unused file

* remove comments

* add comment

* nested list handling

* add todos

* added comment

* use refs for blocks (#424)

* use refs for blocks

* update react htmlConversion test

* Custom inline content and styles commands/copy & paste fixes (#425)

* Fixed commands and internal copy/paste for inline content

* Fixed internal copy/paste for styles

* Small cleanup

* fix some tests

---------

Co-authored-by: yousefed <yousefdardiry@gmail.com>

---------

Co-authored-by: Matthew Lipski <50169049+matthewlipski@users.noreply.github.com>

* use processSync

---------

Co-authored-by: Matthew Lipski <50169049+matthewlipski@users.noreply.github.com>

* fix build

---------

Co-authored-by: Matthew Lipski <50169049+matthewlipski@users.noreply.github.com>

---------

Co-authored-by: Matthew Lipski <matthewlipski@gmail.com>
Co-authored-by: Matthew Lipski <50169049+matthewlipski@users.noreply.github.com>

---------

Co-authored-by: Matthew Lipski <matthewlipski@gmail.com>
Co-authored-by: Matthew Lipski <50169049+matthewlipski@users.noreply.github.com>

---------

Co-authored-by: Yousef <yousefdardiry@gmail.com>
Copy link

vercel bot commented Nov 29, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
blocknote-website ✅ Ready (Inspect) Visit Preview Dec 4, 2023 5:01pm

@YousefED YousefED changed the title feat: Custom block serialization (#257) feature: tables, custom inline content, custom styles, better copy / paste handling Nov 29, 2023
@YousefED YousefED changed the title feature: tables, custom inline content, custom styles, better copy / paste handling feature: v0.10: tables, custom inline content, custom styles, better copy / paste handling Nov 29, 2023
Copy link
Collaborator

@matthewlipski matthewlipski left a comment

Choose a reason for hiding this comment

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

Looks good! Reviewed changes from #422

* Fixed parsing error for styles/inline content where `dom` was the same as `contentDOM`

* Updated react snapshots
@YousefED
Copy link
Collaborator Author

review Inline Content selection

Clicking a react mention results in a "hidden cursor" and selection stays the same. This is different from e.g.: https://embed.tiptap.dev/src/nodes/mention/react/

The reason the selection is different from the tiptap example is that we're using a NodeView for React inline content, and TipTap's implementation of stopEvent and ignoreMutation blocks the selection changes / click propagation. It's fixable, but atm I don't think it's super blocking.

Might be better to fix if at some point we move away from tiptap, or if a critical reason comes up
(note to self): I tested it by comparing a "vanilla" inline content mention with the react version. The vanilla version works ok, the react doesn't (because the node view blocks some things)

* Added playgrounds for vanilla blocks, React blocks, and vanilla inline content

* fix renderHTML error

* clean examples

---------

Co-authored-by: yousefed <yousefdardiry@gmail.com>
* update docs

* add markdown tests

* remove unused file

* add missing space to mention tests
…435)

* Fixed parsing error for styles/inline content where `dom` was the same as `contentDOM`

* Updated react snapshots

* Blocked backspace at start of custom editable inline content

* add comment

---------

Co-authored-by: yousefed <yousefdardiry@gmail.com>
* Added playground for vanilla styles and added simple image block

* Fixed imports to make examples standalone
* remove lodash

* fix
* refactor directory structure

* rename

* fix import/no-cycle lint

* rename dirs

* fix build

* clean css imports
…:TypeCellOS/BlockNote into refactor/tables-customelements-copypaste
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.

Custom InlineContent types Custom blocks: copy & paste, markdown, html Tables support ?
2 participants