Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Commit 53b747a

Browse files
committed
feat(mdx): add block-start/end feature
1 parent 0542667 commit 53b747a

File tree

9 files changed

+189
-44
lines changed

9 files changed

+189
-44
lines changed

packages/mdx-loader/__tests__/__snapshots__/index.js.snap

+53
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,59 @@ export default function MDXContent({
124124
MDXContent.isMDXComponent = true;"
125125
`;
126126

127+
exports[`fusuma-loader should append div tag by block comment 1`] = `
128+
"/* @jsxRuntime classic */
129+
/* @jsx mdx */
130+
131+
import React from 'react';
132+
import { mdx } from '@mdx-js/react';
133+
export const slides = [props => <>
134+
135+
<div>
136+
<p>{\`out\`}</p>
137+
<div className=\\"foo\\">
138+
<p>{\`in
139+
in\`}</p>
140+
</div>
141+
<p>{\`out\`}</p>
142+
</div>
143+
144+
</>];
145+
export const fusumaProps = [{}];
146+
147+
const layoutProps = {
148+
149+
};
150+
const MDXLayout = \\"wrapper\\"
151+
export default function MDXContent({
152+
components,
153+
...props
154+
}) {
155+
return <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
156+
{
157+
/* block-start */
158+
}
159+
<p>{\`out\`}</p>
160+
{
161+
/* block-start: foo */
162+
}
163+
<p>{\`in
164+
in\`}</p>
165+
{
166+
/* block-end */
167+
}
168+
<p>{\`out\`}</p>
169+
{
170+
/* block-end */
171+
}
172+
173+
</MDXLayout>;
174+
}
175+
176+
;
177+
MDXContent.isMDXComponent = true;"
178+
`;
179+
127180
exports[`fusuma-loader should convert MathJax 1`] = `
128181
"/* @jsxRuntime classic */
129182
/* @jsx mdx */

packages/mdx-loader/__tests__/index.js

+15
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,19 @@ second
152152
`;
153153
expect(await transformToJS(src)).toMatchSnapshot();
154154
});
155+
156+
test('should append div tag by block comment', async () => {
157+
const src = `
158+
<!-- block-start -->
159+
out
160+
<!-- block-start: foo -->
161+
in
162+
in
163+
<!-- block-end -->
164+
out
165+
<!-- block-end -->
166+
`;
167+
168+
expect(await transformToJS(src)).toMatchSnapshot();
169+
});
155170
});

packages/mdx-loader/src/mdxPlugin.js

+32-42
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
'use strict';
22

3-
const qr = require('qrcode-generator');
43
const visit = require('unist-util-visit');
54
const mdxAstToMdxHast = require('@mdx-js/mdx/mdx-ast-to-mdx-hast');
65
const { toJSX } = require('@mdx-js/mdx/mdx-hast-to-jsx');
76
const createFusumaProps = require('./createFusumaProps');
8-
const transferMarkdownImageNodeToJSX = require('./transferMarkdownImageNodeToJSX');
7+
const transformQrToJSX = require('./transformers/transformQrToJSX');
8+
const transformScreenToJSX = require('./transformers/transformScreenToJSX');
9+
const transformChartToJSX = require('./transformers/transformChartToJSX');
10+
const transformMarkdownImageNodeToJSX = require('./transformers/transformMarkdownImageNodeToJSX');
911

