Notion to Zenn Markdown

2023.11.02

💻
TECH

NotionのPageをZenn記法のMarkdownに変換するライブラリです。

インストール

npm install notion-to-zenn-md

利用方法

import NotionToZennMarkdown from "notion-to-zenn-md";

// Instantiate with your Notion integration secret
const n2zm = new NotionToZennMarkdown('your_notion_integration_secret');
// Generate markdown from Notion page
const md = await n2zm.generateMd('notion_page_id');

console.log(md);

npm

Github

https://github.com/KOHSUK/notion-to-zenn-md

本ライブラリが指すZenn記法のMarkdownについて

本ライブラリにおいて目指すZenn記法のMarkdownとは次の2つの公式記事の記載されている仕様を指します。

中でも特に以下を簡単に行うことを目指しています。

  1. 埋め込み要素などZenn独自のMarkdown記法をNotionのページコンテンツから生成すること
  2. Zenn CLIで記事管理をするために必要なFrontMatterをNotionのページプロパティから生成すること

例えば、

NotionのCalloutというブロックから、

image

Zenn記法のMarkdownを生成して、

:::message
💡 Callout
:::

Zennのメッセージとして表示させることを目指します。

image

Notionの設定方法と notion-to-zenn-md の連携について

以下の手順で、利用の設定を行います。

  1. Notionに記事管理用のデータベースを作成
  2. Notion APIからアクセスするためIntegrationのシークレットを取得
  3. APIに記事管理用データベースのアクセスを許可
  4. 取得したシークレットを使い notion-to-zenn-md を利用したコードを書いていく

1. Notionに記事管理用のデータベースを作成

Notionを開き、左の一覧より「+」(Add a page)ボタンを押下して新しいページを作成します。

image

新規ページが開かれたら「Table」を選択して新規テーブルを作成します。

image

データベースを新規で作成します。

image

データベースが作成されたらのデータベースのプロパティを編集します。プロパティはFrontMatterの生成に利用します。

以下の様にFrontMatterのキーごとにプロパティを設定する必要があります。

FrontMatterのキー名 プロパティ名 プロパティタイプ 必須 備考
title Title Title Y
type Type Select Y
topics Topics Multi-select Y
published Published Checkbox Y
published_at Published At Date N notion-to-zenn-mdではデフォルトで出力しない設定になっています。
emoji - - Y ページに設定できるアイコンの絵文字を利用します。

以下に項目ごとの詳細な設定方法を示します。プロパティタイプに間違いがないように設定してください。

Title

新規でデータベースを作成した場合にデフォルトでTitleタイプのプロパティが作成されます。

プロパティの名前が、初期では Name となっているので、 Title に変更します。

image

Type

記事の種別を示すTypeプロパティを作成します。

プロパティタイプは Select で、選択肢(Options)は ideatech の2つを用意します。

image

Topics

Zennのタグのような機能のトピックを編集できるプロパティを設定します。プロパティタイプは Multi-select です。

image

Published

公開・非公開を設定するためのプロパティです。プロパティタイプは Checkbox です。

image

Published At

公開時間を設定するためのプロパティです。プロパティタイプは Date です。

image

データベース一覧はこのようになります。

image

Emoji

絵文字はページごとの「Add icon」から設定します。

image

設定するとページタイトルにアイコンがつきます。

image

記事の作成

データベースにページを作成し以下のように記事を書くことができます。

image

2. Notion APIからアクセスするためIntegrationのシークレットを取得

Notionのインテグレーションのページから新しいインテグレーションを作成します。

image

作成するとIntegration Secretが発行されます。これはnotion-to-zenn-mdからNotion APIを叩く際に必要になりますので、コピーしておきます。

image

3. APIに記事管理用データベースのアクセスを許可

先ほどNotionに作ったデータベースのページに戻り、右上の「・・・」ボタンからメニューを開きます。

image

Connectionsから先ほど作ったIntegrationを追加します。これで先ほど生成されたシークレットを用いてこのデータベースにアクセスすることができる様になります。

image

4. 取得したシークレットを使い notion-to-zenn-md を利用したコードを書いていく

先ほど取得したシークレットを用いて、以下の様にNotionの特定のページをページID指定でMarkdownに変換することができます。

以下の例では取得したページからMarkdownを生成してファイルに保存しています。

import NotionToZennMarkdown from "notion-to-zenn-md";
import { promises as fs } from 'fs';

async function writeToFile(data: string) {
  try {
    await fs.writeFile('index.md', data);
    console.log('The file has been saved!');
  } catch (error) {
    console.error('An error occurred:', error);
  }
}

async function main() {
  const n2zm = new NotionToZennMarkdown('secret_xxxxxxxxx'); // シークレット
  const md = await n2zm.generateMd('page_id'); // ページID

  await writeToFile(md);
}

