UNPKG

astronotion

Version:

Library to make Astro sites with content from Notion

175 lines (146 loc) 4.66 kB
import type { Collection, Decoration, ExtendedRecordMap, PageBlock } from "notion-types"; import { checkIfParentPage } from "./check-page-type"; import { filterContentBlocks, filterChildBlocks } from "./filter-blocks"; import type { AnContentBlock } from "./filter-blocks"; import { flattenBlocks, flattenText } from "./flatten"; import { getCover } from "./get-cover"; import { transformImageUrl } from "./image-file"; type AnPageBase = { title: string; icon?: string; cover?: ReturnType<typeof getCover>; description?: Decoration[]; }; export type AnExcerpt = AnPageBase & { id: string; taxonomies: string[]; // !! update when implementing the feature created: number; updated: number; }; export type AnParentPage = { pageType: "NOTION_PARENT"; pageData: AnPageBase & { childPages: AnExcerpt[]; }; }; export type AnEntryPage = { pageType: "NOTION_ENTRY"; pageData: AnExcerpt & { contents: AnContentBlock[]; }; }; export type AnTopLevelPage = AnParentPage | AnEntryPage; type CollectionWithCoverAndDesc = Collection & { cover?: string; description?: Decoration[]; }; /** * Get and transform the "signed_urls" field from page data returned * by notion-client. These will be compared against image URLs to * determine whether they should be downloaded before they expire. * * @param {ExtendedRecordMap} data * @returns {Image} */ const getDownloadableUrlsFromPage = (data: ExtendedRecordMap) => { if (!data.signed_urls) return []; return Object.entries(data.signed_urls).map((item) => item[1]); }; const transformChildPageBlock = (data: PageBlock, downloadableUrls?: string[]) => { const { id, properties, format, created_time, last_edited_time } = data; const title = flattenText(properties?.title || []); const icon = format?.page_icon; const cover = getCover(data); if (cover && cover.url) { cover.url = transformImageUrl(cover.url, downloadableUrls); } // TODO (later) taxonomies & custom created/updated const taxonomies: string[] = []; const created = created_time; const updated = last_edited_time; return { id, title, icon, cover, description: undefined as Decoration[] | undefined, // !! temporary workaround taxonomies, created, updated, }; }; const transformContentBlock = ( data: ReturnType<typeof filterContentBlocks>[number], downloadableUrls?: string[] ) => { if (data.type !== "image") return data; // Do nothing for non-image blocks. const imageUrl = data.properties.source[0][0]; if (imageUrl) { data.properties.source[0][0] = transformImageUrl(imageUrl, downloadableUrls); } return data; }; export const transformParentPage = (data: ExtendedRecordMap): AnParentPage | undefined => { const coll = Object.entries(data.collection)[0][1].value as CollectionWithCoverAndDesc; const downloadableUrls = getDownloadableUrlsFromPage(data); const { name, description, icon } = coll; const title = flattenText(name); const cover = getCover(coll); if (cover && cover.url) { cover.url = transformImageUrl(cover.url, downloadableUrls); } const id = flattenBlocks(data.block)[0].id; const childPages = filterChildBlocks(data.block, id).map((item) => transformChildPageBlock(item as PageBlock, downloadableUrls) ); return { pageType: "NOTION_PARENT", pageData: { title, icon, cover, description, childPages, }, }; }; export const transformEntryPage = (data: ExtendedRecordMap): AnEntryPage | undefined => { const blocks = flattenBlocks(data.block); const pageBlock = blocks[0]; if (pageBlock.type !== "page" || !pageBlock.properties || blocks.length < 3) return; const downloadableUrls = getDownloadableUrlsFromPage(data); const { id, properties, format, created_time, last_edited_time } = pageBlock; const title = flattenText(properties.title); const icon = format?.page_icon; const cover = getCover(pageBlock); if (cover && cover.url) { cover.url = transformImageUrl(cover.url, downloadableUrls); } const contents = filterContentBlocks(blocks).map((item) => transformContentBlock(item, downloadableUrls) ); // TODO (later) taxonomies, custom created/updated, description const taxonomies: string[] = []; const created = created_time; const updated = last_edited_time; let description; return { pageType: "NOTION_ENTRY", pageData: { id, title, icon, cover, description, contents, taxonomies, created, updated, }, }; }; export const transformTopLevelPage = (data: ExtendedRecordMap) => { const isParent = checkIfParentPage(data); return isParent ? transformParentPage(data) : transformEntryPage(data); }; // ?? differentiate _top-level vs child_ entry page if needed