Skip to content

Commit

Permalink
Merge branch 'beta' into beta-toc
Browse files Browse the repository at this point in the history
  • Loading branch information
kellyjosephprice committed May 23, 2024
2 parents d410092 + 6432be8 commit 43d4e60
Show file tree
Hide file tree
Showing 18 changed files with 135 additions and 55 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 49 additions & 0 deletions __tests__/compilers/compatability.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { mdx } from '../../index';

describe('compatability with RDMD', () => {
it('compiles variable nodes', () => {
const ast = {
type: 'readme-variable',
text: 'parliament',
data: {
hName: 'readme-variable',
hProperties: {
variable: 'parliament',
},
},
};

expect(mdx(ast).trim()).toBe('<Variable name="parliament" />');
});

it('compiles glossary nodes', () => {
const ast = {
type: 'readme-glossary-item',
data: {
hProperties: {
term: 'parliament',
},
},
};

expect(mdx(ast).trim()).toBe('<Glossary>parliament</Glossary>');
});

it('compiles reusable-content nodes', () => {
const ast = {
type: 'reusable-content',
tag: 'Parliament',
};

expect(mdx(ast).trim()).toBe('<Parliament />');
});

it('compiles html comments to JSX comments', () => {
const ast = {
type: 'html',
value: '<!-- commentable -->',
};

expect(mdx(ast).trim()).toBe('{/* commentable */}');
});
});
3 changes: 1 addition & 2 deletions __tests__/components/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { cleanup, fireEvent, render } from '@testing-library/react';
import React from 'react';
import { vi } from 'vitest';

import { execute } from '../helpers';