main();

このコードを用いて以下のNotionのページを出力してみます。

image

すると以下のような内容のファイルが出力されます。

---
title: "記事のタイトルです。"
emoji: "🤩"
type: "idea"
topics: ["notion", "markdown"]
published: false
---

# Heading 1


## Heading 2


### Heading 3


Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec interdum eros a metus imperdiet maximus. Aenean gravida lacinia ultricies. Duis sit amet justo et lectus pharetra accumsan. Pellentesque urna erat.(text)

補足:FrontMatterの出力に任意の名前のプロパティを用いたい場合

generateMd メソッドなどの第二引数にFrontMatterの各項目とNotionのページのプロパティ名のマッピングのオブジェクトを渡すことで、任意のプロパティ名を設定したページプロパティからFrontMatterの項目値を取得することができます( emoji 以外)。

例えば、 Topics の代わりに カテゴリー というプロパティ名を使いたいとします。

image

以下の様にコードを変更することで topics の値を カテゴリー プロパティから値を取得することが可能です。

const md = await n2zm.generateMd('page_id', {
    topics: 'カテゴリー'
  });

以下が実際に生成されたFrontMatterの topics の値です。

---
title: "記事のタイトルです。"
emoji: "🤩"
type: "idea"
topics: ["notion-to-zenn-md"]
published: false
---

Published Atに日付を指定
Published Atに日付を指定

	const md = await n2zm.generateMd('page_id', {
    topics: 'カテゴリー',
    publishedAt: 'Published At', // ページのプロパティ名を指定
  });
---
title: "記事のタイトルです。"
emoji: "🤩"
type: "idea"
topics: ["notion-to-zenn-md"]
published: false
published_at: 2023-10-14 00:00
---

その他の機能

以下にその他の機能を示します。

  1. pageToZennMarkdown(pageId: string): Promise<string>
    • NotionのページIDを受け取り、そのページをFrontMatterを含まないZenn記法のマークダウンに変換して返します。
    • 引数: pageId - NotionのページID
    • 戻り値: ページのマークダウン表現
  2. getFrontMatter(pageId: string, mappingKeys: FrontMatterNotionPropMapping): Promise<FrontMatter>
    • NotionのページIDとマッピングキーを受け取り、Zenn記法のマークダウンのFrontMatterを生成して返します。
    • 引数:
      • pageId - NotionのページID
      • mappingKeys - Zenn Markdown Front Matterキーへのマッピングキー
    • 戻り値: FrontMatterオブジェクト
  3. getFrontMatterString(pageId: string, mappingKeys?: Partial<FrontMatterNotionPropMapping>): Promise<string>
    • NotionのページIDとオプショナルなマッピングキーを受け取り、FrontMatterの文字列を生成して返します。
    • 引数:
      • pageId - NotionのページID
      • mappingKeys (オプショナル) - Zenn Markdown Front Matterキーへのマッピングキー。デフォルト値はdefaultMappingです。
    • 戻り値: FrontMatterの文字列表現
  4. stringify(mdString: string, fontMatter: FrontMatter): string
    • マークダウンの文字列とFrontMatterのオブジェクトを受け取り、マークダウンの文字列を生成して返します。
    • 引数:
      • mdString - マークダウンの文字列
      • fontMatter - FrontMatterオブジェクト
    • 戻り値: マークダウンの文字列表現
  5. generateMd(pageId: string, mappingKeys?: Partial<FrontMatterNotionPropMapping>): Promise<string>
    • NotionのページIDとオプショナルなマッピングキーを受け取り、Zenn記法のマークダウンを生成して返します。
    • 引数:
      • pageId - NotionのページID
      • mappingKeys (オプショナル) - Zenn Markdown Front Matterキーへのマッピングキー。デフォルト値はdefaultMappingです。
    • 戻り値: ページのマークダウン表現

NotionブロックからMarkdownへの変換例

見出し

Notion (Heading 1, Heading 2, Heading 3)

image

Markdown

# 見出し1


## 見出し2


### 見出し3


#### 見出し4

zenn-markdown-html

見出し1

見出し2

見出し3

見出し4

リスト

Notion (Bulleted List)

image

Markdown


- Hello!
- Hola!
	- Bonjour!
	- Hi!

zenn-markdown-html

  • Hello!
  • Hola!
    • Bonjour!
    • Hi!

番号付きリスト

Notion (Numbered List)

image

Markdown


1. First
2. Second

zenn-markdown-html

  1. First
  2. Second

テキストリンク

Notion (TextにLink)

image

Markdown


