Skip to content

Commit ac4cc63

Browse files
Merge pull request #18 from remarkjs/feat/sync-api
feat: add use remark sync hook
2 parents 2c8b1cd + 206e25f commit ac4cc63

File tree

11 files changed

+11719
-10419
lines changed

11 files changed

+11719
-10419
lines changed

.github/workflows/gh-page.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
- name: Use Node
1818
uses: actions/setup-node@v2
1919
with:
20-
node-version: 15
20+
node-version: 16
2121

2222
- name: Use cached node_modules
2323
uses: actions/cache@v2

.github/workflows/main.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
strategy:
1212
matrix:
1313
platform: [ubuntu-latest, windows-latest, macos-latest]
14-
node-version: [12, 14, 15]
14+
node-version: [12, 14, 16]
1515

1616
name: '${{ matrix.platform }}: node.js ${{ matrix.node-version }}'
1717

@@ -46,7 +46,7 @@ jobs:
4646
CI: true
4747

4848
- name: Test
49-
run: npm test --ci --coverage --maxWorkers=2
49+
run: npm test -- --ci --coverage --maxWorkers=2
5050
env:
5151
CI: true
5252

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
.DS_Store
33
node_modules
44
.cache
5-
dist
6-
storybook-static
5+
dist/
6+
storybook-static/
7+
coverage/

.husky/.gitignore

Lines changed: 0 additions & 1 deletion
This file was deleted.

package-lock.json

Lines changed: 11020 additions & 10402 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

readme.md

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const ExampleComponent = () => {
3535

3636
useEffect(() => {
3737
setMarkdownSource('# markdown header');
38-
}, [])
38+
}, []);
3939

