-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: mdx-less reusable content (#811)
Adds support for Reusable Content! This PR adds a transformer to convert `html` nodes into `reusable-content` nodes. If the so named content node has been passed in via `reusableContent`, then the parsed `mdsat` is inserted into place. This PR also adds a compiler for writing back out to `md`. The syntax is meant to match html/JSX so we have compatibility with future MDX.
- Loading branch information
1 parent
a3d1ca5
commit cdebefd
Showing
11 changed files
with
174 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { mdast, md } from '../../index'; | ||
|
||
describe('reusable content compiler', () => { | ||
it('writes an undefined reusable content block back to markdown', () => { | ||
const doc = '<RMReusableContent name="undefined" />'; | ||
const tree = mdast(doc); | ||
|
||
expect(md(tree)).toMatch(doc); | ||
}); | ||
|
||
it('writes a defined reusable content block back to markdown', () => { | ||
const reusableContent = { | ||
defined: '# Whoa', | ||
}; | ||
const doc = '<RMReusableContent name="defined" />'; | ||
const tree = mdast(doc, { reusableContent }); | ||
|
||
expect(tree.children[0].children[0].type).toBe('heading'); | ||
expect(md(tree)).toMatch(doc); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
__tests__/transformers/__snapshots__/reusable-content.test.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`reusable content transfomer should replace a reusable content block if the block is provided 1`] = ` | ||
Object { | ||
"children": Array [ | ||
Object { | ||
"children": Array [ | ||
Object { | ||
"type": "text", | ||
"value": "Test", | ||
}, | ||
], | ||
"data": Object { | ||
"hProperties": Object { | ||
"id": "test", | ||
}, | ||
"id": "test", | ||
}, | ||
"depth": 1, | ||
"type": "heading", | ||
}, | ||
Object { | ||
"children": Array [ | ||
Object { | ||
"children": Array [ | ||
Object { | ||
"type": "text", | ||
"value": "link", | ||
}, | ||
], | ||
"title": null, | ||
"type": "link", | ||
"url": "http://example.com", | ||
}, | ||
], | ||
"type": "paragraph", | ||
}, | ||
], | ||
"name": "test", | ||
"type": "reusable-content", | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { mdast } from '../../index'; | ||
|
||
describe('reusable content transfomer', () => { | ||
it('should replace a reusable content block if the block is provided', () => { | ||
const reusableContent = { | ||
test: ` | ||
# Test | ||
[link](http://example.com) | ||
`, | ||
}; | ||
const md = ` | ||
Before | ||
<RMReusableContent name="test" /> | ||
After | ||
`; | ||
|
||
const tree = mdast(md, { reusableContent }); | ||
|
||
expect(tree.children[0].children[0].value).toBe('Before'); | ||
expect(tree.children[1]).toMatchSnapshot(); | ||
expect(tree.children[2].children[0].value).toBe('After'); | ||
}); | ||
|
||
it('should insert an empty node if the reusable content block is not defined', () => { | ||
const md = '<RMReusableContent name="not-defined" />'; | ||
const tree = mdast(md); | ||
|
||
expect(tree.children[0].type).toBe('reusable-content'); | ||
expect(tree.children[0].children).toStrictEqual([]); | ||
}); | ||
|
||
it('does not expand reusable content recursively', () => { | ||
const reusableContent = { | ||
test: '<RMReusableContent name="test" />', | ||
}; | ||
const md = '<RMReusableContent name="test" />'; | ||
const tree = mdast(md, { reusableContent }); | ||
|
||
expect(tree.children[0].children[0].type).toBe('reusable-content'); | ||
expect(tree.children[0].children[0].children).toStrictEqual([]); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { type, tag } from '../transform/reusable-content'; | ||
|
||
export default function ReusableContentCompiler() { | ||
const { Compiler } = this; | ||
const { visitors } = Compiler.prototype; | ||
|
||
visitors[type] = node => `<${tag} name="${node.name}" />`; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import reusableContent from './reusable-content'; | ||
import singleCodeTabs from './single-code-tabs'; | ||
import tableCellInlineCode from './table-cell-inline-code'; | ||
|
||
export const remarkTransformers = [singleCodeTabs]; | ||
export const remarkTransformers = [singleCodeTabs, reusableContent]; | ||
export const rehypeTransformers = [tableCellInlineCode]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { visit } from 'unist-util-visit'; | ||
|
||
export const type = 'reusable-content'; | ||
export const tag = 'RMReusableContent'; | ||
|
||
const regexp = new RegExp(`^\\s*<${tag} name="(?<name>.*)" />\\s*$`); | ||
|
||
const reusableContentTransformer = function () { | ||
const reusableContent = this.data('reusableContent'); | ||
|
||
return tree => { | ||
visit(tree, 'html', (node, index, parent) => { | ||
const result = regexp.exec(node.value); | ||
if (!result || !result.groups.name) return; | ||
|
||
const { name } = result.groups; | ||
const block = { | ||
type, | ||
name, | ||
children: name in reusableContent ? reusableContent[name] : [], | ||
}; | ||
|
||
parent.children[index] = block; | ||
}); | ||
|
||
return tree; | ||
}; | ||
}; | ||
|
||
export default reusableContentTransformer; |