The BlockSuite v0.11.0 release is now available! With 317 PRs landed and 6 new contributors, this version marks a milestone in our journey: evolving from a proprietary editor to a general-purpose editing framework.
BlockSuite originated as an editor designed to meet the needs of the AFFiNE knowledge base, which is why, for a long time, it provided a default EditorContainer
that included both document editing and whiteboard functionalities. Early updates also focused heavily on specific features for AFFiNE products.
However, during the development of BlockSuite, we've built a range of front-end infrastructures from the ground up, spanning from rich text editing to whiteboard rendering. This version introduces extensive engineering refactoring and modular layering, resulting in the birth of a new, universal editing framework.
Traditionally, developing a stable rich text editor could take years of challenging work. But the evolution of BlockSuite has far outpaced this. We believe our work stems from embracing a new architectural pattern called document-centric, which simplifies the complex architecture of traditional editors by natively building the data layer in the editor with CRDT, thereby providing a more efficient development experience.
Key changes in BlockSuite 0.11.0 for developers include:
- The new
@blocksuite/presets
package, which splits the independently usableDocEditor
andEdgelessEditor
, among others. - Distinct structuring of the BlockSuite framework layer, including atomic concepts like
Editor
,Block
,Fragment
,Widget
, and definitive guides on how they combine. The currentDocEditor
andEdgelessEditor
are based on this headless framework layer. - Based on BlockSuite headless, the accompanying front-end framework has been switched from lit to atomico for the experimental editor abed. This proves the feasibility of using the BlockSuite framework independently of specific front-end frameworks. We're also embracing React, Vue, and more diverse front-end frameworks, and there's more to come in terms of framework adaptation!
- Completely rewritten BlockSuite framework tutorial and architectural exploration documentation, also available in Chinese for convenience.
We've also switched to the new home page blocksuite.io, welcome to give it a spin!
The establishment of the framework layer is just the first step in BlockSuite's longer-term vision. The current stable framework layer modules and APIs are still akin to the more low-level, headless part of tools like ProseMirror. Plans are already in place for more out-of-the-box preset support. Stay tuned!
Notable Product Features in 0.11
- Support for Linked Page Previews (#5813): Added the basic functionality to support linked page previews in the Table of Contents (TOC), enhancing user navigation experience.
- Enhanced Bookmark Functionality (#5636): Improved the bookmark block to appear directly at the top level of the edgeless canvas, simplifying the process of pasting elements into the whiteboard.
- Consistent Dragging Behavior (#5613): Improved the consistency of dragging behavior, support dragging paragraphs and images outside of the note block.
- Frame Sidebar Support (#5584): Added support for frame sidebars fragment, which brings more intuitive control in edgeless editor.
- Frame Navigator Optimization (#5498): Optimized the frame navigator, enhancing user navigation efficiency and experience.
- New Table of Contents (TOC) (#5539): Introduced a new TOC fragment, enhancing document organization and navigation capabilities.
- Embed View for Certain Attachment Types (#5475): Added embed view support for certain attachment types, enhancing the presentation and interactivity of multimedia content.
Notable Framework Enhancements in 0.11
- Canvas Content Interleaving Based on
LayerManager
(#5347): Enabled canvas content interleaving with DOM based onLayerManager
, enhancing the editor's visual representation and flexibility. - Support for Multiple Editor Instances (#5878): Implemented support for multiple editor instances, increasing the flexibility and scalability of the editing environment.
- Vitest Browser Test Runner (#5536): Added the DOM-based Vitest browser test runner, making easier for writing integration tests.
- Support for Custom Inline Nodes (#5909): Introduced the custom
InlineSpec
feature, enhancing flexibility in text editing, especially for advanced content editing like inline LaTeX. - Surface Elements API (#5874): Introduced a new surface elements API, avoid raw
Y.Map
manipulations. - Replaced Export Manager (#5934): Fully removed the last part of legacy
ContentParser
and introduced a new export manager based on snapshot and adapter mechanisms, greatly enhancing support for third-party formats and scalability. - Persisting Editing Session State (#5804): Implemented the temporary storage of user toolbar options and other temporary states through
SessionStorage
, enhancing usability in frequent switching scenarios. - Multi-Instance Selection Enhancement (#5852): Refactored the surface selection mechanism to support multiple instances, making the
SurfaceSelection
inEdgelessEditor
more aligned withDocEditor
. - Optimized Zoom In/Out Performance (#5791): Performance optimization for zoom in and out functionalities, improving response speed and smoothness.
- Inline Editor Renaming (#5671): Renamed
VirgoEditor
toInlineEditor
to more accurately reflect its functionality. - Stash and Pop for Reactive Proxy (#5627): Introduced
stash
andpop
functionalities for reactive proxies, making state management of local non-collaborative fields easier. - Splitting Editor Container into Sub-Editors (#5612): Divided the
EditorContainer
into multiple sub-editors, improving manageability and modularization. - Editor and Presets Package Reorg (#5570): Renamed
@blocksuite/editor
to@blocksuite/presets
to more accurately reflect its function and purpose. - Embed Block Helper (#5518): Added an
createEmbedBlock
helper API in@blocksuite/blocks
, simplifying the creation and management of embedded content.
Detailed Bugfixes
- fix: update fonts cdn @Flrande (#5499)
- fix: flaky test @Saul-Mirone (#5555)
- fix: types for this @lawvs (#5557)
- fix: embed portal regex @Saul-Mirone (#5573)
- fix: format-bar custom elements @doouding (#5254)
- fix: update reference id in group and connector in replaceIdMiddleware @regischen (#5616)
- fix: incorrect page tag popup position on zooming @kimhyeonju (#5457)
- fix: update format bar styles @lawvs (#5651)
- fix: snapshot empty @Saul-Mirone (#5692)
- fix: doc site sandbox config @doodlewind (#5701)
- fix: style configuration of the document’s code-sandbox @zqran (#5706)
- fix: toast font @lawvs (#5711)
- fix: transformer won't work for nested props @Saul-Mirone (#5733)
- fix: style for embed github block @Saul-Mirone (#5737)
- fix: eslint ignore patterns @AyushAgrawal-A2 (#5735)
- fix: markdown table view format workaround @nawbc (#5726)
- fix: flaky test @AyushAgrawal-A2 (#5743)
- fix: model should emit change after setting value @Saul-Mirone (#5768)
- fix: element handling with
getPageByElement
in doc & edgeless @AyushAgrawal-A2 (#5771) - fix: date-fns import @doodlewind (#5777)
- fix: replace
\r
for windows in clipboard @zqran (#5764) - fix: forward specs to editor @lawvs (#5809)
- fix: update CFW url for querying url data from bookmarks and make it support external overrides @Flrande (#5811)
- fix: drag handle ui bugs @AyushAgrawal-A2 (#5815)
- fix: drag handle throttle @AyushAgrawal-A2 (#5823)
- fix: bookmark og image size @Flrande (#5827)
- fix: replace id issue for page ref @pengx17 (#5883)
- fix: should not reload bookmark when title is not empty @Flrande (#5882)
- fix: complete draghandle fixme @AyushAgrawal-A2 (#5895)
- fix: store exports @Saul-Mirone (#5902)
- fix: export more types from store @Saul-Mirone (#5903)
- fix: should not relay on business logic in block std @Saul-Mirone (#5913)
- fix: drag handle error on using standalone host @doodlewind (#5914)
- fix: doc dragging area in multiple editors @Saul-Mirone (#5915)
- fix: export png error and rich text format confusion @donteatfriedrice (#5945)
- fix(database): table view progress filtering @sseooh (#5454)
- fix(database): edit view modal position is wrong @zzj3720 (#5522)
- fix(database): column repeated setting to text type causes an error @zzj3720 (#5540)
- fix(database): detail panel position auto update @zzj3720 (#5675)
- fix(database): date cell cannot display date picker again @zqran (#5846)
- fix(edgeless): unable to render image in surface-ref @doouding (#5488)
- fix(edgeless): consider containerOffset when auto-panning @donteatfriedrice (#5492)
- fix(edgeless): reset note observer @regischen (#5494)
- fix(edgeless): copy-as-png not work for nested frame @regischen (#5495)
- fix(edgeless): image keep aspect ratio when resize @regischen (#5505)
- fix(edgeless): export surface-service @regischen (#5509)
- fix(edgeless): incorrect bound size filter @regischen (#5516)
- fix(edgeless): image inside frame cannot be copied as png @donteatfriedrice (#5519)
- fix(edgeless): add edgeless blocks in adapters @fourdim (#5532)
- fix(edgeless): remove redundant template @regischen (#5535)
- fix(edgeless): copy as png for frame and image @regischen (#5546)
- fix(edgeless): no connector after refresh page @devlzl (#5553)
- fix(edgeless): define toggle switch error @donteatfriedrice (#5571)
- fix(edgeless): fix undestroyed note render bug @regischen (#5575)
- fix(edgeless): dom not update after frame update @regischen (#5587)
- fix(edgeless): connector in group copy bug @regischen (#5589)
- fix(edgeless): note duplicate issue & expose service api @regischen (#5591)
- fix(edgeless): delete group without children @regischen (#5595)
- fix(edgeless): move grouped content together on dragging @regischen (#5597)
- fix(edgeless): group element snapshot @regischen (#5594)
- fix(edgeless): partially migrate to new clipboard @regischen (#5606)
- fix(edgeless): group multi alignment @regischen (#5620)
- fix(edgeless): surface canvas resize effect @doouding (#5629)
- fix(edgeless): generate new ids for images and frames in advance @regischen (#5631)
- fix(edgeless): default mode after exiting presentation @regischen (#5643)
- fix(edgeless): update
z-index
style @zqran (#5652) - fix(edgeless): undo/redo after inserting template @doouding (#5655)
- fix(edgeless): panel lacks border radius @Flrande (#5665)
- fix(edgeless): slicer in offseted container @doouding (#5666)
- fix(edgeless): ui styling issues @regischen (#5667)
- fix(edgeless): ui styling issues @regischen (#5679)
- fix(edgeless): indexed canvas does not render when switch to edgeless mode @doouding (#5686)
- fix(edgeless): sort in layer manager init method @doouding (#5696)
- fix(edgeless): fix blur toolbar @Yukiniro (#5698)
- fix(edgeless): limit getNextBlock/getPrevBlock to same note @AyushAgrawal-A2 (#5417)
- fix(edgeless): copy note with style @regischen (#5714)
- fix(edgeless): title editor with max height @regischen (#5717)
- fix(edgeless): fix the inconsistency between the editing and non-editing rendering @Yukiniro (#5721)
- fix(edgeless): undo/redo on image dragging @AyushAgrawal-A2 (#5750)
- fix(edgeless): wrong display in canvas editor when setting text-align to right @Flrande (#5752)
- fix(edgeless): switch to unified clipboard logic @regischen (#5755)
- fix(edgeless): option drag from the mouse point @regischen (#5762)
- fix(edgeless): wrong size display when dragging after changing the font size @donteatfriedrice (#5759)
- fix(edgeless): wrong connector start endpoint style when rotation @donteatfriedrice (#5773)
- fix(edgeless): insert bookmark in note block in edgeless mode will trigger unexpected error @Flrande (#5769)
- fix(edgeless): expand frame click area @regischen (#5780)
- fix(edgeless): share page should be able to hide remote cursor @doouding (#5785)
- fix(edgeless): top level block drag handle position @donteatfriedrice (#5807)
- fix(edgeless): remove preview in frame order menu @regischen (#5825)
- fix(edgeless): frame title @doouding (#5828)
- fix(edgeless): correct overlay position after #5791 @AyushAgrawal-A2 (#5834)
- fix(edgeless): modify blackground default value @regischen (#5856)
- fix(edgeless): canvas text inconsistency between view and editing state @AyushAgrawal-A2 (#5851)
- fix(edgeless): console error on block delete @AyushAgrawal-A2 (#5898)
- fix(edgeless): note background lost when copy as png @donteatfriedrice (#5907)
- fix(edgeless): inserted template should generate new index @doouding (#5921)
- fix(edgeless): change paragraph block placeholder text color @AyushAgrawal-A2 (#5929)
- fix(edgeless): auto-complete panel position @donteatfriedrice (#5936)
- fix(edgeless): add radius property to shape last props schema @regischen (#5951)
- fix(edgeless): clear selection on pressing esc @water-in-stone (#5958)
- fix(inline): do not render when root element is disconnected @Flrande (#5858)
- fix(page): autoscroll during native selection @AyushAgrawal-A2 (#5460)
- fix(page): error when quickly clicking actions in image block @lawvs (#5500)
- fix(page): update todo tests @fourdim (#5534)
- fix(page): format bar flickering @ddeonseo (#5506)
- fix(page): use modified version of remarkGfm @fourdim (#5541)
- fix(page): missing props on note blocks @fourdim (#5542)
- fix(page): deprecate subpage in affine text attributes @fourdim (#5559)
- fix(page): support
shift
in markdown @AliceLanniste (#5588) - fix(page): selection should be able to go through iframe @lawvs (#5580)
- fix(page): should not consider block inside surface-ref when using drag handle @donteatfriedrice (#5603)
- fix(page): bookmark caption background style @doodlewind (#5611)
- fix(page): paste pure images from clipboard @fourdim (#5656)
- fix(page): image loading/failed status @AyushAgrawal-A2 (#5648)
- fix(page): reset list index for non-list in between @doodlewind (#5689)
- fix(page): init setup for standalone doc editor @doodlewind (#5695)
- fix(page): trim end when using slice snapshot @fourdim (#5704)
- fix(page): html image pasting @fourdim (#5729)
- fix(page): caption input unexpectedly disappears @lawvs (#5767)
- fix(page): incorrectly delete behavior when trying to delete reference node @Flrande (#5774)
- fix(page): code block copy error @Saul-Mirone (#5786)
- fix(page): limit shift of side panel toolbar @lawvs (#5795)
- fix(page): parse html tag as plain text @fourdim (#5796)
- fix(page): mock timezone in tests @fourdim (#5802)
- fix(page): merge empty pages in notion database @fourdim (#5803)
- fix(page): autoscroll with input inlineRange @AyushAgrawal-A2 (#5830)
- fix(page): attachment file drop position @AyushAgrawal-A2 (#5833)
- fix(page): unable to add trailing paragraph on click in windows @zqran (#5842)
- fix(page): doc-dragging-area and overlay positions after page scroll @AyushAgrawal-A2 (#5853)
- fix(page): reorder priority for images @fourdim (#5854)
- fix(page): support image proxy in transformers @fourdim (#5855)
- fix(page): set language to be merged when pasting @fourdim (#5868)
- fix(page): unexpected line wrap in code block @lawvs (#5891)
- fix(page): tag value retention @umar23faiz (#5892)
- fix(page): onCut should delete blocks between fromElement and toElement @donteatfriedrice (#5930)
- fix(page): show whitespace when wrap code @lawvs (#5932)
- fix(page): add clipboard fallbacks @fourdim (#5944)
- fix(page): update heading font weight @AyushAgrawal-A2 (#5946)
- fix(playground): wait editor updateComplete to query edgeless page @donteatfriedrice (#5630)
- fix(playground): editor host undefined @donteatfriedrice (#5926)
- fix(presets): render frame preview incorrectly when switch between pages @donteatfriedrice (#5672)
- fix(presets): should only reset selection in the same edgeless @donteatfriedrice (#5678)
- fix(presets): update disposables when editor change @donteatfriedrice (#5682)
- fix(presets): frame portal preview improvement @donteatfriedrice (#5730)
- fix(presets): consider viewport offset @donteatfriedrice (#5734)
- fix(presets): should have only one highlight mask @donteatfriedrice (#5784)
- fix(presets): update TOC pointer style @donteatfriedrice (#5821)
- fix(presets): remove console.log @zzj3720 (#5844)
- fix(presets): emit in tsconfig @fourdim (#5869)
- fix(presets): llama2 chat image support @zzj3720 (#5923)
- fix(store):
model.created
not emit @Flrande (#5537) - fix(store): avoid unstable local transaction @Saul-Mirone (#5556)
- fix(store): await on snapshot slice conversion @fourdim (#5818)
New Contributors
- @sseooh made their first contribution in #5454
- @ddeonseo made their first contribution in #5508
- @gauravruhela07 made their first contribution in #5615
- @nawbc made their first contribution in #5728
- @antriksh-9 made their first contribution in #5766
- @umar23faiz made their first contribution in #5892
Full Changelog: v0.10.0...v0.11.0