4040
return reactContent;
4141
};
@@ -66,6 +66,23 @@ const ExampleComponent = () => {
6666
export default ExampleComponent;
6767
```
6868

69+
### Server side rendering
70+
71+
```tsx
72+
import React from 'react';
73+
import { useRemarkSync } from 'react-remark';
74+
75+
const ExampleComponent = () => {
76+
const reactContent = useRemarkSync('# markdown header');
77+
78+
return reactContent;
79+
};
80+
81+
export default ExampleComponent;
82+
```
83+
84+
:notebook: Note that some remark plugins are async, these plugins will error if used with `useRemarkSync`.
85+
6986
[More examples of usage as hook in storybook.](https://remarkjs.github.io/react-remark/?path=/story/remark-hook)
7087

7188
### As a component
@@ -155,13 +172,12 @@ import rehypeAutoLinkHeadings from 'rehype-autolink-headings';
155172
// ...
156173

157174
const [reactContent, setMarkdownSource] = useRemark({
158-
remarkParseOptions: { commonmark: true },
159175
remarkPlugins: [remarkGemoji],
160-
remarkToRehypeOptions: { commonmark: true },
176+
remarkToRehypeOptions: { allowDangerousHtml: true },
161177
rehypePlugins: [rehypeSlug, rehypeAutoLinkHeadings],
162178
rehypeReactOptions: {
163179
components: {
164-
p: props => <p className="custom-paragraph" {...props} />,
180+
p: (props) => <p className="custom-paragraph" {...props} />,
165181
},
166182
},
167183
});
@@ -179,13 +195,12 @@ import rehypeAutoLinkHeadings from 'rehype-autolink-headings';
179195
// ...
180196

181197
<Remark
182-
remarkParseOptions={{ commonmark: true }}
183198
remarkPlugins={[remarkGemoji]}
184-
remarkToRehypeOptions={{ commonmark: true }}
199+
remarkToRehypeOptions={{ allowDangerousHtml: true }}
185200
rehypePlugins={[rehypeSlug, rehypeAutoLinkHeadings]}
186201
rehypeReactOptions={{
187202
components: {
188-
p: props => <p className="custom-paragraph" {...props} />,
203+
p: (props) => <p className="custom-paragraph" {...props} />,
189204
},
190205
}}
191206
>

src/index.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,40 @@ import rehypeReact, { Options as RehypeReactOptions } from 'rehype-react';
1515

1616
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
1717

18-
export interface UseRemarkOptions {
19-
remarkParseOptions?: Partial<RemarkParseOptions>;
18+
export interface UseRemarkSyncOptions {
19+
remarkParseOptions?: RemarkParseOptions;
2020
remarkToRehypeOptions?: RemarkRehypeOptions;
2121
rehypeReactOptions?: PartialBy<
2222
RehypeReactOptions<typeof createElement>,
2323
'createElement'
2424
>;
2525
remarkPlugins?: PluggableList;
2626
rehypePlugins?: PluggableList;
27+
}
28+
29+
export const useRemarkSync = (
30+
source: string,
31+
{
32+
remarkParseOptions,
33+
remarkToRehypeOptions,
34+
rehypeReactOptions,
35+
remarkPlugins = [],
36+
rehypePlugins = [],
37+
}: UseRemarkOptions = {}
38+
): ReactElement =>
39+
unified()
40+
.use(remarkParse, remarkParseOptions)
41+
.use(remarkPlugins)
42+
.use(remarkToRehype, remarkToRehypeOptions)
43+
.use(rehypePlugins)
44+
.use(rehypeReact, {
45+
createElement,
46+
Fragment,
47+
...rehypeReactOptions,
48+
} as RehypeReactOptions<typeof createElement>)
49+
.processSync(source).result as ReactElement;
50+
51+
export interface UseRemarkOptions extends UseRemarkSyncOptions {
2752
onError?: (err: Error) => void;
2853
}
2954

stories/remark-hook-async.stories.tsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { useEffect } from 'react';
2+
import remarkGfm from 'remark-gfm';
3+
import remarkMath from 'remark-math';
4+
import rehypeKatex from 'rehype-katex';
5+
import rehypeRaw from 'rehype-raw';
6+
import rehypeSanitize from 'rehype-sanitize';
7+
import 'katex/dist/katex.min.css';
8+
9+
import { useRemarkSync } from '../src';
10+
11+
export default {
12+
title: 'Remark Hooks/sync and ssr with useRemarkSync',
13+
component: useRemarkSync,
14+
};
15+
16+
export const CommonMark = ({ content }) => {
17+
return useRemarkSync(content);
18+
};
19+
CommonMark.args = {
20+
content: `# header
21+
22+
1. ordered
23+
2. list
24+
25+
* unordered
26+
* list`,
27+
};
28+
29+
export const GithubFlavoredMarkdown = ({ content }) => {
30+
return (
31+
useRemarkSync(content, {
32+
remarkPlugins: [remarkGfm],
33+
}) || <></>
34+
);
35+
};
36+
GithubFlavoredMarkdown.args = {
37+
content: `# header
38+
39+
| column 1 | column 2 |
40+
| -------- | -------- |
41+
| first | row |
42+
`,
43+
};
44+
45+
export const MarkdownWithMath = ({ content }) => {
46+
return useRemarkSync(content, {
47+
remarkPlugins: [remarkMath],
48+
rehypePlugins: [rehypeKatex],
49+
});
50+
};
51+
MarkdownWithMath.args = {
52+
content: `Lift($L$) can be determined by Lift Coefficient ($C_L$) like the following equation.
53+
54+
$$
55+
L = \\frac{1}{2} \\rho v^2 S C_L
56+
$$`,
57+
};
58+
59+
export const MixedHTMLSanitized = ({ content }) => {
60+
return useRemarkSync(content, {
61+
remarkToRehypeOptions: { allowDangerousHtml: true },
62+
rehypePlugins: [rehypeRaw, rehypeSanitize],
63+
});
64+
};
65+
MixedHTMLSanitized.args = {
66+
content: `# header
67+
68+
<strong>mixed</strong>
69+
<em>with</em>
70+
<kbd>html</kbd>`,
71+
};

stories/remark-hook.stories.tsx renamed to stories/remark-hook-sync.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import 'katex/dist/katex.min.css';
99
import { useRemark } from '../src';
1010

1111
export default {
12-
title: 'Remark Hook',
12+
title: 'Remark Hooks/standard use with useRemark',
1313
component: useRemark,
1414
};
1515

0 commit comments

Comments
 (0)