Expand Down Expand Up @@ -32,7 +31,7 @@ describe('Components', () => {
({ container } = render(React.createElement(component)));

expect(container.innerHTML).toMatchInlineSnapshot(
`"<blockquote class="callout callout_warn" theme="🚧"><h3 class="callout-heading empty"><span class="callout-icon">🚧</span></h3><p>Callout with no title.</p></blockquote>"`,
`"<blockquote class="callout callout_warn" theme="🚧"><h3 class="callout-heading empty"><span class="callout-icon">🚧</span></h3><p></p><p>Callout with no title.</p></blockquote>"`,
);

cleanup();
Expand Down
11 changes: 9 additions & 2 deletions __tests__/parsers/__snapshots__/callouts.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ exports[`Parse RDMD Callouts > renders an info callout 1`] = `
},
},
"type": "text",
"value": "ℹ️ Info Callout",
"value": "Info Callout",
},
],
"position": {
Expand Down Expand Up @@ -72,6 +72,13 @@ exports[`Parse RDMD Callouts > renders an info callout 1`] = `
"type": "paragraph",
},
],
"data": {
"hName": "Callout",
"hProperties": {
"empty": false,
"icon": "ℹ️",
},
},
"position": {
"end": {
"column": 60,
Expand All @@ -84,7 +91,7 @@ exports[`Parse RDMD Callouts > renders an info callout 1`] = `
"offset": 1,
},
},
"type": "blockquote",
"type": "rdme-callout",
},
],
"position": {
Expand Down
32 changes: 10 additions & 22 deletions __tests__/parsers/callouts.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { mdast } from '../../index';

describe.skip('Parse RDMD Callouts', () => {
describe('Parse RDMD Callouts', () => {
it('renders an info callout', () => {
const text = `
> ℹ️ Info Callout
Expand All @@ -10,18 +10,6 @@ describe.skip('Parse RDMD Callouts', () => {
expect(mdast(text)).toMatchSnapshot();
});

it('supports a default theme', () => {
const text = `
> 🥇 Themeless
>
> Lorem ipsum dolor sit amet consectetur adipisicing elit.`;

const tree = mdast(text);

expect(tree.children[0].type).toBe('rdme-callout');
expect(tree.children[0].data.hProperties.theme).toBe('default');
});

it('parses a callout with no title', () => {
const text = `
> ℹ️
Expand All @@ -31,8 +19,8 @@ describe.skip('Parse RDMD Callouts', () => {
const tree = mdast(text);

expect(tree.children[0].type).toBe('rdme-callout');
expect(tree.children[0].data.hProperties.theme).toBe('info');
expect(tree.children[0].data.hProperties.title).toBe('');
expect(tree.children[0].data.hProperties.icon).toBe('ℹ️');
expect(tree.children[0].data.hProperties.empty).toBe(true);
});

describe('edge cases', () => {
Expand All @@ -44,8 +32,8 @@ describe.skip('Parse RDMD Callouts', () => {
`;

const tree = mdast(text);
expect(tree.children[0].data.hProperties.value).toBe('<span>With html!</span>');
expect(tree.children[0].children[1].children[0].type).toBe('html');
expect(tree.children[0].children[1].children[0].children[0].value).toBe('With html!');
expect(tree.children[0].children[1].children[0].type).toBe('mdxJsxTextElement');
});

it('allows trailing spaces after the icon', () => {
Expand All @@ -56,7 +44,7 @@ describe.skip('Parse RDMD Callouts', () => {
const tree = mdast(text);
expect(tree.children[0].data.hProperties.icon).toBe('🛑');
expect(tree.children[0].children[0].children[0].value).toBe(
'Compact headings must be followed by two line breaks before the following block.'
'Compact headings must be followed by two line breaks before the following block.',
);
});
});
Expand All @@ -83,20 +71,20 @@ describe.skip('Parse RDMD Callouts', () => {
expect(tree.children[0].children[0].children[1].type).toBe('rdme-callout');
});

it('does not require a line break between the title and the body', () => {
it('does require a line break between the title and the body', () => {
const text = `
> 💁 Undocumented Behavior
> Lorem ipsum dolor sit amet consectetur adipisicing elit.`;

const tree = mdast(text);
expect(tree.children[0].data.hProperties.title).toBe(
expect(tree.children[0].children[0].children[0].value).toBe(
`Undocumented Behavior
Lorem ipsum dolor sit amet consectetur adipisicing elit.`
Lorem ipsum dolor sit amet consectetur adipisicing elit.`,
);
});
});

describe.skip('emoji modifier support', () => {
describe('emoji modifier support', () => {
const emojis = ['📘', '🚧', '⚠️', '👍', '✅', '❗️', '❗', '🛑', '⁉️', '‼️', 'ℹ️', '⚠'];

emojis.forEach(emoji => {
Expand Down
2 changes: 1 addition & 1 deletion __tests__/transformers/callouts.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { mdast, hast } from '../../index';
import { mdast } from '../../index';

describe('callouts transformer', () => {
it('can parse callouts', () => {
Expand Down
5 changes: 4 additions & 1 deletion __tests__/transformers/readme-components.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ describe('Readme Components Transformer', () => {
const docs = {
['rdme-callout']: {
md: `> 📘 It works!`,
mdx: `<Callout icon="📘" heading="It works!" />`,
mdx: `
<Callout icon="📘">
It works!
</Callout>`,
},
code: {
md: `
Expand Down
11 changes: 4 additions & 7 deletions components/Callout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ interface Props extends React.PropsWithChildren<React.HTMLAttributes<HTMLQuoteEl
attributes?: {};
icon: string;
theme?: string;
heading?: React.ReactElement;
empty?: boolean;
}

const themes: Record<string, string> = {
Expand All @@ -23,20 +23,17 @@ const themes: Record<string, string> = {
};

const Callout = (props: Props) => {
const { attributes, children, icon } = props;

const { attributes, children, icon, empty } = props;
let theme = props.theme || themes[icon] || 'default';
const [heading, ...body] = Array.isArray(children) ? children : [children];
const empty = !heading.props.children;

return (
// @ts-ignore
<blockquote {...attributes} className={`callout callout_${theme}`} theme={icon}>
<h3 className={`callout-heading${empty ? ' empty' : ''}`}>
<span className="callout-icon">{icon}</span>
{!empty && heading}
{empty || children[0]}
</h3>
{body}
{empty ? children : React.Children.toArray(children).slice(1)}
</blockquote>
);
};
Expand Down
6 changes: 4 additions & 2 deletions docs/callout-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ hidden: true
> - was only rendering
> - one child
<Callout heading="Now with MDX" theme="error" icon="🔥">
### Even supports markdown
<Callout theme="error" icon="🔥">
Now with MDX

### Even supports markdown

Much _wow_
</Callout>
5 changes: 4 additions & 1 deletion enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ export enum NodeTypes {
i = 'i',
image = 'image',
htmlBlock = 'html-block',
embed = 'rdme-embed'
embed = 'rdme-embed',
variable = 'readme-variable',
glossary = 'readme-glossary-item',
reusableContent = 'reusable-content',
}
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
},
"peerDependencies": {
"@mdx-js/react": "^3.0.0",
"@readme/variable": "^16.0.0",
"@readme/variable": "^16.1.0",
"@tippyjs/react": "^4.1.0",
"react": "16.x || 17.x || 18.x",
"react-dom": "16.x || 17.x || 18.x"
Expand Down
25 changes: 25 additions & 0 deletions processor/compile/compatibility.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Html } from 'mdast';
import { NodeTypes } from '../../enums';

type CompatNodes =
| { type: NodeTypes.variable; text: string }
| { type: NodeTypes.glossary; data: { hProperties: { term: string } } }
| { type: NodeTypes.reusableContent; tag: string }
| Html;

const compatibility = (node: CompatNodes) => {
switch (node.type) {
case NodeTypes.variable:
return `<Variable name="${node.text}" />`;
case NodeTypes.glossary:
return `<Glossary>${node.data.hProperties.term}</Glossary>`;
case NodeTypes.reusableContent:
return `<${node.tag} />`;
case 'html':
return node.value.replaceAll(/<!--(.*)-->/g, '{/*$1*/}');
default:
throw new Error('Unhandled node type!');
}
};

export default compatibility;
5 changes: 5 additions & 0 deletions processor/compile/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import embed from './embed';
import gemoji from './gemoji';
import htmlBlock from './html-block';
import image from './image';
import compatibility from './compatibility';
import { NodeTypes } from '../../enums';

function compilers() {
Expand All @@ -18,6 +19,10 @@ function compilers() {
[NodeTypes.embed]: embed,
[NodeTypes.htmlBlock]: htmlBlock,
[NodeTypes.image]: image,
[NodeTypes.variable]: compatibility,
[NodeTypes.glossary]: compatibility,
[NodeTypes.reusableContent]: compatibility,
html: compatibility,
};

toMarkdownExtensions.push({ extensions: [{ handlers }] });
Expand Down
17 changes: 10 additions & 7 deletions processor/transform/callouts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,18 @@ const calloutTransformer = () => {

if (icon && match) {
const heading = startText.slice(match.length);

node.children[0].children[0].value = heading;
node.type = NodeTypes.callout;
node.data = {
hName: 'Callout',
hProperties: {
icon,

Object.assign(node, {
type: NodeTypes.callout,
data: {
hName: 'Callout',
hProperties: {
icon,
empty: !heading.length,
},
},
};
});
}
});
};
Expand Down
8 changes: 3 additions & 5 deletions processor/transform/readme-components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,15 @@ const coerceJsxToMd =

parent.children[index] = mdNode;
} else if (node.name === 'Callout') {
const { heading, icon } = attributes<{ heading?: string; icon: string }>(node);

const child = mdast(heading);
const { icon, empty = false } = attributes<{ empty?: boolean; icon: string }>(node);

// @ts-ignore
const mdNode: Callout = {
children: [child?.children?.[0], ...node.children].filter(Boolean) as any,
children: node.children as any,
type: NodeTypes.callout,
data: {
hName: node.name,
hProperties: { icon },
hProperties: { icon, empty },
},
position: node.position,
};
Expand Down
1 change: 1 addition & 0 deletions types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type Callout = Omit<Blockquote, 'type'> & {
hName: 'Callout';
hProperties: {
icon: string;
empty: boolean;
};
};
};
Expand Down

0 comments on commit 43d4e60

Please sign in to comment.