Skip to content

Commit a2800d2

Browse files
authored
Merge pull request #27 from jasononeil/feature/plugins-for-webpack1
Allow MarkdownIt plugins to be supplied as Strings rather than functions
2 parents 54e59fe + e354952 commit a2800d2

File tree

4 files changed

+339
-8
lines changed

4 files changed

+339
-8
lines changed

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ module.exports = {
138138

139139
* `passElementProps`: Controls whether props can be passed from the parent to the generated elements. Defaults to `false`.
140140
* `implicitlyImportReact`: Whether to include React and PropTypes in the imports automatically. If set to `false`, you need to either supply React and PropTypes or import them explicitly. Defaults to `true`.
141-
* `markdownItPlugins`: An array of [MarkdownIt plugin instances](https://www.npmjs.org/browse/keyword/markdown-it-plugin) (and optionally their additional arguments) to use within the markdown renderer. As these are functions, this option is only able to be used via the Webpack configuration object.
141+
* `markdownItPlugins`: An array of [MarkdownIt plugins](https://www.npmjs.org/browse/keyword/markdown-it-plugin) (and optionally their additional arguments) to use within the markdown renderer. These can be specified either as instances, or as paths as returned by `require.resolve`.
142142

143143
##### MarkdownIt Plugins
144144

@@ -159,6 +159,24 @@ If you supply an array of [MarkdownIt plugins](https://www.npmjs.org/browse/keyw
159159

160160
The configuration above will supply both [`markdown-it-anchor`](https://www.npmjs.com/package/markdown-it-anchor) and [`markdown-it-table-of-contents`](https://www.npmjs.com/package/markdown-it-table-of-contents) to MarkdownIt's `use` method. `markdown-it-table-of-contents` is supplied within an array, and the entire array is passed as the arguments to `use`, allowing specifying plugin configurations.
161161

162+
###### Legacy Webpack compatibility
163+
164+
For compatibility with Webpack 1.x, where plugin configuration must be JSON compatible, plugins can be passed as path strings rather than the plugin object itself.
165+
166+
The equivalent of the example above in Webpack 1.x would be as follows.
167+
168+
```javascript
169+
module.exports = {
170+
markdownComponentLoader: {
171+
markdownItPlugins: [
172+
require.resolve('markdown-it-anchor'),
173+
[require.resolve('markdown-it-table-of-contents'), { containerClass: 'my-container-class' }]
174+
]
175+
},
176+
{...more}
177+
};
178+
```
179+
162180
### Styling and Interaction
163181

164182
#### Container Styling

src/__snapshots__/convert.spec.js.snap

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,302 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`convert accepts plugins specified as a string has the expected preamble 1`] = `
4+
"
5+
import React from 'react';
6+
import PropTypes from 'prop-types';
7+
8+
MarkdownComponent.propTypes = {
9+
className: PropTypes.string,
10+
style: PropTypes.object
11+
};
12+
13+
MarkdownComponent['title'] = 'Markdown Component Loader';
14+
15+
"
16+
`;
17+
18+
exports[`convert accepts plugins specified as a string renders as expected within React 1`] = `
19+
Object {
20+
"propTypes": Object {
21+
"className": [Function],
22+
"style": [Function],
23+
},
24+
"title": "Markdown Component Loader",
25+
}
26+
`;
27+
28+
exports[`convert accepts plugins specified as a string renders as expected within React 2`] = `
29+
<div
30+
className={undefined}
31+
style={undefined}
32+
>
33+
<center>
34+
<h1>
35+
<img
36+
alt="Markdown Component Loader"
37+
id="logo"
38+
src={Object {}}
39+
/>
40+
</h1>
41+
<p>
42+
A Webpack loader that turns Markdown into dynamic, stateless React components!
43+
</p>
44+
<p>
45+
<a
46+
className="bubble-link github-link"
47+
href="https://github.com/ticky/markdown-component-loader"
48+
>
49+
Check it out on GitHub
50+
</a>
51+
</p>
52+
</center>
53+
<h3
54+
id="welcomemdx"
55+
>
56+
welcome.mdx
57+
</h3>
58+
<pre>
59+
<code
60+
className="language-markdown"
61+
>
62+
<span
63+
className="emphasis"
64+
>
65+
Hey there **
66+
{{ props.who }}
67+
** ✌🏼
68+
</span>
69+
<br />
70+
</code>
71+
</pre>
72+
<h3
73+
id="appjsx"
74+
>
75+
app.jsx
76+
</h3>
77+
<pre>
78+
<code
79+
className="language-jsx"
80+
>
81+
<span
82+
className="emphasis"
83+
>
84+
import Welcome from './welcome.mdx';
85+
</span>
86+
<br />
87+
88+
<br />
89+
ReactDOM.render(
90+
<br />
91+
<span
92+
className="emphasis"
93+
>
94+
&lt;Welcome who="Monkey Magic" /&gt;,
95+
</span>
96+
<br />
97+
document.getElementById('app')
98+
<br />
99+
);
100+
<br />
101+
</code>
102+
</pre>
103+
<h3
104+
id="rendered"
105+
>
106+
Rendered:
107+
</h3>
108+
<pre>
109+
<code
110+
className="language-html"
111+
>
112+
<span
113+
className="hljs-tag"
114+
>
115+
&lt;
116+
<span
117+
className="hljs-name"
118+
>
119+
div
120+
</span>
121+
122+
<span
123+
className="hljs-attr"
124+
>
125+
id
126+
</span>
127+
=
128+
<span
129+
className="hljs-string"
130+
>
131+
"app"
132+
</span>
133+
&gt;
134+
</span>
135+
<br />
136+
<span
137+
className="emphasis"
138+
>
139+
&lt;p&gt;Hey there &lt;strong&gt;Monkey Magic&lt;/strong&gt; ✌🏼&lt;/p&gt;
140+
</span>
141+
<br />
142+
<span
143+
className="hljs-tag"
144+
>
145+
&lt;/
146+
<span
147+
className="hljs-name"
148+
>
149+
div
150+
</span>
151+
&gt;
152+
</span>
153+
<br />
154+
</code>
155+
</pre>
156+
<h2
157+
id="what-else-can-it-do"
158+
>
159+
What else can it do?
160+
</h2>
161+
<p>
162+
Use JSX within Markdown. Plus import objects such as shared snippets, fancy library functions or even whole React components, using YAML front-matter:
163+
</p>
164+
<pre>
165+
<code
166+
className="language-markdown"
167+
>
168+
---
169+
<br />
170+
<span
171+
className="emphasis"
172+
>
173+
imports:
174+
</span>
175+
<br />
176+
<span
177+
className="emphasis"
178+
>
179+
numberFormat: number-format
180+
</span>
181+
<br />
182+
<span
183+
className="hljs-section"
184+
>
185+
<span
186+
className="emphasis"
187+
>
188+
Button: ui/button
189+
</span>
190+
<br />
191+
---
192+
</span>
193+
<br />
194+
<br />
195+
You are visitor number
196+
<span
197+
className="emphasis"
198+
>
199+
{{ numberFormat(1000000) }}
200+
</span>
201+
!
202+
<br />
203+
<br />
204+
<span
205+
className="emphasis"
206+
>
207+
&lt;Button path="/browser-info"&gt;Details&lt;/Button&gt;
208+
</span>
209+
<br />
210+
</code>
211+
</pre>
212+
<p>
213+
Destructured imports, with some added single quotes:
214+
</p>
215+
<pre>
216+
<code
217+
className="language-markdown"
218+
>
219+
---
220+
<br />
221+
imports:
222+
<br />
223+
<span
224+
className="hljs-section"
225+
>
226+
<span
227+
className="emphasis"
228+
>
229+
'{ window, document }': global
230+
</span>
231+
<br />
232+
---
233+
</span>
234+
<br />
235+
<br />
236+
Hello, your user agent is
237+
<span
238+
className="emphasis"
239+
>
240+
{{ window.navigator.userAgent }}
241+
</span>
242+
.
243+
<br />
244+
</code>
245+
</pre>
246+
<h2
247+
id="give-it-a-go"
248+
>
249+
Give it a go!
250+
</h2>
251+
<p>
252+
Want to see exactly what Markdown Component Loader will generate when it translates the mdx into a stateless React component?
253+
</p>
254+
<div
255+
className="repl-image"
256+
>
257+
<div>
258+
<a
259+
className="bubble-link white-bubble"
260+
href="repl.html"
261+
>
262+
Launch editor
263+
</a>
264+
</div>
265+
</div>
266+
<h2
267+
id="get-started"
268+
>
269+
Get started
270+
</h2>
271+
<p>
272+
Check out the
273+
<a
274+
href="https://github.com/ticky/markdown-component-loader"
275+
>
276+
GitHub Readme
277+
</a>
278+
for how to get started, including details on how to add styles and event handlers to the DOM nodes generated by the markdown, and other options for customizing the loader.
279+
</p>
280+
<center>
281+
<a
282+
className="bubble-link github-link"
283+
href="https://github.com/ticky/markdown-component-loader"
284+
>
285+
Check it out on GitHub
286+
</a>
287+
<hr />
288+
<p>
289+
Made with 💜 by
290+
<a
291+
href="https://twitter.com/ticky"
292+
>
293+
@ticky
294+
</a>
295+
</p>
296+
</center>
297+
</div>
298+
`;
299+
3300
exports[`convert doesn't trigger any kind of comment highlighting in highlights has the expected preamble 1`] = `
4301
"
5302
import React from 'react';

src/convert.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,15 @@ export default (source, config) => {
137137
if (config.markdownItPlugins && Array.isArray(config.markdownItPlugins)) {
138138
renderer = config.markdownItPlugins
139139
.reduce(
140-
(markdownRenderer, pluginDefinition) => (
141-
markdownRenderer.use(...(
142-
Array.isArray(pluginDefinition)
143-
? pluginDefinition
144-
: [pluginDefinition]
145-
))
146-
),
140+
(markdownRenderer, pluginDefinition) => {
141+
if (!Array.isArray(pluginDefinition)) {
142+
pluginDefinition = [pluginDefinition];
143+
}
144+
if (typeof pluginDefinition[0] === 'string') {
145+
pluginDefinition[0] = require(pluginDefinition[0]);
146+
}
147+
return markdownRenderer.use(...pluginDefinition);
148+
},
147149
renderer
148150
);
149151
}

src/convert.spec.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,18 @@ describe('convert', () => {
219219
`
220220
)).toThrowErrorMatchingSnapshot();
221221
});
222+
223+
describe('accepts plugins specified as a string', () => {
224+
RUN_ONE_FIXTURE(
225+
readFileSync(
226+
path.join(__dirname, '../app/Homepage.mdx'),
227+
{ encoding: 'utf-8' }
228+
),
229+
{
230+
markdownItPlugins: [
231+
path.relative(__dirname, require.resolve("markdown-it-anchor"))
232+
]
233+
}
234+
);
235+
});
222236
});

0 commit comments

Comments
 (0)