0.1.3 • Published 2 years ago
notion2hast v0.1.3
notion2hast
Notion の blocks を hast へ変換。
実装中。
Installtion
$ npm install --save notion2hastSecurity
notion2hast は信頼できるソースのみを扱う前提で動作します。
第三者からのソースを扱う状況では hast-util-sanitize の併用を推奨します。
Usage
basic
import { Client as NotionClient } from '@notionhq/client'
import { ClientOptions } from '@notionhq/client/build/src/Client'
import { toHtml as hastToHtml } from 'hast-util-to-html'
import { blockToHast } from 'notion2hast'
import { Client } from 'notion2hast'
class FromNotion extends Client {
private client: NotionClient
constructor(options?: ClientOptions) {
super()
this.client = new NotionClient(options)
}
listBlockChildren(
...args: Parameters<NotionClient['blocks']['children']['list']>
): ReturnType<NotionClient['blocks']['children']['list']> {
return this.client.blocks.children.list(...args)
}
}
const apiKey = process.env.API_KEY
const blockId = process.env.BLOCK_ID
const client = new FromNotion({
auth: apiKey
})
const tree = await blockToHast(client, {
block_id: blockId,
blocktoHastOpts: { defaultClassName: true },
richTexttoHastOpts: { defaultClassName: true }
})
console.log(`${hastToHtml(tree)}`)<p>最初のパラグラフ。</p>
<h2>文字装飾</h2>
<p><strong>太字</strong></p>
<p><em>italic</em></p>
<p><s>打消し線</s></p>
<p><code>code</code></p>
<h2>リスト</h2>
<ul>
<li>項目1</li>
<li>
項目2
<ul>
<li>
項目2-1
<ul>
<li>項目<span style="color: #0b6e99">2-1-1</span></li>
</ul>
</li>
<li>項目2-2</li>
</ul>
</li>
</ul>Custom Client
Notions の Client(主に fetch 関連)が利用できない環境では Custom Client を利用可能。
以下、Google Apps Script(clasp) で利用する場合の例。
tohast.ts
import { Client as NotionClient } from '@notionhq/client'
import { ClientOptions } from '@notionhq/client/build/src/Client'
import { toHtml as hastToHtml } from 'hast-util-to-html'
import { blockToHast } from '@hankei6km/notion2hast'
import { Client } from '@hankei6km/notion2hast'
import { listBlockChildren } from './notion'
export namespace NotionToHast {
class FromNotion extends Client {
//private client: NotionClient;
private auth: ClientOptions['auth']
constructor(options?: ClientOptions) {
super()
this.auth = options?.auth
}
async listBlockChildren(
...args: Parameters<NotionClient['blocks']['children']['list']>
): Promise<ReturnType<NotionClient['blocks']['children']['list']>> {
return listBlockChildren(this.auth || '', args[0].block_id) as any
}
}
export async function toHast(apiKey: string, block_id: string) {
const client = new FromNotion({ auth: apiKey })
const tree = await blockToHast(client, {
block_id,
blocktoHastOpts: { defaultClassName: true },
richTexttoHastOpts: { defaultClassName: true }
})
console.log(`${hastToHtml(tree)}`)
}
}notion.ts
import {
CreatePageParameters,
UpdatePageParameters,
QueryDatabaseParameters,
QueryDatabaseResponse
} from '@notionhq/client/build/src/api-endpoints'
const apiIUrlCreatePage = 'https://api.notion.com/v1/pages'
const apiUrlDabtabaseQuery = (database_id: string) =>
`https://api.notion.com/v1/databases/${database_id}/query`
const apiUrlUpdatePage = (page_id: string) =>
`https://api.notion.com/v1/pages/${page_id}`
const apiUrListBlockChildren = (block_id: string) =>
`https://api.notion.com/v1/blocks/${block_id}/children`
const apiVersion = '2022-02-22'
export function isErrRes(
res: GoogleAppsScript.URL_Fetch.HTTPResponse
): boolean {
const code = Math.trunc(res.getResponseCode() / 100)
if (code === 4 || code === 5) {
return true
}
return false
}
export function listBlockChildren(apiKey: string, block_id: string) {
const url = apiUrListBlockChildren(block_id)
try {
const res = UrlFetchApp.fetch(url, {
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
'Notion-Version': apiVersion
},
muteHttpExceptions: true
})
const code = res.getResponseCode()
if (isErrRes(res)) {
throw res.getContentText()
}
const resQuery = JSON.parse(res.getContentText()) as QueryDatabaseResponse
return resQuery
} catch (e) {
console.log(`${e}`)
throw e
}
}default class name
各要素にデフォルトの class 名を追加。デフォルトのクラス名は properties map の key が使用される。
const client = new FromNotion({
auth: apiKey,
blocktoHastOpts: { defaultClassName: true },
richTexttoHastOpts: { defaultClassName: true }
})<p class="paragraph">最初のパラグラフ。</p>
<h2 class="heading-2">文字装飾</h2>
<p class="paragraph"><strong class="text-bold">太字</strong></p>
<p class="paragraph"><em class="text-italic">italic</em></p>
<p class="paragraph"><s class="text-strikethrough">打消し線</s></p>
<p class="paragraph"><code class="text-code">code</code></p>properties map
指定要素のプロパティを変更。className を指定した場合、指定された要素にデフォルト class 名は追加されない。
const client = new FromNotion({
auth: apiKey,
blocktoHastOpts: {
defaultClassName: true,
blockToHastBuilderOpts: {
propertiesMap: {
'heading-2': { style: 'border: solid;' },
callout: { className: 'flex' },
'callout-paragraph': { className: 'grow' }
}
}
},
richTexttoHastOpts: { defaultClassName: true }
})<h2 style="border: solid" class="heading-2">コールアウト</h2>
<div class="flex" style="background-color: #ebeced">
<div class="callout-icon-emoji">💡</div>
<div class="grow">
<p>コールアウトの<strong class="text-bold">テキスト</strong>。</p>
</div>
</div>対応状況
Block
- paragraph
- heading_1
- heading_2
- heading_3
- bulleted_list_item
- numbered_list_item
- quote
- to_do - チェックは properties map で表現
- toggle
- template
- synced_block
- child_page
- child_database
- equation
- code
- callout
- divider
- breadcrumb
- table_of_contents
- column_list
- column
- link_to_page
- table
- table_row
- embed
- bookmark -
aタグとして変換 - image
- video
- file
- audio
- link_preview
- unsupported
rich text
- text
- annotations
- bold
- italic
- strikethrough
- underline
- code
- color
- href
- annotations
- mention
- user
- date
- link_preview
- template_mention
- template_mention_date
- template_mention_user
- page
- database
- annotations
- bold
- italic
- strikethrough
- underline
- code
- color
- href
- equation
- annotations
- bold
- italic
- strikethrough
- underline
- code
- color
- href
- annotations
properties mapping
block
paragraphheading-1heading-2heading-3codecode-precode-codecode-captioncalloutcallout-icon-emojicallout-icon-imagecallout-paragraphdividercolumn-listcolumnbulleted-listbulleted-list-itemnumbered-listnumbered-list-itemquotetodotodo-checkedtodo-not-checkedtodo-texttoggletoggle-summarytabletable-rowtable-row-celltable-row-headertable-row-header-top-lefttable-row-header-toptable-row-header-leftbookmarkbookmark-linkbookmark-captionimageimage-imgimage-caption
rich text
text-linktext-boldtext-codetext-italictext-strikethroughtext-underline
color
graybrownorangeyellowgreenbluepurplepinkredgray_backgroundbrown_backgroundorange_backgroundyellow_backgroundgreen_backgroundblue_backgroundpurple_backgroundpink_backgroundred_background
ライセンス
MIT License
Copyright (c) 2022 hankei6km