diff --git a/README.md b/README.md index 0dfd0bebb..42b25d269 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ -ReadMe's flavored Markdown parser and MDX rendering engine. RDMD CI Status +ReadMe's MDX rendering engine and custom component collection. RDMD CI Status ``` npm install --save @readme/markdown @@ -21,14 +21,12 @@ export default ({ body }) =>
{run(compile(body))} #### `compile` -Compiles mdx to js. A wrapper around [`mdx.compile`](https://mdxjs.com/packages/mdx/#compilefile-options) - -You usually only need this when calling `run` as well. It's been left as a seperate step as a potential caching opportunity. +Compiles MDX to JS. Essentially a wrapper around [`mdx.compile`](https://mdxjs.com/packages/mdx/#compilefile-options). You usually only need this when calling `run` as well. It's been left as a seperate step as a potential caching opportunity. ###### Parameters -- `string` (`string`) -- An mdx document -- `opts` ([`CompileOpts`](#compileopts), optional) -- configuration +- `string` (`string`) -- an MDX document +- `opts` ([`CompileOpts`](#compileopts), optional) -- a configuration object ###### Returns @@ -36,10 +34,8 @@ compiled code (`string`) #### `run` -Run compiled code. A wrapper around [`mdx.run`](https://mdxjs.com/packages/mdx/#runcode-options) - > [!CAUTION] -> This `eval`'s JavaScript. +> **This will `eval` the compiled MDX**! Essentially a wrapper around [`mdx.run`](https://mdxjs.com/packages/mdx/#runcode-options). ###### Parameters @@ -64,17 +60,11 @@ Parses mdx to an hast. #### `plain` -Parses mdx to a plain string. - -> [!WARNING] -> This **does** not `eval` the doc. +Parses mdx to a plain string. (This **does** not `eval` the doc.) #### `tags` -Returns a list of tag names from the doc. - -> [!WARNING] -> This **does** not `eval` the doc. +Returns a list of tag names from the doc. (This **does** not `eval` the doc.) #### `utils` @@ -86,10 +76,10 @@ Extends [`CompileOptions`](https://mdxjs.com/packages/mdx/#compileoptions) ###### Additional Properties -- `lazyImages` (`boolean`, optional) -- Load images lazily. -- `safeMode` (`boolean`, optional) -- Extract script tags from `HTMLBlock`s -- `components` (`Record`, optional) -- An object of tag names to mdx. -- `copyButtons` (`Boolean`, optional) — Automatically insert a button to copy a block of text to the clipboard. Currently used on `` elements. +- `lazyImages` (`boolean`, optional) -- load images lazily +- `safeMode` (`boolean`, optional) -- extract script tags from `HTMLBlock`s +- `components` (`Record`, optional) -- an object of tag names to mdx. +- `copyButtons` (`Boolean`, optional) — add a copy button to code blocks ### `RunOpts` @@ -97,24 +87,22 @@ Extends [`RunOptions`](https://mdxjs.com/packages/mdx/#runoptions) ###### Additional Properties -- `components` (`Record`, optional) -- An object of tag names to executed components. -- `imports` (`Record`, optional) -- An object of modules to import. +- `components` (`Record`, optional) -- a set of custom MDX components +- `imports` (`Record`, optional) -- an set of modules to import globally - `terms` (`GlossaryTerm[]`, optional) -- `variables` (`Variables`, optional) -- An object containing [user variables}(https://github.com/readmeio/variable). +- `variables` (`Variables`, optional) -- an object containing [user variables](https://github.com/readmeio/variable) ### `RMDXModule` ###### Properties -- `default` (`() => MDXContent`) -- The mdx douments default export -- `toc` (`HastHeading[]`) -- A list of headings in the document -- `Toc` (`() => MDCContent`) -- A table of contents component +- `default` (`() => MDXContent`) -- the MDX douments default export +- `toc` (`HastHeading[]`) -- a list of headings in the document +- `Toc` (`() => MDCContent`) -- a table of contents component ## Flavored Syntax -~~Our old editor rendered "Magic Block" components from a custom, JSON-based syntax. To provide seamless backwards-compatibility, our new processor ships with built in support for parsing this old format, and transpiles it straight in to our new, flavored Markdown.~~ - -We've also sprinkled a bit of our own syntactic sugar on top to let you supercharge your docs. [**Learn more about ReadMe's flavored syntax!**](https://docs.readme.com/rdmd/docs/syntax-extensions) +We've also sprinkled a bit of our own custom components in to help you supercharge your docs. [**Learn more about ReadMe's new MDX engine!**](https://docs.readme.com/rdmd/page/mdx-engine) ## Local Development @@ -131,8 +119,3 @@ If you make changes to the docs or how the markdown is rendered, you may need to ``` make updateSnapshot ``` - -## Credits - -- **License**: MIT -- **Authors**: [Dom Harrington](https://github.com/domharrington/), [Rafe Goldberg](https://github.com/rafegoldberg) diff --git a/__tests__/__snapshots__/index.test.js.snap b/__tests__/__snapshots__/index.test.js.snap index a7330bb0b..c022784ac 100644 --- a/__tests__/__snapshots__/index.test.js.snap +++ b/__tests__/__snapshots__/index.test.js.snap @@ -335,7 +335,7 @@ exports[`export multiple Markdown renderers > renders plain markdown as React 1` exports[`heading 1`] = `"

