diff --git a/README.md b/README.md index c37e822..3240b6b 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ The following [Notion API block object types](https://developers.notion.com/refe | Video | ❌ Missing | | | File | ❌ Missing | | | PDF | ❌ Missing | | -| Bookmark | ❌ Missing | | +| Bookmark | ✅ Yes | use a caption as a link name | | | Equation | ❌ Missing | | | Divider | ✅ Yes | | | Table Of Contents | ❌ not planned | static site generators have their own ToC implementations | diff --git a/src/BlockRenderer.ts b/src/BlockRenderer.ts index 54ffe9b..6f98ea9 100644 --- a/src/BlockRenderer.ts +++ b/src/BlockRenderer.ts @@ -14,6 +14,7 @@ import { DeferredRenderer } from "./DeferredRenderer"; import { RenderingContextLogger } from "./RenderingContextLogger"; import { RichTextRenderer } from "./RichTextRenderer"; import { RenderingContext } from "./RenderingContext"; +import { LinkRenderer } from "./LinkRenderer"; const debug = require("debug")("blocks"); @@ -24,7 +25,8 @@ export interface BlockRenderResult { export class BlockRenderer { constructor( private readonly richText: RichTextRenderer, - private readonly deferredRenderer: DeferredRenderer + private readonly deferredRenderer: DeferredRenderer, + private readonly link: LinkRenderer ) {} async renderBlock( @@ -102,16 +104,27 @@ export class BlockRenderer { return { lines: "---" }; case "child_database": const msg = `\n`; - const db = await this.deferredRenderer.renderChildDatabase(block.id, context.linkResolver); + const db = await this.deferredRenderer.renderChildDatabase( + block.id, + context.linkResolver + ); return { lines: msg + db.markdown }; case "synced_block": // nothing to render, only the contents of the synced block are relevant // however, these are children nöpcl, and thus retrieved by recursion in RecusivveBodyRenderer return null; + case "bookmark": + // render caption (if provided) as a link name + const caption = block.bookmark.caption || []; + let title = block.bookmark.url; + if (caption.length > 0) + title = await this.richText.renderPlainText(caption); + return { + lines: this.link.renderUrlLink(title, block.bookmark.url), + }; case "toggle": case "child_page": case "embed": - case "bookmark": case "video": case "file": case "pdf": @@ -145,10 +158,7 @@ export class BlockRenderer { } } - async renderImage( - block: ImageBlock, - assets: AssetWriter - ): Promise { + async renderImage(block: ImageBlock, assets: AssetWriter): Promise { const url = this.parseUrl(block.image); const imageFile = await assets.download(url, block.id); diff --git a/src/sync.ts b/src/sync.ts index ffd7b14..4bbeda9 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -1,18 +1,18 @@ -import { BlockRenderer } from './BlockRenderer'; -import { ChildDatabaseRenderer } from './ChildDatabaseRenderer'; -import { DatabaseEntryRenderer } from './DatabaseEntryRenderer'; -import { DatabasePageRenderer } from './DatabasePageRenderer'; -import { DatabaseViewRenderer } from './DatabaseViewRenderer'; -import { DeferredRenderer } from './DeferredRenderer'; -import { FrontmatterRenderer } from './FrontmatterRenderer'; -import { LinkRenderer } from './LinkRenderer'; -import { MentionedPageRenderer } from './MentionedPageRenderer'; -import { NotionApiFacade } from './NotionApiFacade'; -import { PageLinkResolver } from './PageLinkResolver'; -import { PropertiesParser } from './PropertiesParser'; -import { RecursiveBodyRenderer } from './RecursiveBodyRenderer'; -import { RichTextRenderer } from './RichTextRenderer'; -import { SyncConfig } from './SyncConfig'; +import { BlockRenderer } from "./BlockRenderer"; +import { ChildDatabaseRenderer } from "./ChildDatabaseRenderer"; +import { DatabaseEntryRenderer } from "./DatabaseEntryRenderer"; +import { DatabasePageRenderer } from "./DatabasePageRenderer"; +import { DatabaseViewRenderer } from "./DatabaseViewRenderer"; +import { DeferredRenderer } from "./DeferredRenderer"; +import { FrontmatterRenderer } from "./FrontmatterRenderer"; +import { LinkRenderer } from "./LinkRenderer"; +import { MentionedPageRenderer } from "./MentionedPageRenderer"; +import { NotionApiFacade } from "./NotionApiFacade"; +import { PageLinkResolver } from "./PageLinkResolver"; +import { PropertiesParser } from "./PropertiesParser"; +import { RecursiveBodyRenderer } from "./RecursiveBodyRenderer"; +import { RichTextRenderer } from "./RichTextRenderer"; +import { SyncConfig } from "./SyncConfig"; export async function sync(notionApiToken: string, config: SyncConfig) { const publicApi = new NotionApiFacade(notionApiToken); @@ -32,7 +32,11 @@ export async function sync(notionApiToken: string, config: SyncConfig) { linkRenderer ); const propertiesParser = new PropertiesParser(richTextRenderer); - const blockRenderer = new BlockRenderer(richTextRenderer, deferredRenderer); + const blockRenderer = new BlockRenderer( + richTextRenderer, + deferredRenderer, + linkRenderer + ); const bodyRenderer = new RecursiveBodyRenderer(publicApi, blockRenderer); const entryRenderer = new DatabaseEntryRenderer(propertiesParser); const pageRenderer = new DatabasePageRenderer( @@ -52,7 +56,10 @@ export async function sync(notionApiToken: string, config: SyncConfig) { // seed it with the root database const rootLinkResolver = new PageLinkResolver("."); - await deferredRenderer.renderChildDatabase(config.cmsDatabaseId, rootLinkResolver); + await deferredRenderer.renderChildDatabase( + config.cmsDatabaseId, + rootLinkResolver + ); await deferredRenderer.process(); const rendered = deferredRenderer.getRenderedPages();