diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 405f30143..482308138 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -61,6 +61,6 @@ jobs: # Sync docs to rdmd.readme.io # - name: Sync docs to rdmd.readme.io - uses: readmeio/rdme@v8 + uses: readmeio/rdme@v9 with: rdme: docs ./docs --key=${{ secrets.RDME_KEY }} --version=2 diff --git a/__tests__/lib/plain/custom-components.test.ts b/__tests__/lib/plain/custom-components.test.ts new file mode 100644 index 000000000..34a5a5958 --- /dev/null +++ b/__tests__/lib/plain/custom-components.test.ts @@ -0,0 +1,33 @@ +import { hast, plain } from '../../../index'; + +describe('plain compiler', () => { + it('should include the title of Accordion', () => { + const mdx = ` + + Body + +`; + + expect(plain(hast(mdx))).toContain('Title Body'); + }); + + it('should include the title of Card', () => { + const mdx = ` + + Body + +`; + + expect(plain(hast(mdx))).toContain('Title Body'); + }); + + it('should include the title of Tab', () => { + const mdx = ` + + Body + +`; + + expect(plain(hast(mdx))).toContain('Title Body'); + }); +}); diff --git a/__tests__/migration/tables.test.ts b/__tests__/migration/tables.test.ts index 255d5ec8e..50daa6250 100644 --- a/__tests__/migration/tables.test.ts +++ b/__tests__/migration/tables.test.ts @@ -486,4 +486,21 @@ ${JSON.stringify( " `); }); + + it('compiles tables with leading escapes', () => { + const md = ` +| Col 1 | Col 2 | +| --------- | ----- | +| \\_foo_\\ | bar | +`; + + const mdx = migrate(md); + + expect(mdx).toMatchInlineSnapshot(` + "| Col 1 | Col 2 | + | --------- | ----- | + | \\_foo\\_\\ | bar | + " + `); + }); }); diff --git a/lib/hast.ts b/lib/hast.ts index 92c864166..9ec5ccec9 100644 --- a/lib/hast.ts +++ b/lib/hast.ts @@ -1,6 +1,6 @@ import astProcessor, { rehypePlugins, MdastOpts } from './ast-processor'; import remarkRehype from 'remark-rehype'; -import { injectComponents } from '../processor/transform'; +import { injectComponents, mdxToHast } from '../processor/transform'; import { MdastComponents } from '../types'; import mdast from './mdast'; @@ -10,7 +10,11 @@ const hast = (text: string, opts: MdastOpts = {}) => { return memo; }, {}); - const processor = astProcessor(opts).use(injectComponents({ components })).use(remarkRehype).use(rehypePlugins); + const processor = astProcessor(opts) + .use(injectComponents({ components })) + .use(mdxToHast) + .use(remarkRehype) + .use(rehypePlugins); return processor.runSync(processor.parse(text)); }; diff --git a/lib/plain.ts b/lib/plain.ts index 220814f93..9f775870b 100644 --- a/lib/plain.ts +++ b/lib/plain.ts @@ -21,32 +21,39 @@ function one(node: Nodes, opts: Options) { if ('tagName' in node) { if (STRIP_TAGS.includes(node.tagName)) return ''; - if (node.tagName === 'html-block') { - if (!node.properties.html) return ''; - return all(hast(node.properties.html.toString()), opts); - } - - if (node.tagName === 'rdme-callout') { - const { icon, title } = node.properties; - - const children = node?.children?.slice(title ? 1 : 0); - const body = children ? all({ type: 'root', children }, opts) : ''; - - return [icon, ' ', title, title && body && ': ', body].filter(Boolean).join(''); - } - - if (node.tagName === 'readme-glossary-item') { - return node.properties.term; - } - - if (node.tagName === 'readme-variable') { - const key = node.properties.variable.toString(); - const val = opts.variables[key]; - return val || `<<${key}>>`; - } - - if (node.tagName === 'img') { - return node.properties?.title || ''; + switch (node.tagName) { + case 'html-block': { + if (!node.properties.html) return ''; + return all(hast(node.properties.html.toString()), opts); + } + case 'rdme-callout': { + const { icon, title } = node.properties; + + const children = node?.children?.slice(title ? 1 : 0); + const body = children ? all({ type: 'root', children }, opts) : ''; + + return [icon, ' ', title, title && body && ': ', body].filter(Boolean).join(''); + } + case 'readme-glossary-item': { + return node.properties.term; + } + case 'readme-variable': { + const key = node.properties.variable.toString(); + const val = opts.variables[key]; + return val || `<<${key}>>`; + } + case 'img': { + return node.properties?.title || ''; + } + case 'Accordion': + case 'Card': + case 'Tab': { + const title = node.properties?.title || ''; + const children = node?.children; + const body = children ? all({ type: 'root', children }, opts) : ''; + + return [title, body].filter(Boolean).join(' '); + } } } diff --git a/package-lock.json b/package-lock.json index 60d5dbc25..5a81ffb6b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11880,9 +11880,9 @@ "dev": true }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dependencies": { "ms": "^2.1.3" }, diff --git a/processor/migration/index.ts b/processor/migration/index.ts index 02c9907ae..45805ca56 100644 --- a/processor/migration/index.ts +++ b/processor/migration/index.ts @@ -3,12 +3,6 @@ import imagesTransformer from './images'; import linkReferenceTransformer from './linkReference'; import tableCellTransformer from './table-cell'; -const transformers = [ - emphasisTransformer, - imagesTransformer, - linkReferenceTransformer, - tableCellTransformer, -]; - -export default transformers +const transformers = [emphasisTransformer, imagesTransformer, linkReferenceTransformer, tableCellTransformer]; +export default transformers; diff --git a/processor/transform/index.ts b/processor/transform/index.ts index 7a9bc5898..a21491da0 100644 --- a/processor/transform/index.ts +++ b/processor/transform/index.ts @@ -4,24 +4,26 @@ import embedTransformer from './embeds'; import imageTransformer from './images'; import gemojiTransformer from './gemoji+'; +import compatabilityTransfomer from './compatability'; import divTransformer from './div'; import injectComponents from './inject-components'; +import mdxToHast from './mdx-to-hast'; +import mermaidTransformer from './mermaid'; import readmeComponentsTransformer from './readme-components'; import readmeToMdx from './readme-to-mdx'; -import variablesTransformer from './variables'; import tablesToJsx from './tables-to-jsx'; -import compatabilityTransfomer from './compatability'; -import mermaidTransformer from './mermaid'; +import variablesTransformer from './variables'; export { compatabilityTransfomer, divTransformer, + injectComponents, + mdxToHast, + mermaidTransformer, readmeComponentsTransformer, readmeToMdx, - injectComponents, - variablesTransformer, tablesToJsx, - mermaidTransformer, + variablesTransformer, }; export const defaultTransforms = { diff --git a/processor/transform/mdx-to-hast.ts b/processor/transform/mdx-to-hast.ts new file mode 100644 index 000000000..f6a6c1544 --- /dev/null +++ b/processor/transform/mdx-to-hast.ts @@ -0,0 +1,27 @@ +import { visit } from 'unist-util-visit'; +import { MdxJsxFlowElement, MdxJsxTextElement } from 'mdast-util-mdx'; +import { Transform } from 'mdast-util-from-markdown'; +import { Parents } from 'mdast'; +import { getAttrs, isMDXElement } from '../utils'; +import * as Components from '../../components'; + +const setData = (node: MdxJsxFlowElement | MdxJsxTextElement, index: number, parent: Parents) => { + if (!node.name) return; + if (!(node.name in Components)) return; + + parent.children[index] = { + ...node, + data: { + hName: node.name, + hProperties: getAttrs(node), + }, + }; +}; + +const mdxToHast = (): Transform => tree => { + visit(tree, isMDXElement, setData); + + return tree; +}; + +export default mdxToHast; diff --git a/processor/transform/tables-to-jsx.ts b/processor/transform/tables-to-jsx.ts index 7d401137e..dc423d274 100644 --- a/processor/transform/tables-to-jsx.ts +++ b/processor/transform/tables-to-jsx.ts @@ -36,7 +36,7 @@ const visitor = (table: Table, index: number, parent: Parents) => { parent.children.splice(index, 1, { type: 'text', value: '\n' }); }); - if (!phrasing(content)) { + if (!phrasing(content) && content.type !== 'escape') { hasFlowContent = true; return EXIT; }