Example Header

"`; -exports[`image 1`] = `"Image"`; +exports[`image 1`] = `"Image"`; exports[`list items 1`] = ` "
    diff --git a/__tests__/compilers/images.test.ts b/__tests__/compilers/images.test.ts index 84b8a4b4a..f7db0cdd7 100644 --- a/__tests__/compilers/images.test.ts +++ b/__tests__/compilers/images.test.ts @@ -18,4 +18,10 @@ describe('image compiler', () => { expect(mdx(mdast(doc))).toMatch(doc); }); + + it('correctly serializes an Image component with expression attributes back to MDX', () => { + const doc = ''; + + expect(mdx(mdast(doc))).toMatch(doc); + }); }); diff --git a/__tests__/components/Image.test.tsx b/__tests__/components/Image.test.tsx index 6e3f9f4a9..0bc47dc43 100644 --- a/__tests__/components/Image.test.tsx +++ b/__tests__/components/Image.test.tsx @@ -10,7 +10,7 @@ describe('Image', () => { expect(screen.getByRole('img')).toMatchInlineSnapshot(` { > Embed 3`] = `""`; -exports[`Components > Image 1`] = `"Bro eats pizza and makes an OK gesture."`; +exports[`Components > Image 1`] = `"Bro eats pizza and makes an OK gesture."`; diff --git a/components/Image/index.tsx b/components/Image/index.tsx index a4a983893..338b3cce3 100644 --- a/components/Image/index.tsx +++ b/components/Image/index.tsx @@ -16,7 +16,7 @@ interface ImageProps { const Image = (Props: ImageProps) => { const { - align = 'center', + align = '', alt = '', border = false, caption, @@ -75,7 +75,7 @@ const Image = (Props: ImageProps) => { width={width} height={height} title={title} - className={`img img-align-center${border ? ' border' : ''}`} + className={`img img-align-center ${border ? 'border' : ''}`} alt={alt} loading={lazy ? 'lazy' : 'eager'} /> @@ -101,7 +101,7 @@ const Image = (Props: ImageProps) => { width={width} height={height} title={title} - className={`img img-align-${align}${border ? ' border' : ''}`} + className={`img ${align ? `img-align-${align}` : ''} ${border ? 'border' : ''}`} alt={alt} loading={lazy ? 'lazy' : 'eager'} /> diff --git a/components/Image/style.scss b/components/Image/style.scss index 516a9810c..9573e4047 100644 --- a/components/Image/style.scss +++ b/components/Image/style.scss @@ -37,10 +37,8 @@ &[alt~='align-left'] { @extend %img-align-left; } - - &[width='80%'], + &[align='middle'], // hack to fix Firefox; see: https://stackoverflow.com/a/45901819/1341949 &[align='center'], - &[align='middle'], &[alt~='align-center'] { @extend %img-align-center; } diff --git a/processor/utils.ts b/processor/utils.ts index 3cc6ac51f..4b92969db 100644 --- a/processor/utils.ts +++ b/processor/utils.ts @@ -1,6 +1,11 @@ -import { Node } from 'mdast'; -import { MdxJsxFlowElement, MdxJsxTextElement, MdxFlowExpression } from 'mdast-util-mdx'; -import { MdxJsxAttribute } from 'mdast-util-mdx-jsx'; +import type { Node } from 'mdast'; +import type { MdxJsxFlowElement, MdxJsxTextElement, MdxFlowExpression } from 'mdast-util-mdx'; +import type { + MdxJsxAttribute, + MdxJsxAttributeValueExpression, + MdxJsxAttributeValueExpressionData, +} from 'mdast-util-mdx-jsx'; +import mdast from '../lib/mdast'; /** * Formats the hProperties of a node as a string, so they can be compiled back into JSX/MDX. @@ -145,13 +150,39 @@ export const reformatHTML = (html: string, indent: number = 2): string => { export const toAttributes = (object: Record, keys: string[] = []): MdxJsxAttribute[] => { let attributes: MdxJsxAttribute[] = []; - Object.entries(object).forEach(([name, value]) => { - if (keys.length > 0 && !keys.includes(name)) return; + Object.entries(object).forEach(([name, v]) => { + if ((keys.length > 0 && !keys.includes(name)) || typeof v === 'undefined') return; + + let value: MdxJsxAttributeValueExpression | string; + + if (typeof v === 'string') { + value = v; + } else { + /* values can be null, undefined, string, or a expression, eg: + * + * ``` + * + * ``` + * + * Parsing the expression seems to only be done by the library + * `mdast-util-mdx-jsx`, and so the most straight forward way to parse + * the expression and get the appropriate AST is with our `mdast` + * function. + */ + const proxy = mdast(`{${v}}`); + const data = proxy.children[0].data as MdxJsxAttributeValueExpressionData; + + value = { + type: 'mdxJsxAttributeValueExpression', + value: v.toString(), + data, + }; + } attributes.push({ type: 'mdxJsxAttribute', name, - value: value as string, + value, }); });