{
  "site": "at://did:plc:uyjvm2kqevlb4pa6sf63476h/site.standard.publication/3mi2kahf6x22y",
  "$type": "site.standard.document",
  "title": "Lexicons",
  "content": {
    "$type": "org.blocknote.document#content",
    "blocks": [
      {
        "id": "86c3dfc2-09ec-44d3-a99c-39c381b169f3",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        },
        "inlineContent": [
          {
            "text": "This post is in reaction to ",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          },
          {
            "href": "https://bsky.app/profile/pfrazee.com",
            "type": "link",
            "$type": "org.blocknote.schema#link",
            "content": [
              {
                "text": "@pfrazee.com",
                "type": "text",
                "$type": "org.blocknote.schema#styledText",
                "styles": {}
              }
            ]
          },
          {
            "text": " here: ",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          },
          {
            "href": "https://bsky.app/profile/pfrazee.com/post/3mfd4onkpkk2o",
            "type": "link",
            "$type": "org.blocknote.schema#link",
            "content": [
              {
                "text": "https://bsky.app/profile/pfrazee.com/post/3mfd4onkpkk2o",
                "type": "text",
                "$type": "org.blocknote.schema#styledText",
                "styles": {}
              }
            ]
          }
        ]
      },
      {
        "id": "c7ca1e7a-29f9-4c06-bd2e-db3e8c675201",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        }
      },
      {
        "id": "f326cc6c-8640-4ac8-9a0c-ff2ff4286171",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        },
        "inlineContent": [
          {
            "href": "https://blocknotejs.org",
            "type": "link",
            "$type": "org.blocknote.schema#link",
            "content": [
              {
                "text": "BlockNote",
                "type": "text",
                "$type": "org.blocknote.schema#styledText",
                "styles": {}
              }
            ]
          },
          {
            "text": ", is an extensible rich text editor ",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          },
          {
            "href": "https://www.blocknotejs.org/docs/foundations/document-structure",
            "type": "link",
            "$type": "org.blocknote.schema#link",
            "content": [
              {
                "text": "with a structure",
                "type": "text",
                "$type": "org.blocknote.schema#styledText",
                "styles": {}
              }
            ]
          },
          {
            "text": " very similar to what Paul was describing: ",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          }
        ]
      },
      {
        "id": "36e5cbde-ec9d-443b-b651-7e95edbc28e7",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        },
        "inlineContent": [
          {
            "text": "It is ",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          },
          {
            "href": "https://www.blocknotejs.org/docs/foundations/schemas",
            "type": "link",
            "$type": "org.blocknote.schema#link",
            "content": [
              {
                "text": "extensible",
                "type": "text",
                "$type": "org.blocknote.schema#styledText",
                "styles": {}
              }
            ]
          },
          {
            "text": ", meaning that it can offer the addition of new block types; and, even swapping out of the schema entirely.",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          }
        ]
      },
      {
        "id": "1e75b676-0927-4f0d-aa66-a46af3054a3f",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        }
      },
      {
        "id": "6eba65b4-183d-40f8-b930-5af8959b994d",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        },
        "inlineContent": [
          {
            "text": "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).",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          }
        ]
      },
      {
        "id": "93f60a24-5666-49d8-8762-fcd9b3cb8049",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        }
      },
      {
        "id": "e7d19121-9e8d-40ca-94d3-55312c008bdf",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        },
        "inlineContent": [
          {
            "text": "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.",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          }
        ]
      },
      {
        "id": "d41b916b-d491-438c-8912-6eb704ca58d7",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        }
      },
      {
        "id": "b3e3cd6c-9b7e-49b2-b029-2a3309b0ddaf",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        },
        "inlineContent": [
          {
            "text": "Take a look at this Typepec for BlockNote for more: ",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          },
          {
            "href": "https://github.com/typespecs/BlockNote/blob/main/lib/main.tsp",
            "type": "link",
            "$type": "org.blocknote.schema#link",
            "content": [
              {
                "text": "https://github.com/typespecs/BlockNote/blob/main/lib/main.tsp",
                "type": "text",
                "$type": "org.blocknote.schema#styledText",
                "styles": {}
              }
            ]
          }
        ]
      },
      {
        "id": "d115c479-4773-4fab-af90-3b5cf730bc1a",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        }
      },
      {
        "id": "52cc9c67-11da-43a4-a8a6-259f24649f32",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        },
        "inlineContent": [
          {
            "text": "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:",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          }
        ]
      },
      {
        "id": "ac9521c4-a652-4d32-a357-97d7bfd1628b",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        }
      },
      {
        "id": "471727fe-a4dd-478c-92cb-03582c86b17c",
        "type": "codeBlock",
        "props": {
          "language": "typescript"
        },
        "inlineContent": [
          {
            "text": "interface ParagraphBlock {\n  id: string;\n  type: \"paragraph\";\n  props:",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          },
          {
            "text": " ",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {
              "textColor": "rgb(225, 228, 232)"
            }
          },
          {
            "text": "{\n    backgroundColor: string;\n    textColor: string;\n    textAlignment: \"left\" | \"center\" | \"right\" | \"justify\";\n  };\n  content: InlineContent[];\n  children",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          },
          {
            "text": ":",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {
              "textColor": "rgb(249, 117, 131)"
            }
          },
          {
            "text": " Block[];\n};",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          }
        ]
      },
      {
        "id": "24167dea-7f8c-4f0f-87b1-70b19ede770f",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        }
      },
      {
        "id": "5db8ef4c-01af-404a-acdf-bb4f0b70c2ef",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        },
        "inlineContent": [
          {
            "text": "Or, more generically:",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          }
        ]
      },
      {
        "id": "05486797-b6a6-4a2c-95d7-208ca729624f",
        "type": "codeBlock",
        "props": {
          "language": "typescript"
        },
        "inlineContent": [
          {
            "text": "type Block = {\n  id: string;\n  type: string;\n  props: Record<string, boolean | number | string>;\n  content: InlineContent[] | TableContent | undefined;\n  children: Block[];\n};\n\ntype Link = {\n  type: \"link\";\n  content: StyledText[];\n  href: string;\n};\n\ntype StyledText = {\n  type: \"text\";\n  text: string;\n  styles: Styles;\n};\n\ntype CustomInlineContent = {\n  type: string;\n  content: StyledText[] | undefined;\n  props: Record<string, boolean | number | string>;\n};\n\ntype InlineContent = Link | StyledText | CustomInlineContent;\n\n// tables are special cased, for now\ntype TableContent = {\n  type: \"tableContent\";\n  columnWidths: (number | undefined)[];\n  headerRows?: number;\n  headerCols?: number;\n  rows: {\n    cells: TableCell[];\n  }[];\n};\n\ntype TableCell = {\n  type: \"tableCell\";\n  props: {\n    backgroundColor: string;\n    textColor: string;\n    textAlignment: \"left\" | \"center\" | \"right\" | \"justify\";\n    colspan?: number;\n    rowspan?: number;\n  };\n  content: InlineContent[];\n};",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          }
        ]
      },
      {
        "id": "a0eaad57-c079-4633-8a50-1856f1cecf31",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        }
      },
      {
        "id": "05c3b60d-96ea-4b13-bab7-7054a91cf282",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        },
        "inlineContent": [
          {
            "text": "Too abstract? Let’s see a BlockNote document:",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          }
        ]
      },
      {
        "id": "15e7f7b2-8271-4213-9c21-81652291a2d2",
        "type": "codeBlock",
        "props": {
          "language": "json"
        },
        "inlineContent": [
          {
            "text": "[\n  {\n    \"id\": \"502a74dd-55ba-4637-9e78-9e355fc01469\",\n    \"type\": \"paragraph\",\n    \"props\": {\n      \"backgroundColor\": \"default\",\n      \"textColor\": \"default\",\n      \"textAlignment\": \"left\"\n    },\n    \"content\": [\n      {\n        \"type\": \"text\",\n        \"text\": \"Hello world\",\n        \"styles\": {}\n      }\n    ],\n    \"children\": []\n  },\n  {\n    \"id\": \"721f2779-fc08-4354-99b6-6031c722cdfe\",\n    \"type\": \"heading\",\n    \"props\": {\n      \"backgroundColor\": \"default\",\n      \"textColor\": \"default\",\n      \"textAlignment\": \"left\",\n      \"level\": 1,\n      \"isToggleable\": false\n    },\n    \"content\": [\n      {\n        \"type\": \"text\",\n        \"text\": \"Heading\",\n        \"styles\": {}\n      }\n    ],\n    \"children\": []\n  },\n  {\n    \"id\": \"13a9c876-9809-44c9-8b37-ccba066dad10\",\n    \"type\": \"paragraph\",\n    \"props\": {\n      \"backgroundColor\": \"default\",\n      \"textColor\": \"default\",\n      \"textAlignment\": \"left\"\n    },\n    \"content\": [],\n    \"children\": []\n  }\n]",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          }
        ]
      },
      {
        "id": "d8d1fb3c-2008-4911-b267-ece27f9c89d5",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        }
      },
      {
        "id": "dc1fd688-8281-4c4b-ae6c-56b8e82d2f2c",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        },
        "inlineContent": [
          {
            "text": "Want to the see the mapping of this very document? ",
            "type": "text",
            "$type": "org.blocknote.schema#styledText",
            "styles": {}
          },
          {
            "href": "https://pdsls.dev/at://did:plc:uyjvm2kqevlb4pa6sf63476h/site.standard.document/3mi2kahquxs2y",
            "type": "link",
            "$type": "org.blocknote.schema#link",
            "content": [
              {
                "text": "Head on over to it on pdsls!",
                "type": "text",
                "$type": "org.blocknote.schema#styledText",
                "styles": {}
              }
            ]
          }
        ]
      },
      {
        "id": "e9f16690-269c-46a7-be77-0cce1d3da3d9",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        }
      },
      {
        "id": "2c8123e7-e0a6-43f4-9300-349c259a6a0a",
        "type": "paragraph",
        "props": {
          "textColor": "default",
          "textAlignment": "left",
          "backgroundColor": "default"
        }
      }
    ]
  },
  "updatedAt": "2026-03-28T10:41:39.614Z",
  "publishedAt": "2026-03-28T10:41:39.614Z",
  "textContent": "This post is in reaction to @pfrazee.com here: https://bsky.app/profile/pfrazee.com/post/3mfd4onkpkk2o\nIt is extensible, meaning that it can offer the addition of new block types; and, even swapping out of the schema entirely.\nSo, 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).\nI 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.\nTake a look at this Typepec for BlockNote for more: https://github.com/typespecs/BlockNote/blob/main/lib/main.tsp\nIn 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:\ninterface ParagraphBlock {\n  id: string;\n  type: \"paragraph\";\n  props: {\n    backgroundColor: string;\n    textColor: string;\n    textAlignment: \"left\" | \"center\" | \"right\" | \"justify\";\n  };\n  content: InlineContent[];\n  children: Block[];\n};\nOr, more generically:\ntype Block = {\n  id: string;\n  type: string;\n  props: Record<string, boolean | number | string>;\n  content: InlineContent[] | TableContent | undefined;\n  children: Block[];\n};\n\ntype Link = {\n  type: \"link\";\n  content: StyledText[];\n  href: string;\n};\n\ntype StyledText = {\n  type: \"text\";\n  text: string;\n  styles: Styles;\n};\n\ntype CustomInlineContent = {\n  type: string;\n  content: StyledText[] | undefined;\n  props: Record<string, boolean | number | string>;\n};\n\ntype InlineContent = Link | StyledText | CustomInlineContent;\n\n// tables are special cased, for now\ntype TableContent = {\n  type: \"tableContent\";\n  columnWidths: (number | undefined)[];\n  headerRows?: number;\n  headerCols?: number;\n  rows: {\n    cells: TableCell[];\n  }[];\n};\n\ntype TableCell = {\n  type: \"tableCell\";\n  props: {\n    backgroundColor: string;\n    textColor: string;\n    textAlignment: \"left\" | \"center\" | \"right\" | \"justify\";\n    colspan?: number;\n    rowspan?: number;\n  };\n  content: InlineContent[];\n};\nToo abstract? Let’s see a BlockNote document:\n[\n  {\n    \"id\": \"502a74dd-55ba-4637-9e78-9e355fc01469\",\n    \"type\": \"paragraph\",\n    \"props\": {\n      \"backgroundColor\": \"default\",\n      \"textColor\": \"default\",\n      \"textAlignment\": \"left\"\n    },\n    \"content\": [\n      {\n        \"type\": \"text\",\n        \"text\": \"Hello world\",\n        \"styles\": {}\n      }\n    ],\n    \"children\": []\n  },\n  {\n    \"id\": \"721f2779-fc08-4354-99b6-6031c722cdfe\",\n    \"type\": \"heading\",\n    \"props\": {\n      \"backgroundColor\": \"default\",\n      \"textColor\": \"default\",\n      \"textAlignment\": \"left\",\n      \"level\": 1,\n      \"isToggleable\": false\n    },\n    \"content\": [\n      {\n        \"type\": \"text\",\n        \"text\": \"Heading\",\n        \"styles\": {}\n      }\n    ],\n    \"children\": []\n  },\n  {\n    \"id\": \"13a9c876-9809-44c9-8b37-ccba066dad10\",\n    \"type\": \"paragraph\",\n    \"props\": {\n      \"backgroundColor\": \"default\",\n      \"textColor\": \"default\",\n      \"textAlignment\": \"left\"\n    },\n    \"content\": [],\n    \"children\": []\n  }\n]\nWant to the see the mapping of this very document? Head on over to it on pdsls!"
}