1012
function mdxPlugin() {
1113
return (tree) => {
@@ -34,29 +36,17 @@ function mdxPlugin() {
3436
const attr = rest.map((r) => r.trim());
3537

3638
if (prefix === 'qr') {
37-
if (['http', 'https'].includes(attr[0])) {
38-
const url = `${attr[0]}:${attr[1]}`;
39-
const q = qr(0, 'L');
40-
q.addData(url);
41-
q.make();
42-
const svg = q.createSvgTag();
43-
44-
slide.push(
45-
...[
46-
n,
47-
{
48-
...n,
49-
type: 'jsx',
50-
value: svg
51-
.replace('width="58px"', '')
52-
.replace('height="58px"', '')
53-
.replace('<svg ', '<svg className="qr"'),
54-
},
55-
]
56-
);
57-
58-
return;
59-
}
39+
slide.push(
40+
...[
41+
n,
42+
{
43+
...n,
44+
...transformQrToJSX(attr),
45+
},
46+
]
47+
);
48+
49+
return;
6050
}
6151

6252
if (prefix === 'screen') {
@@ -65,19 +55,10 @@ function mdxPlugin() {
6555
n,
6656
{
6757
...n,
68-
type: 'jsx',
69-
value:
70-
'<div className="fusuma-screen">' +
71-
'<div>This view can capture the screen.<br />' +
72-
'Click to get started.;)<br /><br />' +
73-
'Note: This feature runs only in Presenter Mode.' +
74-
'</div>' +
75-
`<video id="fusuma-screen-${videoId}" />` +
76-
'</div>',
58+
...transformScreenToJSX(videoId),
7759
},
7860
]
7961
);
80-
8162
++videoId;
8263
return;
8364
}
@@ -87,11 +68,7 @@ function mdxPlugin() {
8768
if (lang === 'chart') {
8869
slide.push({
8970
...n,
90-
type: 'jsx',
91-
value: `<div className="mermaid" id="mermaid-${mermaidId}" data-value="${n.value.replace(
92-
/ {4}/g,
93-
''
94-
)}" style={{ visibility: 'hidden'}}>${n.value.replace(/ {4}/g, '')}</div>`,
71+
...transformChartToJSX(mermaidId, value),
9572
});
9673

9774
++mermaidId;
@@ -119,7 +96,8 @@ function mdxPlugin() {
11996

12097
visit(n, null, (node) => {
12198
if (node.type === 'image') {
122-
const { type, value } = transferMarkdownImageNodeToJSX(node);
99+
const { type, value } = transformMarkdownImageNodeToJSX(node);
100+
123101
node.type = type;
124102
node.value = value;
125103
delete node.alt;
@@ -145,9 +123,21 @@ function mdxPlugin() {
145123
type: 'root',
146124
children: slide,
147125
});
148-
const mdxJSX = toJSX(hash);
126+
let mdxJSX = toJSX(hash)
127+
// TODO: refactor
128+
.replace(/{\s.+\/\* block-end \*\/\s.+}/gm, '</div>');
129+
130+
const matches = mdxJSX.matchAll(/{\s.+\/\* block-start:?(.*?) \*\/\s.+}/gm);
131+
132+
for (const pos of matches) {
133+
const [, className] = pos;
134+
const div = className ? `<div className="${className.trim()}">` : '<div>';
135+
mdxJSX = mdxJSX.replace(/{\s.+\/\* block-start:?(.*?) \*\/\s.+}/m, div);
136+
}
137+
149138
// jsx variable is established, so we don't use babel/parser
150139
const jsx = mdxJSX.match(/<MDXLayout.+?>([\s\S]*)<\/MDXLayout>/m);
140+
151141
if (jsx) {
152142
const template = `
153143
(props) => (
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict';
2+
3+
function transformChartToJSX(mermaidId, value) {
4+
return {
5+
type: 'jsx',
6+
value: `<div className="mermaid" id="mermaid-${mermaidId}" data-value="${value.replace(
7+
/ {4}/g,
8+
''
9+
)}" style={{ visibility: 'hidden'}}>${value.replace(/ {4}/g, '')}</div>`,
10+
};
11+
}
12+
13+
module.exports = transformChartToJSX;

packages/mdx-loader/src/transferMarkdownImageNodeToJSX.js packages/mdx-loader/src/transformers/transformMarkdownImageNodeToJSX.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
const { toJSX } = require('@mdx-js/mdx/mdx-hast-to-jsx');
44
const mdxAstToMdxHast = require('@mdx-js/mdx/mdx-ast-to-mdx-hast');
55

6-
function transferMarkdownImageNodeToJSX(node) {
6+
function transformMarkdownImageNodeToJSX(node) {
77
const hash = mdxAstToMdxHast()(node);
88
const { src, alt } = hash.properties;
99
let jsx;
@@ -26,4 +26,4 @@ function transferMarkdownImageNodeToJSX(node) {
2626
};
2727
}
2828

29-
module.exports = transferMarkdownImageNodeToJSX;
29+
module.exports = transformMarkdownImageNodeToJSX;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
3+
const qr = require('qrcode-generator');
4+
5+
function transformQrToJSX(attr) {
6+
if (['http', 'https'].includes(attr[0])) {
7+
const url = `${attr[0]}:${attr[1]}`;
8+
const q = qr(0, 'L');
9+
q.addData(url);
10+
q.make();
11+
const svg = q.createSvgTag();
12+
13+
return {
14+
type: 'jsx',
15+
value: svg
16+
.replace('width="58px"', '')
17+
.replace('height="58px"', '')
18+
.replace('<svg ', '<svg className="qr"'),
19+
};
20+
}
21+
throw new Error('Invalid URL');
22+
}
23+
24+
module.exports = transformQrToJSX;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
'use stirct';
2+
3+
function transformScreenToJSX(videoId) {
4+
return {
5+
type: 'jsx',
6+
value:
7+
'<div className="fusuma-screen">' +
8+
'<div>This view can capture the screen.<br />' +
9+
'Click to get started.;)<br /><br />' +
10+
'Note: This feature runs only in Presenter Mode.' +
11+
'</div>' +
12+
`<video id="fusuma-screen-${videoId}" />` +
13+
'</div>',
14+
};
15+
}
16+
17+
module.exports = transformScreenToJSX;

samples/debug/slides/06-blocks.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!-- block-start: outer -->
2+
3+
outer
4+
5+
<!-- block-start: middle -->
6+
7+
middle
8+
9+
<!-- block-start: inner -->
10+
11+
inner
12+
13+
<!-- block-end -->
14+
15+
middle
16+
17+
<!-- block-end -->
18+
19+
outer
20+
21+
<!-- block-end -->

samples/debug/style.css

+12
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,15 @@ __body {
1919
height: 150px;
2020
width: 150px;
2121
}
22+
23+
.outer {
24+
color: red;
25+
}
26+
27+
.middle {
28+
color: blue;
29+
}
30+
31+
.inner {
32+
color: green;
33+
}

0 commit comments

Comments
 (0)