나만의 Markdown 언어를 사용하는 MDX 플러그인 만들기

어제 Imigrated my website from plain HTML to Next.js + MDX , HTML로 작성할 때 중복 및 상용구 문제를 해결했습니다. 그러나 Next.js + MDX를 사용하는 것은 단지 그것에 관한 것이 아니라 기술적으로 제한 없이 내 쓰기 프레임워크를 사용자 정의할 수 있는 문을 열었습니다(이 때문에 Medium/DEV.to/Hashnode에서 내 웹사이트로 마이그레이션했습니다. 처음).

어떻게?



TL;DR: Intercept Next.js and MDX pipeline, parse our custom syntax and write into supported syntax.



Next.js 및 MDX는 사용자 지정 및 유연성을 염두에 두고 설계 및 생성되었습니다.
  • Next.js는 React 서버 렌더링 페이지를 빌드하기 위한 파이프라인을 생성합니다. 무언가를 JSX(및 JavaScript 함수)로 변환할 수 있는 한 기술적으로 모든 것을 사용할 수 있습니다(MDX가 예입니다). Next.js는 또한 Webpack 및 Babel을 기반으로 구축되어 더 큰 플러그인 생태계에 액세스할 수 있습니다.
  • MDX는 Markdown 기반 구문을 JSX로 변환하는 파이프라인을 만듭니다. 콘텐츠(자연어, 마크다운 등)를 구조화된 데이터로 컴파일하는 기존 unifiedjs , remarkrehype 생태계와 함께 작동하도록 설계 및 구축되었습니다. 그런 다음 구조화된 데이터를 처리, 수정하고 기존 언어(JSX, MDX 등)로 작성할 수 있습니다.

  • 결합된 파이프라인은 다음과 같습니다.
  • 사용자 정의 Markdown 문서를 정의하고 작성합니다.
  • Next.js는 문서를 페이지로 읽고 MDX로 ​​보냅니다.
  • (여기서 가로채고 사용자 지정)
  • MDX가 문서를 Remark 및 Rehype로 보냅니다.
  • Remark는 문서를 MDXAST라는 데이터 구조로 변환합니다.
  • (여기서 가로채고 사용자 지정)
  • Rehype는 MDXAST를 MDXHAST라는 데이터 구조로 변환합니다.
  • (여기서 가로채고 사용자 지정)
  • Rehype는 최종 구조화된 데이터를 JSX 페이지에 씁니다.
  • Next.js는 HTML 페이지를 정적으로 생성합니다.

  • 수행할 수 있는 작업의 몇 가지 예:
  • 파일이 Git에 처음 커밋된 시간을 가져오고 이를 게시 날짜로 사용합니다.
  • 파일의 위치와 이름을 기반으로 레이아웃 구성 요소를 결정합니다.
  • Github와 웹사이트 모두에서 아름답게 렌더링된 게시물이 있는 Github 고유의 Markdown 구문을 작성하십시오.
  • Markdown을 DEV.to, Hashnode, Medium과 같은 다양한 플랫폼에 배포하기에 적합한 형식으로 변환하는 생성기를 작성하십시오.

  • 제가 한?



    이전에는 blog/ 디렉토리의 모든 MDX 페이지가 수동으로 작성된 JSX props와 함께 BlogPost 구성 요소를 가져오고 내보내야 했으며 다음과 같은 단점이 있습니다.
  • blog 디렉토리에 있다는 것은 MDX 페이지가 사용해야 하는 레이아웃을 나타내기에 충분해야 합니다. 가져오기 및 내보내기는 상용구입니다.
  • 표준 및 Open Graph URL이 올바르게 렌더링될 수 있도록 모든 페이지에 path 소품을 작성해야 했습니다. 그러나 수동으로 작성한 prop을 작성하지 않아도 파일 위치가 충분해야 합니다.
  • Github에서 MDX를 지원하지 않기 때문에 가져오기 및 내보내기 문이 Github에서 매우 보기 흉하게 렌더링됩니다.

  • 위의 문제를 해결하기 위해 다음과 같은 개념을 설계했습니다.
  • path , slug 및 레이아웃은 파일 위치에서 유추됩니다. 가져오기 및 복제된 소품이 없습니다.
  • Remark가 Markdown 구문을 처리한 후 파이프라인을 가로채고 적절한 props가 미리 채워진 import 문과 해당 레이아웃 구성 요소를 포함하는 줄export default을 동적으로 추가합니다.
  • SEOdescription, published time와 같은 기타 모든 정보는 Github이 제대로 렌더링할 수 있도록 YAML 프론트매터로 작성되었습니다.

  • MDX에서 기사가 어떻게 보이는지



    full source code 참조:

    ---
    title: "Switch to Next.js and MDX"
    description: ">-"
      I switched from plain HTML to using Next.js and MDX to have better ease of
      writing and extensibility.
    published time: 2020-12-18
    ---
    
    ## The Problem
    
    To prevent myself from procrastinating, I [started my blog dead simple in plain
    HTML][start blog].
    


    사용자 정의 플러그인 작성 방법(개념적으로)



    full source code 참조:

    const path = require("path");
    const yaml = require("yaml");
    const find = require("unist-util-find");
    
    const Components = {
      blog: "BlogPost",
    };
    
    const getSubpage = (file) => path.basename(file.dirname);
    
    const getRoute = (file) => {
      const sub = getSubpage(file);
    
      const Component = Components[sub];
      if (!Component)
        return file.fail(
          `Subpage '${sub}' is invalid. Valid subpages: ${Object.keys(Components)
            .map((it) => `'${it}'`)
            .join(", ")}.`
        );
    
      const slug = file.stem;
      return {
        Component,
        slug,
        path: `${sub}/${slug}`,
      };
    };
    
    module.exports = () => (tree, file) => {
      const frontmatter = find(tree, { type: "yaml" });
      const { title, description, "published time": publishedTime } = yaml.parse(
        frontmatter.value
      );
    
      const { path, Component } = getRoute(file);
      const props = `{
        path: "${path}",
        title: "${title}",
        description: "${description}",
        publishedTime: new Date("${publishedTime}"),
      }`;
    
      tree.children.unshift(
        {
          type: "import",
          value: `import ${Component} from "~components/mdx/${Component}";`,
        },
        {
          type: "export",
          default: true,
          value: `export default ${Component}(${props});`,
        }
      );
    };
    

    좋은 웹페이지 즐겨찾기