I ended up just creating a metaobject with everything I could — headings, bold text, italics, etc:
==================================# Heading 1## Heading 2### Heading 3#### Heading 4##### Heading 5###### Heading 6
This is a paragraph. This is bold text. This is italic text. This is bold and italic text. This is a link.
- first in unordered list
- second in unordered list
A paragraph in between
- first in ordered list
- second in ordered list
==================================
then inspect the network request payload:
{"type":"root","children":[{"type":"heading","children":[{"type":"text","value":"Heading 1"}],"level":1},{"type":"heading","level":2,"children":[{"type":"text","value":"Heading 2"}]},{"type":"heading","children":[{"type":"text","value":"Heading 3"}],"level":3},{"type":"heading","level":4,"children":[{"type":"text","value":"Heading 4"}]},{"type":"heading","level":5,"children":[{"type":"text","value":"Heading 5"}]},{"type":"heading","level":6,"children":[{"type":"text","value":"Heading 6"}]},{"type":"paragraph","children":[{"type":"text","value":"This is a paragraph. This is "},{"type":"text","value":"bold text","bold":true},{"type":"text","value":". This is "},{"type":"text","value":"italic text","italic":true},{"type":"text","value":". This is "},{"type":"text","value":"bold and italic text","bold":true,"italic":true},{"type":"text","value":". This is a "},{"url":"https://example.com","title":"Go to an example site","target":"_blank","type":"link","children":[{"type":"text","value":"link."}]},{"type":"text","value":""}]},{"listType":"unordered","type":"list","children":[{"type":"list-item","children":[{"type":"text","value":"first in unordered list"}]},{"type":"list-item","children":[{"type":"text","value":"second in unordered list"}]}]},{"type":"paragraph","children":[{"type":"text","value":"A paragraph in between"}]},{"listType":"ordered","type":"list","children":[{"type":"list-item","children":[{"type":"text","value":"first in ordered list"}]},{"type":"list-item","children":[{"type":"text","value":"second in ordered list"}]}]},{"type":"heading","level":3,"children":[{"type":"text","value":""}]}]}
From that you can generate a JSON schema or Typescript types:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Generated schema for Root",
"type": "object",
"properties": {
"type": {
"type": "string"
},
"children": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"children": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"value": {
"type": "string"
},
"bold": {
"type": "boolean"
},
"italic": {
"type": "boolean"
},
"url": {
"type": "string"
},
"title": {
"type": "string"
},
"target": {
"type": "string"
},
"children": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"value": {
"type": "string"
}
},
"required": [
"type",
"value"
]
}
}
},
"required": [
"type"
]
}
},
"level": {
"type": "number"
},
"listType": {
"type": "string"
}
},
"required": [
"type",
"children"
]
}
}
},
"required": [
"type",
"children"
]
}
It’s a pretty basic ast, but if you’re trying to convert HTML to it, there are some gotchas (especially if the HTML is not valid, like mine was):
- root has to be the first node
- only headings, paragraphs, and lists can be under the root
- no divs, imgs, anchors, etc, can be a child of the root