🤖

Zenn CLIでslugに日時を自動設定する

2024/04/11に公開

最近、GitHubリポジトリでZennのコンテンツを管理するの記事を参考に、GitHubリポジトリでZennの記事を管理するようにしました。

https://github.com/revoltage-inc/revoltage-articles

Zennでは、Zenn CLIを使って、記事を新規作成したり、プレビューしたりすることができます。
今回は、Zenn CLIで記事を新規作成する際に、slugに日時を自動設定する方法を紹介します。

はじめに

いきなり否定的から入ってしまいますが、slugに日時を設定することはアンチパターンの可能性があります。

GoogleにおけるURL構造のベストプラクティスには、URLに日時を含めることはアンチパターンとして明言されてはいないので、SEO的に大きな問題にはならないと思われますが、
検索結果の表示でURLに日時が含まれることで、古い記事だと誤認させる可能性があります。
slugには日時ではなく、シンプルでわかりやすい語句をURLに使用することが望ましいです。

それを理解した上で、参考にしてもらえればと思います。

なぜZenn CLIのslugに日時を自動設定するのか

Zenn CLIのコマンドでslugオプションを指定せずに記事を新規作成すると、
デファイル名がランダム14桁の半角英数字のMarkdownファイルがarticlesディレクトリ直下に生成されます。
このファイル名=slugです。

MarkdownファイルはZenn CLIのファイルの配置ルールの都合上、articlesディレクトリ直下に必ず配置する必要があります。
ディレクトリのネストはできません。

そして、自分のVSCodeのエクスプローラー内のファイルの並び順はデフォルト設定の名前順です。
ファイル名がランダムだと並び順までランダムになるため、ファイル数が増えるほど新規作成したファイルを探すのが若干面倒になります。

Markdownファイル一覧

そこで、Markdownファイルが名前順にソートされるように、slugに日時を自動設定したいと考えました。

Zennのslugはサイト全体でユニークである必要がある

Zennのslugはサイト全体でユニークである必要があるため、slugに日時だけでは不十分です。
そのため、今回のアプローチでは日時とランダムな文字列を組み合わせます。

slugはサイト全体で(記事や本などのコンテンツの種類ごとに)ユニークにする必要があります。他ユーザーの記事で使用済みのslugも使用できないのでご注意ください。
slugは半角英小文字(a-z)、半角数字(0-9)、ハイフン(-)、アンダースコア(_)の12〜50字の組み合わせにする必要があります。
slugは一度zenn.dev上で作成されたら変更できません(slugを変えると別の投稿として作成されます)。
参考: Zennのスラッグ(slug)とは

slugに日時を自動設定する

前置きが長くなりましたが、slugに日時を自動設定する方法を紹介します。

まず、slugを生成するために下記のslug.mjsのファイルを作成します。
ESMなので拡張子を.mjsにしています。

import { randomBytes } from 'node:crypto'
import { format } from 'date-fns'

console.log(`${format(new Date(), 'yyyyMMddHHmmss')}-${randomBytes(7).toString('hex')}`)

ちなみにランダムな文字列を生成するために、cryptoモジュールのrandomBytes関数を使用していますが これはZenn CLIの実装のリスペクトです。
UUIDやULID、Snowflakeなどを使っても良いですが、slugの文字数制限があるのと、あまりファイル名を長くしたくないため、この実装になりました。

https://github.com/zenn-dev/zenn-editor/blob/canary/packages/zenn-cli/src/server/lib/helper.ts#L11-L13

あとはZenn CLIのコマンドでslugを指定する時に、下記のコマンドを実行します。

npx zenn new:article --slug="$(node ./slug.mjs)"

TypeScriptで書きたい場合は、拡張子を.mtsに書き換えて、ts-nodeを挟んで実行します。
コマンドが長いので、package.jsonscriptsに追加しておくと便利です。

npm i -D @types/node ts-node typescript

npx zenn new:article --slug="$(node --no-warnings --loader ts-node/esm ./slug.mts)"

おまけ

VSCodeの設定をいじることでエクスプローラー内のファイルを更新順で並べ替える方法もあります。
エクスプローラー内全てのファイルの並び順が変わるため自分は試していませんが、参考にしてください。

{
  "explorer.sortOrder": "modified"
}

あと日時をユニークなIDとして誤って使うと、衝突してこのようなインシデントがつながる可能性があるので注意しましょう。

https://www.fujitsu.com/jp/group/fjj/about/resources/news/topics/2023/0509.html

参考リンク

Discussion