contentlayer.config.tsに型をつける

2023/09/07に公開

contentlayerとは?

mdファイルからページを生成するやつです。next.jsで使う以外に方法があるのか僕には分かりませんがとても便利。
Contentlayer makes content easy for developers

サンプル

anyで誤魔化してる人多そうだったので、コピペして置いときます
UnistNodeをどこかからインポートできるかなーと思ったけど見つけきれんかった。

contentlayer.config.ts
import { ComputedFields, defineDocumentType, makeSource } from 'contentlayer/source-files';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import rehypePrettyCode from 'rehype-pretty-code';
import rehypeSlug from 'rehype-slug';
import remarkGfm from 'remark-gfm';
import { UnistNode, UnistTree } from '@/types/unist';

const computedFields: ComputedFields = {
  slug: {
    type: 'string',
    resolve: (doc) => `/${doc._raw.flattenedPath}`,
  },
  slugAsParams: {
    type: 'string',
    resolve: (doc) => doc._raw.flattenedPath.split('/').slice(1).join('/'),
  },
};

export const Doc = defineDocumentType(() => ({
  name: 'Doc',
  filePathPattern: `docs/**/*.mdx`,
  contentType: 'mdx',
  fields: {
    title: {
      type: 'string',
      required: true,
    },
    description: {
      type: 'string',
    },
    published: {
      type: 'boolean',
      default: true,
    },
  },
  computedFields,
}));

export default makeSource({
  contentDirPath: './content',
  documentTypes: [Doc],
  mdx: {
    remarkPlugins: [remarkGfm],
    rehypePlugins: [
      rehypeSlug,
      [
        rehypePrettyCode,
        {
          theme: 'github-dark',
          onVisitLine(node: UnistTree) {
            if (node.children.length === 0) {
              node.children = [{ type: 'text', value: ' ' }];
            }
          },
          onVisitHighlightedLine(node: UnistNode) {
            node.properties?.className?.push('line--highlighted');
          },
          onVisitHighlightedWord(node: UnistNode) {
            node.properties?.className?.push('word--highlighted');
          },
        },
      ],
      [
        rehypeAutolinkHeadings,
        {
          properties: {
            className: ['subheading-anchor'],
            ariaLabel: 'Link to section',
          },
        },
      ],
    ],
  },
});
types/unist.d.ts
import type { Node } from 'unist';

export interface UnistNode extends Node {
  url?: string;
  type: string;
  name?: string;
  tagName?: string;
  value?: string;
  properties?: {
    __rawString__?: string;
    __className__?: string;
    __filename__?: string;
    className?: string[];
    [key: string]: unknown;
  } & TerminalCommands;
  attributes?: {
    name: string;
    value: unknown;
    type?: string;
  }[];
  children?: UnistNode[];
}

export interface UnistTree extends Node {
  children: UnistNode[];
}

export interface TerminalCommands {
  __npmCommand__?: string;
  __yarnCommand__?: string;
  __pnpmCommand__?: string;
}

参考資料

jsだけど参考にしたソースはこちら

https://github.com/shadcn-ui/taxonomy/blob/651f984e52edd65d40ccd55e299c1baeea3ff017/contentlayer.config.js

Discussion