Post

Markdown으로 수식 파싱하기

📌 시작하며

현재 작업 물에서 Markdown으로 작성한 글을 HTML로 파싱할 필요가 있었다. 다른 h1태그들은 손 쉽게 가독성 있는 디자인을 적용했는데, 중첩된 리스트(ul, ol)는 .css파일을 이용해 더 직관적으로 표현할 필요가 있었다. 특히 순서가 있는 리스트인 ol의 경우 depth에 따라 1. 2. 3.1) 2) 3)① ② ③ 처럼 기호를 다르게 표시하는 것이 좋을 듯 하여 해당 구현 과정을 정리하고자 한다.

🔧 React-Markdown 커스터마이징

먼저 react-markdown 라이브러리를 사용할 때 ul, ol 태그를 직접 커스터마이징한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
export default function MarkdownRenderer({ content }: Props) {
  return (
    <Markdown
      remarkPlugins={[remarkGfm, remarkMath, remarkBreaks]}
      rehypePlugins={[
        rehypeRaw,
        [
          rehypeKatex as any,
          {
            throwOnError: false,
            strict: "ignore",
          },
        ],
      ]}
      components={{
        ul: ({ node, children, ...props }) => {
          const nested = hasNestedList(node)

          return (
            <ul
              {...props}
              className={cn("list-disc list-inside pl-4", {
                "space-y-3": nested,
              })}
            >
              {children}
            </ul>
          )
        },

        ol: ({ node, children, ...props }) => {
          const nested = hasNestedList(node)

          return (
            <ol
              {...props}
              className={cn("list-decimal list-inside pl-4", {
                "space-y-3": nested,
              })}
            >
              {children}
            </ol>
          )
        },
      }}
    >
      {content}
    </Markdown>
  )
}

💖 CSS를 이용한 커스터마이징

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/* li 내부 p 태그가 블록으로 줄바꿈 되는 것 방지 */
.markdown li > p {
  margin: 0;
  display: inline;
}

/* 1단계: 기본 1. 2. 3. */
.markdown ol {
  list-style: decimal;
  padding-left: 1.25rem;
}

/* 2단계: 1) 2) 3) */
.markdown ol ol {
  list-style: none;
  counter-reset: level2;
}

.markdown ol ol > li {
  counter-increment: level2;
}

.markdown ol ol > li::marker {
  content: counter(level2) ") ";
}

/* 3단계: ① ② ③ */
.markdown ol ol ol {
  list-style: none;
  counter-reset: level3;
}

.markdown ol ol ol > li {
  counter-increment: level3;
}

.markdown ol ol ol > li::marker {
  content: counter(level3, cjk-decimal) " ";
}

counter()란?

counter는 CSS 안에서 자동으로 번호를 세는 변수 시스템으로, HTML에 숫자를 쓰지 않아도 CSS가 알아서 숫자를 카운팅해준다.

단계역할
counter-reset카운터 시작값 초기화
counter-increment요소마다 +1 증가
counter()현재 숫자를 꺼내서 표시

::marker란?

::marker는 li 앞에 붙는 번호나 불릿만 선택하는 의사요소로 아래와 같이 커스텀 가능하다.

  • 숫자/불릿 색 변경 가능
  • 폰트 크기 가능
  • content 변경 가능

다만 박스처럼 움직이는 것은 불가능함에 주의한다.

counter와 marker를 이용해 숫자를 계산하고 화면에 표시할 수 있다.

💖 counter() 스타일

counter() 스타일예시
decimal1, 2, 3
lower-alphaa, b, c
upper-alphaA, B, C
lower-romani, ii, iii
upper-romanI, II, III
cjk-decimal①, ②, ③
korean-hangul-formal일, 이, 삼
This post is licensed under CC BY 4.0 by the author.