diff --git a/__tests__/compilers/tables.test.js b/__tests__/compilers/tables.test.js index 978f7ba0e..6d5ebde02 100644 --- a/__tests__/compilers/tables.test.js +++ b/__tests__/compilers/tables.test.js @@ -27,22 +27,20 @@ describe('table compiler', () => { const tree = mdast(markdown); visit(tree, 'tableCell', cell => { - cell.children = [{ type: 'text', value: `${cell.children[0].value}\n\nšŸ¦‰` }]; + cell.children = [{ type: 'text', value: `${cell.children[0].value}\nšŸ¦‰` }]; }); expect(mdx(tree)).toMatchInlineSnapshot(` - " + "
- - @@ -50,15 +48,13 @@ describe('table compiler', () => { - - @@ -88,16 +84,16 @@ describe('table compiler', () => { }); expect(mdx(tree)).toMatchInlineSnapshot(` - "
+ th 1 - šŸ¦‰ + th 2 - šŸ¦‰
+ cell 1 - šŸ¦‰ + cell 2 - šŸ¦‰
+ "
- - @@ -105,11 +101,11 @@ describe('table compiler', () => { - - diff --git a/__tests__/lib/hast.test.ts b/__tests__/lib/hast.test.ts index 49912575a..3cf95bd71 100644 --- a/__tests__/lib/hast.test.ts +++ b/__tests__/lib/hast.test.ts @@ -22,17 +22,3 @@ describe('hast transformer', () => { expect(hast(md, { components })).toStrictEqualExceptPosition(expected); }); }); - -describe('hastFromHtml', () => { - it('parses html', () => { - const html = '
Nice
'; - const tree = hastFromHtml(html); - - // @ts-ignore - expect(tree.children[0].tagName).toBe('html'); - // @ts-ignore - expect(tree.children[0].children[1].children[0].tagName).toBe('div'); - // @ts-ignore - expect(tree.children[0].children[1].children[0].children[0].tagName).toBe('span'); - }); -}); diff --git a/__tests__/lib/mdast.test.ts b/__tests__/lib/mdast.test.ts deleted file mode 100644 index e5d9bc3e6..000000000 --- a/__tests__/lib/mdast.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { mdast } from '../../lib'; - -describe('mdast transformer', () => { - it('parses variables into the tree', () => { - const md = ` -Hello, {user.name} - `; - - const ast = mdast(md); - expect(ast.children[0].children[1].type).toBe('readme-variable'); - expect(ast.children[0].children[1].value).toBe('{user.name}'); - }); -}); diff --git a/__tests__/lib/mdast/index.test.ts b/__tests__/lib/mdast/index.test.ts new file mode 100644 index 000000000..cb74bcc4f --- /dev/null +++ b/__tests__/lib/mdast/index.test.ts @@ -0,0 +1,21 @@ +import { mdast } from '../../../lib'; +import { readdir, readFile } from 'node:fs/promises'; + +describe('mdast transformer', async () => { + const cases = await Promise.all( + (await readdir(__dirname)) + .filter(name => !name.match(/.[tj]sx?/)) + .map(async dirname => { + return { + name: dirname, + mdx: await readFile(`${__dirname}/${dirname}/in.mdx`, { encoding: 'utf8' }), + ast: JSON.parse(await readFile(`${__dirname}/${dirname}/out.json`, { encoding: 'utf8' })), + }; + }), + ); + + it.each(cases)('parses $name', ({ mdx, ast }) => { + // @ts-ignore + expect(mdast(mdx)).toStrictEqualExceptPosition(ast); + }); +}); diff --git a/__tests__/lib/mdast/tables/in.mdx b/__tests__/lib/mdast/tables/in.mdx new file mode 100644 index 000000000..93fcee557 --- /dev/null +++ b/__tests__/lib/mdast/tables/in.mdx @@ -0,0 +1,28 @@ +
+ * 1 * 2 * 3 + th 2
+ cell 1 + cell 2
+ + + + + + + + + + + + + + + + + +
+ Heading One + + Heading Two +
+ * list item + * list item + + :shrug: +
diff --git a/__tests__/lib/mdast/tables/out.json b/__tests__/lib/mdast/tables/out.json new file mode 100644 index 000000000..f3acd27b1 --- /dev/null +++ b/__tests__/lib/mdast/tables/out.json @@ -0,0 +1,109 @@ +{ + "type": "root", + "children": [ + { + "align": ["center", "center"], + "children": [ + { + "children": [ + { + "children": [ + { + "children": [ + { + "type": "text", + "value": "Heading One" + } + ], + "type": "paragraph" + } + ], + "type": "tableCell" + }, + { + "children": [ + { + "children": [ + { + "type": "text", + "value": "Heading Two" + } + ], + "type": "paragraph" + } + ], + "type": "tableCell" + } + ], + "type": "tableRow" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "checked": null, + "children": [ + { + "children": [ + { + "type": "text", + "value": "list item" + } + ], + "type": "paragraph" + } + ], + "spread": false, + "type": "listItem" + }, + { + "checked": null, + "children": [ + { + "children": [ + { + "type": "text", + "value": "list item" + } + ], + "type": "paragraph" + } + ], + "spread": false, + "type": "listItem" + } + ], + "ordered": false, + "spread": false, + "start": null, + "type": "list" + } + ], + "type": "tableCell" + }, + { + "children": [ + { + "children": [ + { + "name": "shrug", + "type": "gemoji", + "value": "šŸ¤·" + } + ], + "type": "paragraph" + } + ], + "type": "tableCell" + } + ], + "type": "tableRow" + } + ], + "type": "tableau" + } + ] +} diff --git a/__tests__/lib/mdast/variables/in.mdx b/__tests__/lib/mdast/variables/in.mdx new file mode 100644 index 000000000..65c2ff69c --- /dev/null +++ b/__tests__/lib/mdast/variables/in.mdx @@ -0,0 +1 @@ +Hello, {user.name} diff --git a/__tests__/lib/mdast/variables/out.json b/__tests__/lib/mdast/variables/out.json new file mode 100644 index 000000000..6f095bced --- /dev/null +++ b/__tests__/lib/mdast/variables/out.json @@ -0,0 +1,72 @@ +{ + "children": [ + { + "children": [ + { + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7 + }, + "start": { + "column": 1, + "line": 1, + "offset": 0 + } + }, + "type": "text", + "value": "Hello, " + }, + { + "data": { + "hName": "Variable", + "hProperties": { + "name": "name" + } + }, + "position": { + "end": { + "column": 19, + "line": 1, + "offset": 18 + }, + "start": { + "column": 8, + "line": 1, + "offset": 7 + } + }, + "type": "readme-variable", + "value": "{user.name}" + } + ], + "position": { + "end": { + "column": 19, + "line": 1, + "offset": 18 + }, + "start": { + "column": 1, + "line": 1, + "offset": 0 + } + }, + "type": "paragraph" + } + ], + "position": { + "end": { + "column": 1, + "line": 2, + "offset": 19 + }, + "start": { + "column": 1, + "line": 1, + "offset": 0 + } + }, + "type": "root" +} diff --git a/__tests__/transformers/readme-components.test.ts b/__tests__/transformers/readme-components.test.ts index c34a0a015..7de3d0a65 100644 --- a/__tests__/transformers/readme-components.test.ts +++ b/__tests__/transformers/readme-components.test.ts @@ -6,7 +6,7 @@ describe('Readme Components Transformer', () => { { md: '', type: 'code' }, { md: '', type: 'code-tabs' }, { md: '', type: 'image-block' }, - { md: '', type: 'table' }, + { md: '
', type: 'tableau' }, { md: '', type: 'tutorial-tile' }, ]; @@ -52,25 +52,6 @@ Second md: `![](http://placekitten.com/600/200)`, mdx: ``, }, - table: { - md: ` -| h1 | h2 | -| --- | --- | -| a1 | a2 | - `, - // @todo there's text nodes that get inserted between the td's. Pretty sure - // they'd get filtered out by rehype, but lets keep the tests easy. - mdx: ` -
- - - - - - -
h1h2
a1a2
- `, - }, }; it.each(Object.entries(docs))('matches the equivalent markdown for %s', (type, { md, mdx }) => { let mdTree = mdast(md); diff --git a/components/Table/index.tsx b/components/Table/index.tsx index af2783edc..99f28f22a 100644 --- a/components/Table/index.tsx +++ b/components/Table/index.tsx @@ -1,6 +1,7 @@ import React from 'react'; interface Props extends JSX.IntrinsicAttributes { + align: ('left' | 'center' | 'right')[]; children: [React.ReactElement]; } diff --git a/enums.ts b/enums.ts index f090c690f..a8f96c243 100644 --- a/enums.ts +++ b/enums.ts @@ -8,6 +8,7 @@ export enum NodeTypes { i = 'i', imageBlock = 'image-block', reusableContent = 'reusable-content', + tableau = 'tableau', tutorialTile = 'tutorial-tile', variable = 'readme-variable', } diff --git a/index.tsx b/index.tsx index 194a52faf..220a1fcca 100644 --- a/index.tsx +++ b/index.tsx @@ -1,13 +1,9 @@ -import debug from 'debug'; - import * as Components from './components'; import { getHref } from './components/Anchor'; import { options } from './options'; import './styles/main.scss'; -const unimplemented = debug('mdx:unimplemented'); - const utils = { get options() { return { ...options }; @@ -17,13 +13,5 @@ const utils = { calloutIcons: {}, }; -export const html = (text: string, opts = {}) => { - unimplemented('html export'); -}; - -export const esast = (text: string, opts = {}) => { - unimplemented('esast export'); -}; - -export { compile, hast, hastFromHtml, run, mdast, mdx, plain, remarkPlugins } from './lib'; +export { compile, hast, run, mdast, mdx, plain, remarkPlugins } from './lib'; export { Components, utils }; diff --git a/lib/hast.ts b/lib/hast.ts index e61647d79..92c864166 100644 --- a/lib/hast.ts +++ b/lib/hast.ts @@ -3,8 +3,6 @@ import remarkRehype from 'remark-rehype'; import { injectComponents } from '../processor/transform'; import { MdastComponents } from '../types'; import mdast from './mdast'; -import { unified } from 'unified'; -import rehypeParse from 'rehype-parse'; const hast = (text: string, opts: MdastOpts = {}) => { const components: MdastComponents = Object.entries(opts.components || {}).reduce((memo, [name, doc]) => { @@ -16,9 +14,4 @@ const hast = (text: string, opts: MdastOpts = {}) => { return processor.runSync(processor.parse(text)); }; - -export const hastFromHtml = (html: string) => { - return unified().use(rehypeParse).parse(html); -}; - export default hast; diff --git a/lib/index.ts b/lib/index.ts index 248c41474..4f9876c69 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,10 +1,10 @@ import astProcessor, { MdastOpts, remarkPlugins } from './ast-processor'; import compile from './compile'; -import hast, { hastFromHtml } from './hast'; +import hast from './hast'; import mdast from './mdast'; import mdx from './mdx'; import plain from './plain'; import run from './run'; export type { MdastOpts }; -export { astProcessor, compile, hast, hastFromHtml, mdast, mdx, plain, run, remarkPlugins }; +export { astProcessor, compile, hast, mdast, mdx, plain, run, remarkPlugins }; diff --git a/lib/mdast.ts b/lib/mdast.ts index 8e0eb26d3..321db18ad 100644 --- a/lib/mdast.ts +++ b/lib/mdast.ts @@ -1,10 +1,9 @@ -import { readmeComponentsTransformer } from '../processor/transform'; import astProcessor, { MdastOpts } from './ast-processor'; const mdast: any = (text: string, opts: MdastOpts = {}) => { - const processor = astProcessor(opts).use(readmeComponentsTransformer({ components: opts.components })); - + const processor = astProcessor(opts); const tree = processor.parse(text); + return processor.runSync(tree); }; diff --git a/package-lock.json b/package-lock.json index f6256b401..032f9ab67 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,6 @@ "path-browserify": "^1.0.1", "process": "^0.11.10", "prop-types": "^15.8.1", - "rehype-parse": "^9.0.0", "rehype-remark": "^10.0.0", "rehype-slug": "^6.0.0", "remark": "^15.0.1", @@ -26976,20 +26975,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/rehype-parse": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.0.tgz", - "integrity": "sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-from-html": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/rehype-raw": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-5.1.0.tgz", diff --git a/package.json b/package.json index 01fb07285..93d76fda6 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "path-browserify": "^1.0.1", "process": "^0.11.10", "prop-types": "^15.8.1", - "rehype-parse": "^9.0.0", "rehype-remark": "^10.0.0", "rehype-slug": "^6.0.0", "remark": "^15.0.1", diff --git a/processor/transform/readme-components.ts b/processor/transform/readme-components.ts index 769999d9a..f19c4b7d9 100644 --- a/processor/transform/readme-components.ts +++ b/processor/transform/readme-components.ts @@ -1,10 +1,10 @@ import { NodeTypes } from '../../enums'; -import { BlockContent, Code, Parents, Table } from 'mdast'; +import { BlockContent, Code, Node, Parents, Table, TableCell, TableRow } from 'mdast'; import { Transform } from 'mdast-util-from-markdown'; import { MdxJsxFlowElement, MdxJsxTextElement } from 'mdast-util-mdx'; -import { Callout, EmbedBlock, HTMLBlock, ImageBlock } from 'types'; -import { visit } from 'unist-util-visit'; +import { Callout, EmbedBlock, HTMLBlock, ImageBlock, Tableau } from 'types'; +import { visit, SKIP } from 'unist-util-visit'; import { getAttrs, isMDXElement, getChildren, formatHTML } from '../utils'; import { mdast } from '../../lib'; @@ -19,17 +19,34 @@ const types = { HTMLBlock: NodeTypes.htmlBlock, Table: 'table', Variable: NodeTypes['variable'], - td: 'tableCell', - tr: 'tableRow', TutorialTile: NodeTypes.tutorialTile, }; +enum TableNames { + tr = 'tr', + th = 'th', + td = 'td', +} + +const tableTypes = { + [TableNames.tr]: 'tableRow', + [TableNames.th]: 'tableCell', + [TableNames.td]: 'tableCell', +}; + interface Options { components: Record; + html?: boolean; } +interface MdxJsxTableCell extends Omit { + name: 'th' | 'td'; +} + +const isTableCell = (node: Node): node is MdxJsxTableCell => isMDXElement(node) && ['th', 'td'].includes(node.name); + const coerceJsxToMd = - ({ components = {} } = {}) => + ({ components = {}, html = false } = {}) => (node: MdxJsxFlowElement | MdxJsxTextElement, index: number, parent: Parents) => { if (node.name in components) return; @@ -57,7 +74,7 @@ const coerceJsxToMd = const mdNode: ImageBlock = { alt, position, - children: attrs.caption ? mdast(attrs.caption).children : node.children as any, + children: attrs.caption ? mdast(attrs.caption).children : (node.children as any), title, type: NodeTypes.imageBlock, url: url || attrs.src, @@ -89,18 +106,39 @@ const coerceJsxToMd = parent.children[index] = mdNode; } else if (node.name === 'Table') { - const { children, position } = node; + const { position } = node; const { align = [...new Array(node.children.length)].map(() => null) } = getAttrs>(node); - - const mdNode: Table = { + let children: TableRow[] = []; + + visit(node, { name: 'tr' }, row => { + let rowChildren: TableCell[] = []; + + visit(row, isTableCell, ({ name, children, position }) => { + rowChildren.push({ + type: tableTypes[name], + children, + position, + } as TableCell); + }); + + children.push({ + type: tableTypes[row.name], + children: rowChildren, + position: row.position, + }); + }); + + const mdNode: Tableau = { align, - type: 'table', + type: NodeTypes.tableau, position, - // @ts-ignore children, }; + visit(mdNode, isMDXElement, coerceJsxToMd({ components, html })); + parent.children[index] = mdNode; + return SKIP; } else if (node.name === 'Callout') { const { icon, empty = false } = getAttrs(node); @@ -136,14 +174,10 @@ const coerceJsxToMd = const mdNode: BlockContent = { children: node.children, type: types[node.name], - ...(['tr', 'td'].includes(node.name) - ? {} - : { - data: { - hName: node.name, - ...(Object.keys(hProperties).length && { hProperties }), - }, - }), + data: { + hName: node.name, + ...(Object.keys(hProperties).length && { hProperties }), + }, position: node.position, }; diff --git a/processor/transform/tables-to-jsx.ts b/processor/transform/tables-to-jsx.ts index 4125844ae..5ee0a66cb 100644 --- a/processor/transform/tables-to-jsx.ts +++ b/processor/transform/tables-to-jsx.ts @@ -7,6 +7,17 @@ import { fromMarkdown } from 'mdast-util-from-markdown'; import { mdxJsxFromMarkdown } from 'mdast-util-mdx-jsx'; import { phrasing } from 'mdast-util-phrasing'; +const alignToStyle = (align: 'left' | 'center' | 'right') => { + return { + type: 'mdxJsxAttribute', + name: 'style', + value: { + type: 'mdxJsxAttributeValueExpression', + value: `{ textAlign: \"${align}\" }`, + }, + }; +}; + const visitor = (table: Table, index: number, parent: Parents) => { let hasFlowContent = false; @@ -27,6 +38,8 @@ const visitor = (table: Table, index: number, parent: Parents) => { visit(table, 'tableCell', tableCellVisitor); if (!hasFlowContent) return; + const styles = table.align.map(alignToStyle); + const head = { type: 'mdxJsxFlowElement', name: 'thead', @@ -34,19 +47,12 @@ const visitor = (table: Table, index: number, parent: Parents) => { { type: 'mdxJsxFlowElement', name: 'tr', - children: table.children[0].children.map((cell, idx) => { - const proxy = fromMarkdown(`
`, { - extensions: [mdxJsx()], - mdastExtensions: [mdxJsxFromMarkdown()], - }); - // @ts-ignore - const { attributes } = proxy.children[0]; - + children: table.children[0].children.map((cell, index) => { return { type: 'mdxJsxFlowElement', name: 'th', - attributes, children: cell.children, + attributes: [styles[index]], }; }), }, @@ -60,28 +66,32 @@ const visitor = (table: Table, index: number, parent: Parents) => { return { type: 'mdxJsxFlowElement', name: 'tr', - children: row.children.map((cell, idx) => { - const proxy = fromMarkdown(`
`, { - extensions: [mdxJsx()], - mdastExtensions: [mdxJsxFromMarkdown()], - }); - // @ts-ignore - const { attributes } = proxy.children[0]; - + children: row.children.map((cell, index) => { return { type: 'mdxJsxFlowElement', name: 'th', - attributes, children: cell.children, + attributes: [styles[index]], }; }), }; }), }; + const attributes = [ + { + type: 'mdxJsxAttribute', + name: 'align', + value: { + type: 'mdxJsxAttributeValueExpression', + value: JSON.stringify(table.align), + }, + }, + ]; const jsx = { type: 'mdxJsxFlowElement', name: 'Table', + attributes, children: [head, body], }; diff --git a/processor/utils.ts b/processor/utils.ts index e4d98a90f..3f86fa6a3 100644 --- a/processor/utils.ts +++ b/processor/utils.ts @@ -13,7 +13,7 @@ import { MdxJsxFlowElement, MdxJsxTextElement, MdxFlowExpression } from 'mdast-u export const formatHProps = (node: Node): string => { const hProps = getHProps(node); return formatProps(hProps); -} +}; /** * Formats an object of props as a string. @@ -24,7 +24,7 @@ export const formatHProps = (node: Node): string => { export const formatProps = (props: Object): string => { const keys = Object.keys(props); return keys.map(key => `${key}="${props[key]}"`).join(' '); -} +}; /** * Returns the hProperties of a node. @@ -36,7 +36,7 @@ export const formatProps = (props: Object): string => { export const getHProps = (node: Node): T => { const hProps = node.data?.hProperties || {}; return hProps as T; -} +}; /** * Returns array of hProperty keys. @@ -45,10 +45,10 @@ export const getHProps = (node: Node): T => { * @param {Node} node * @returns {Array} array of hProperty keys */ -export const getHPropKeys = (node: Node): any => { +export const getHPropKeys = (node: Node): any => { const hProps = getHProps(node); return Object.keys(hProps) || []; -} +}; /** * Gets the attributes of an MDX element and returns them as an object of hProperties. @@ -60,7 +60,7 @@ export const getHPropKeys = (node: Node): any => { export const getAttrs = (jsx: MdxJsxFlowElement | MdxJsxTextElement): any => jsx.attributes.reduce((memo, attr) => { if ('name' in attr) { - memo[attr.name] = attr.value; + memo[attr.name] = typeof attr.value !== 'string' ? JSON.parse(attr.value.value) : attr.value; } return memo; @@ -75,14 +75,14 @@ export const getAttrs = (jsx: MdxJsxFlowElement | MdxJsxTextElement): any => * @returns {Array} array of child text nodes */ export const getChildren = (jsx: MdxJsxFlowElement | MdxJsxTextElement): any => - jsx.children.reduce((memo, child: MdxFlowExpression, i) => { - memo[i] = { + jsx.children.reduce((memo, child: MdxFlowExpression, i) => { + memo[i] = { type: 'text', value: child.value, position: child.position, - }; - return memo; - }, [] as T); + }; + return memo; + }, [] as T); /** * Tests if a node is an MDX element. @@ -93,7 +93,7 @@ export const getChildren = (jsx: MdxJsxFlowElement | MdxJsxTextElement): any */ export const isMDXElement = (node: Node): node is MdxJsxFlowElement | MdxJsxTextElement => { return ['mdxJsxFlowElement', 'mdxJsxTextElement'].includes(node.type); -} +}; /** * Takes an HTML string and formats it for display in the editor. Removes leading/trailing newlines @@ -103,7 +103,7 @@ export const isMDXElement = (node: Node): node is MdxJsxFlowElement | MdxJsxText * @returns {string} formatted HTML */ export const formatHTML = (html: string): string => { - // Remove leading/trailing backticks if present, since they're used to keep the HTML + // Remove leading/trailing backticks if present, since they're used to keep the HTML // from being parsed prematurely if (html.startsWith('`') && html.endsWith('`')) { html = html.slice(1, -1); @@ -114,12 +114,12 @@ export const formatHTML = (html: string): string => { // // Get the number of spaces in the first line to determine the tab size // const tab = cleaned.match(/^\s*/)[0].length; - // // Remove the first indentation level from each line + // // Remove the first indentation level from each line // const tabRegex = new RegExp(`^\\s{${tab}}`, 'gm'); // const unindented = cleaned.replace(tabRegex, ''); - + return cleaned; -} +}; /** * Reformat HTML for the markdown/mdx by adding an indentation to each line. This assures that the @@ -140,4 +140,4 @@ export const reformatHTML = (html: string, indent: number = 2): string => { // const indented = cleaned.split('\n').map((line: string) => `${tab}${line}`).join('\n'); return cleaned; -} +}; diff --git a/types.d.ts b/types.d.ts index 727ef9604..d941595ca 100644 --- a/types.d.ts +++ b/types.d.ts @@ -1,4 +1,4 @@ -import { Code, Data, Literal, Parent, Blockquote, Node, Root, Text } from 'mdast'; +import { Code, Data, Literal, Parent, Blockquote, Node, Root, Text, Table } from 'mdast'; import { NodeTypes } from './enums'; import { Element } from 'hast'; @@ -86,6 +86,10 @@ interface FaEmoji extends Literal { type: NodeTypes.i; } +interface Tableau extends Omit { + type: NodeTypes.tableau; +} + interface TutorialTile extends Node { backgroundColor: string; emoji: string; @@ -110,9 +114,10 @@ declare module 'mdast' { interface BlockContentMap { [NodeTypes.callout]: Callout; [NodeTypes.codeTabs]: CodeTabs; - [NodeTypes.imageBlock]: ImageBlock; [NodeTypes.embedBlock]: EmbedBlock; [NodeTypes.htmlBlock]: HTMLBlock; + [NodeTypes.imageBlock]: ImageBlock; + [NodeTypes.tableau]: Tableau; [NodeTypes.tutorialTile]: TutorialTile; } @@ -130,6 +135,7 @@ declare module 'mdast' { [NodeTypes.htmlBlock]: HTMLBlock; [NodeTypes.i]: FaEmoji; [NodeTypes.imageBlock]: ImageBlock; + [NodeTypes.tableau]: Tableau; [NodeTypes.tutorialTile]: TutorialTile; [NodeTypes.variable]: Variable; }