Lexicons

Nick The Sick March 28, 2026
Source
This post is in reaction to @pfrazee.com here: https://bsky.app/profile/pfrazee.com/post/3mfd4onkpkk2o It is extensible, meaning that it can offer the addition of new block types; and, even swapping out of the schema entirely. So, given this, there should be a very straightforward mapping from BlockNote’s JSON to a lexicon, so just as a proof of the concept - I made that mapping. This allows a BlockNote document to be represented as a lexicon & convert to and from the format (essentially a 1:1 mapping since they are so similar). I actually see this lexicon as sort of being the foundation for a new type of rich text editor, which can have community-driven embeds, in a marketplace. Take a look at this Typepec for BlockNote for more: https://github.com/typespecs/BlockNote/blob/main/lib/main.tsp In BlockNote, we de-couple the schema from the document content, this allows us to be agnostic of the implementation of our blocks (content types like paragraphs, code-blocks), while still having a regular structure that we can use to understand the document’s content in a consistent way. Let’s look at an example of the schema that this very document relies on: a paragraph block: interface ParagraphBlock { id: string; type: "paragraph"; props: { backgroundColor: string; textColor: string; textAlignment: "left" | "center" | "right" | "justify"; }; content: InlineContent[]; children: Block[]; }; Or, more generically: type Block = { id: string; type: string; props: Record; content: InlineContent[] | TableContent | undefined; children: Block[]; }; type Link = { type: "link"; content: StyledText[]; href: string; }; type StyledText = { type: "text"; text: string; styles: Styles; }; type CustomInlineContent = { type: string; content: StyledText[] | undefined; props: Record; }; type InlineContent = Link | StyledText | CustomInlineContent; // tables are special cased, for now type TableContent = { type: "tableContent"; columnWidths: (number | undefined)[]; headerRows?: number; headerCols?: number; rows: { cells: TableCell[]; }[]; }; type TableCell = { type: "tableCell"; props: { backgroundColor: string; textColor: string; textAlignment: "left" | "center" | "right" | "justify"; colspan?: number; rowspan?: number; }; content: InlineContent[]; }; Too abstract? Let’s see a BlockNote document: [ { "id": "502a74dd-55ba-4637-9e78-9e355fc01469", "type": "paragraph", "props": { "backgroundColor": "default", "textColor": "default", "textAlignment": "left" }, "content": [ { "type": "text", "text": "Hello world", "styles": {} } ], "children": [] }, { "id": "721f2779-fc08-4354-99b6-6031c722cdfe", "type": "heading", "props": { "backgroundColor": "default", "textColor": "default", "textAlignment": "left", "level": 1, "isToggleable": false }, "content": [ { "type": "text", "text": "Heading", "styles": {} } ], "children": [] }, { "id": "13a9c876-9809-44c9-8b37-ccba066dad10", "type": "paragraph", "props": { "backgroundColor": "default", "textColor": "default", "textAlignment": "left" }, "content": [], "children": [] } ] Want to the see the mapping of this very document? Head on over to it on pdsls!

Discussion in the ATmosphere

Loading comments...