Closed5

Next.jsでmdxを使ってみる

水無瀬水無瀬

next.config.js修正

おそらく無いので作るところから。

$touch next.config.js
const withMDX = require('@next/mdx')({
  extension: /\.mdx?$/
});
module.exports = withMDX({
  pageExtensions: ['ts', 'tsx', 'md', 'mdx']
});
水無瀬水無瀬

サンプル追加

# pages配下にmdxファイルを追加
$ touch pages/hello.mdx
hello.mdx
# sample
ここから↓がjsx.
<article>
  <h1>Hello World!</h1>
  <div style={{backgroundColor: 'red', fontSize: '200%'}}>
    sample text.
  </div>
</article>
水無瀬水無瀬

component読みこむ

header component作成

お試しのコンポーネントを作る。

Header.tsx
import React from 'react';
import style from './Header.module.css';

interface Props {
  heading: string,
  color?: 'red' | 'blue'
}

export const HeaderComponent: React.FC<Props> = ({heading, color}) => {
  if (!color) {
    return <h1 className={style.header}>{heading}</h1>;
  }
  switch(color) {
    case 'red':
      return <h1 className={`${style.header} ${style['header--red']}`}>{heading}</h1>;
    case 'blue':
      return <h1 className={`${style.header} ${style['header--blue']}`}>{heading}</h1>;
  }
}
Header.module.css
.header {
  font-size: 28px;
}
.header--red {
  color: red;
}
.header--blue {
  color: blue;
}

mdx修正

hello.mdx
import {HeaderComponent} from '../components/header/Header.tsx';

# sample
ここから↓がjsx.
<article>
  <HeaderComponent heading="Hello World!"/>
  <div style={{backgroundColor: 'red', fontSize: '200%'}}>
    sample text.
  </div>
</article>
<article>
  <HeaderComponent heading="Hello World!" color="red"/>
  <div style={{backgroundColor: 'red', fontSize: '200%'}}>
    red heading.
  </div>
</article>
<article>
  <HeaderComponent heading="Hello World!" color="blue"/>
  <div style={{backgroundColor: 'red', fontSize: '200%'}}>
    blue heading.
  </div>
</article>
水無瀬水無瀬

コードブロック作ってみる

mdのコードブロックでシンタックスハイライトが効かないっぽかったので自作。
絶対うまいやり方がある気がする。

ライブラリ追加

$ yarn add prism-react-renderer

コンポーネント作成

Codeblock.tsx
import React from 'react';
import Highlight, {defaultProps, Language} from 'prism-react-renderer';

export const CodeBlockComponent: React.FC<{code: string, language: Language}> = ({code, language}) => {
  return (
    <Highlight {...defaultProps} code={code} language={language}>
      {({className, style, tokens, getLineProps, getTokenProps}) => (
        <pre className={className} style={{...style, padding: '20px'}}>
          {tokens.map((line, i) => (
            <div key={i} {...getLineProps({line, key: i})}>
              {line.map((token, key) => (
                <span key={key} {...getTokenProps({token, key})} />
              ))}
            </div>
          ))}
        </pre>
      )}
    </Highlight>
  )
};

mdx修正

hello.mdx
import {HeaderComponent} from '../components/header/Header.tsx';
import {CodeBlockComponent} from '../components/codeblock/CodeBlock.tsx';

# sample
ここから↓がjsx.
<article>
  <HeaderComponent heading="Hello World!"/>
  <div style={{backgroundColor: 'red', fontSize: '200%'}}>
    sample text.
  </div>
</article>
<article>
  <HeaderComponent heading="Hello World!" color="red"/>
  <div style={{backgroundColor: 'red', fontSize: '200%'}}>
    red heading.
  </div>
</article>
<article>
  <HeaderComponent heading="Hello World!" color="blue"/>
  <div style={{backgroundColor: 'red', fontSize: '200%'}}>
    blue heading.
  </div>
</article>

<CodeBlockComponent
  code={`
    const hoge = 'hoge';
    console.log(hoge);
  `}
  language="javascript"
/>

↓はハイライトされない
```js
const hoge = 'hoge';
console.log(hoge);

参考リンク

このスクラップは2020/12/29にクローズされました