[アンカーテキスト](https://www.kohsuk.tech/)

zenn-markdown-html

アンカーテキスト

画像

Notion (Image)

image

Markdown


![image](https://image.example.com)

zenn-markdown-html

image

画像の横幅を指定する

Notion (Text)

image

Markdown

![altテキスト](https://kohsuk-blog-assets.s3.ap-northeast-1.amazonaws.com/articles/notion-to-zenn-markdown/1698930064770. =250x)

zenn-markdown-html

altテキスト

キャプションをつける

Notion

NotionのImageのCaptionを利用できます。

image

image

Markdown

![キャプション](https://image.example.com)
*キャプション*

zenn-markdown-html

キャプション
キャプション

画像にリンクを貼る

Notion (Text)

image

Markdown

[![alt text](https://via.placeholder.com/300x200)](https://www.kohsuk.tech/)

zenn-markdown-html

alt text

テーブル

Notion (Table)

image

Markdown


| Head | Head | Head |
| ---- | ---- | ---- |
| Text | Text | Text |
| Text | Text | Text |

zenn-markdown-html

Head Head Head
Text Text Text
Text Text Text

コードブロック

Notion (Code)

image

Markdown

const sayHello = () => {  
	console.log("Hello!");  
};  

zenn-markdown-html

const sayHello = () => {
	console.log("Hello!");
};

ファイル名を表示する

NotionのCodeブロックはキャプションをつけることができます。キャプションにファイル名を記載することで、 言語:ファイル名 とMarkdownを出力させることができます。

Notion (Code)

image

Markdown

hello.js
const sayHello = () => {  
	console.log("Hello!");  
};  

zenn-markdown-html

hello.js
const sayHello = () => {
	console.log("Hello!");
};

diff のシンタックスハイライト

NotionのCodeブロックにも Diff がありますが、言語とファイル名を指定する欄はありません。

ですので、ここでもCaptionを利用して言語:ファイル名と書くことでMarkdownでの出力に対応しています。

Notion (Code)

image

Markdown

hello.js
const sayHello = () => {  
-	console.log("Hello!");  
+	console.log("Hello, world!");  
};  

zenn-markdown-html

hello.js
const sayHello = () => {
-	console.log("Hello!");
+	console.log("Hello, world!");
};

数式(ブロック)

Notion (Block equation)

image

Markdown


$$
x^n + y^n = z^n\text{ has no non-zero integer solutions for } x, y, z \text{ when } n > 2.
$$

zenn-markdown-html

x^n + y^n = z^n\text{ has no non-zero integer solutions for } x, y, z \text{ when } n > 2.

数式(インライン)

Notion (Inline equation)

image

Markdown


$E = mc^2$ の様にインラインで数式を含める

zenn-markdown-html

E = mc^2 の様にインラインで数式を含める

引用

Notion (Quote)

image

Markdown


> 引用文  
> 引用文

zenn-markdown-html

引用文
引用文

注釈

Notionに対応する記法がないため、テキストブロックに直接記載します。

Notion (Text)

image

Markdown


注釈は例[^1]の様に書きます。インライン^[注釈の内容2]を書くこともできます。


[^1]: 注釈の内容1

zenn-markdown-html

注釈は例[1]の様に書きます。インライン[2]を書くこともできます。

区切り線

Notion (Divider)

image

Markdown


---

zenn-markdown-html


インラインスタイル

Notion (Text)

image

Markdown


_イタリック_


**太字**


~~打ち消し線~~


インラインで `code` を挿入する

zenn-markdown-html

イタリック

太字

打ち消し線

インラインで code を挿入する

インラインのコメント

Notionに該当するブロックがないため、Textブロックに以下の様に記載することで、出力されたMarkdownにHTMLのコメントを挿入します。

Notion (Text)

image

Markdown


<!— インラインのコメント >

zenn-markdown-html

<!— インラインのコメント —>

Zenn 独自の記法

メッセージ

Notion (Callout)

image

Markdown


:::message
🔥 メッセージです。
:::

zenn-markdown-html

アコーディオン(トグル)

Notion (Text)

image

Markdown


:::details タイトル


内容です。


:::

zenn-markdown-html

タイトル

内容です。

コンテンツの埋め込み

リンクカード

Notion (Web bookmark)

image

Markdown


@[card](https://www.kohsuk.tech/tech)

zenn-markdown-html

その他の埋め込み

Notionの Embeds で用意されているものについては、順次対応していきます。

ダイアグラム

NotionにMermaindのダイアグラムをリアルタイムで見ながらコードブロックを編集する機能を利用できます。出力結果は以下の通り、 mermaid のコードブロックのMarkdownです。

Notion (Code - Mermaid)

image

Markdown

zenn-markdown-html

脚注
  1. 注釈の内容1 ↩︎

  2. 注釈の内容2 ↩︎


Homeへ戻る
profile picture

Kosuke Kihara

I'm a Web Developer👑 who shares tips on Tech, Productivity, Design, and much more!

Kohsuk11KOHSUKkohsuk.tech@gmail.com