반응형

들어가며

remark? rehype?

  • remark는 Markdown을 처리하는 라이브러리
  • rehype는 HTML을 처리하는 라이브러리

markdown to html

모듈 설치

yarn add unified remark-parse remark-rehype rehype-stringify

코드

import unified from 'unified';
import remarkParse from 'remark-parse';
import remark2rehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';

const markdown = `
### Hello World
- AAA
    - AAA-1
    - AAA-2
- BBB
    - BBB-1
`;

const html = unified()
    .use(remarkParse)
    .use(remark2rehype)
    .use(rehypeStringify)
    .processSync(markdown)
    .toString();

console.log(html);

결과

<h3>Hello World</h3>
<ul>
<li>AAA
<ul>
<li>AAA-1</li>
<li>AAA-2</li>
</ul>
</li>
<li>BBB
<ul>
<li>BBB-1</li>
</ul>
</li>
</ul>

html to markdown

모듈 설치

yarn add unified rehype-parse rehype-remark remark-stringify

코드

import unified from 'unified';
import remarkStringify from 'remark-stringify';
import rehypeParse from 'rehype-parse';
import rehype2Remark from 'rehype-remark';

const html = `
<h3>Hello World</h3>
<ul>
<li>AAA
<ul>
<li>AAA-1</li>
<li>AAA-2</li>
</ul>
</li>
<li>BBB
<ul>
<li>BBB-1</li>
</ul>
</li>
</ul>
`;

const markdown = unified()
    .use(rehypeParse)
    .use(rehype2Remark)
    .use(remarkStringify, { bullet: '-', fance: '`', fances: true })
    .processSync(html)
    .toString();

console.log(markdown);

결과

### Hello World

- AAA

    - AAA-1
    - AAA-2

- BBB

    - BBB-1

remark, rehype 노드 구조

remark, rehype 트리 출력하기

const html = unified()
    .use(remarkParse)
    .use((options) => (remarkTree) => console.log(JSON.stringify(remarkTree))) // 추가
    .use(remark2rehype)
    .use((options) => (rehypeTree) => console.log(JSON.stringify(rehypeTree))) // 추가
    .use(rehypeStringify)
    .processSync(markdown)
    .toString();

remark 노드 구조 예시

{
    "type": "root",
    "children": [
        {
            "type": "heading",
            "depth": 3,
            "children": [
                {
                    "type": "text",
                    "value": "Hello World",
                    "position": {
                        "start": {
                            "line": 2,
                            "column": 5,
                            "offset": 5
                        },
                        "end": {
                            "line": 2,
                            "column": 16,
                            "offset": 16
                        }
                    }
                }
            ],
            "position": {
                "start": {
                    "line": 2,
                    "column": 1,
                    "offset": 1
                },
                "end": {
                    "line": 2,
                    "column": 16,
                    "offset": 16
                }
            }
        }
    ]
}

rehype 노드 구조 예시

{
    "type": "root",
    "children": [
        {
            "type": "element",
            "tagName": "h3",
            "properties": {},
            "children": [
                {
                    "type": "text",
                    "value": "Hello World",
                    "position": {
                        "start": {
                            "line": 2,
                            "column": 5,
                            "offset": 5
                        },
                        "end": {
                            "line": 2,
                            "column": 16,
                            "offset": 16
                        }
                    }
                }
            ],
            "position": {
                "start": {
                    "line": 2,
                    "column": 1,
                    "offset": 1
                },
                "end": {
                    "line": 2,
                    "column": 16,
                    "offset": 16
                }
            }
        }
    ]
}

기타

html 포맷팅을 하고싶다면?

yarn add rehype-format
import rehypeFormat from 'rehype-format';

const html = unified()
    .use(remarkParse)
    .use(remark2rehype)
    .use(rehypeFormat) // 추가
    .use(rehypeStringify)
    .processSync(markdown)
    .toString();

console.log(html);
<h3>Hello World</h3>
<ul>
  <li>AAA
    <ul>
      <li>AAA-1</li>
      <li>AAA-2</li>
    </ul>
  </li>
  <li>BBB
    <ul>
      <li>BBB-1</li>
    </ul>
  </li>
</ul>

노드 조작을 하고싶다면?

yarn add unist-util-visit
import visit from 'unist-util-visit';

const html = unified()
    .use(remarkParse)
    .use((options) => (tree) => {
        // 추가
        visit(
            tree,
            (node) => node.type === 'text',
            (node) => (node.value = node.value + '~!!'),
        );
    })
    .use(remark2rehype)
    .use(rehypeFormat)
    .use(rehypeStringify)
    .processSync(markdown)
    .toString();

console.log(html);
<h3>Hello World~!!</h3>
<ul>
  <li>AAA~!!
    <ul>
      <li>AAA-1~!!</li>
      <li>AAA-2~!!</li>
    </ul>
  </li>
  <li>BBB~!!
    <ul>
      <li>BBB-1~!!</li>
    </ul>
  </li>
</ul>

참고

반응형

'Development > JS' 카테고리의 다른 글

[BackboneJS] 예제  (0) 2021.06.26
[Javascript] Selection & Range  (0) 2021.01.05

+ Recent posts