notion-utils
Advanced tools
+7
-2
@@ -342,3 +342,3 @@ // src/estimate-page-read-time.ts | ||
| void queue.add(async () => { | ||
| var _a, _b; | ||
| var _a, _b, _c; | ||
| try { | ||
@@ -379,3 +379,8 @@ if (targetPageId && pendingPageIds.has(targetPageId) && pageId !== targetPageId) { | ||
| for (const collectionData of Object.values(collectionViews)) { | ||
| const { blockIds } = collectionData; | ||
| const blockIds = Array.from( | ||
| /* @__PURE__ */ new Set([ | ||
| ...((_c = collectionData == null ? void 0 : collectionData.collection_group_results) == null ? void 0 : _c.blockIds) || [], | ||
| ...collectionData.blockIds | ||
| ]) | ||
| ); | ||
| if (blockIds) { | ||
@@ -382,0 +387,0 @@ for (const collectionItemId of blockIds) { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/estimate-page-read-time.ts","../src/get-block-title.ts","../src/get-block-collection-id.ts","../src/get-text-content.ts","../src/get-page-table-of-contents.ts","../src/format-date.ts","../src/format-notion-date-time.ts","../src/get-all-pages-in-space.ts","../src/id-to-uuid.ts","../src/parse-page-id.ts","../src/get-block-icon.ts","../src/get-block-parent-page.ts","../src/get-canonical-page-id.ts","../src/get-page-property.ts","../src/normalize-title.ts","../src/uuid-to-id.ts","../src/get-date-value.ts","../src/get-page-breadcrumbs.ts","../src/get-page-content-block-ids.ts","../src/is-url.ts","../src/get-page-image-urls.ts","../src/get-page-title.ts","../src/get-page-tweet-urls.ts","../src/get-page-tweet-ids.ts","../src/map-image-url.ts","../src/map-page-url.ts","../src/merge-record-maps.ts","../src/normalize-url.ts"],"sourcesContent":["import {\n type Block,\n type ExtendedRecordMap,\n type PageBlock\n} from 'notion-types'\n\nimport { getBlockTitle } from './get-block-title'\nimport { getPageTableOfContents } from './get-page-table-of-contents'\n\ntype EstimatePageReadTimeOptions = {\n wordsPerMinute?: number\n imageReadTimeInSeconds?: number\n}\n\ntype ContentStats = {\n numWords: number\n numImages: number\n}\n\ntype PageReadTimeEstimate = ContentStats & {\n totalWordsReadTimeInMinutes: number\n totalImageReadTimeInMinutes: number\n totalReadTimeInMinutes: number\n}\n\n/**\n * Returns an estimate for the time it would take for a person to read the content\n * in the given Notion page.\n *\n * Uses Medium for inspiration.\n *\n * @see https://blog.medium.com/read-time-and-you-bc2048ab620c\n * @see https://github.com/ngryman/reading-time\n *\n * TODO: handle non-english content.\n */\nexport function estimatePageReadTime(\n block: Block,\n recordMap: ExtendedRecordMap,\n {\n wordsPerMinute = 275,\n imageReadTimeInSeconds = 12\n }: EstimatePageReadTimeOptions = {}\n): PageReadTimeEstimate {\n const stats = getBlockContentStats(block, recordMap)\n const totalWordsReadTimeInMinutes = stats.numWords / wordsPerMinute\n const totalImageReadTimeInSeconds =\n stats.numImages > 10\n ? (stats.numImages / 2) * (imageReadTimeInSeconds + 3) +\n (stats.numImages - 10) * 3 // n/2(a+b) + 3 sec/image\n : (stats.numImages / 2) *\n (2 * imageReadTimeInSeconds + (1 - stats.numImages)) // n/2[2a+(n-1)d]\n const totalImageReadTimeInMinutes = totalImageReadTimeInSeconds / 60\n\n const totalReadTimeInMinutes =\n totalWordsReadTimeInMinutes + totalImageReadTimeInMinutes\n\n return {\n ...stats,\n totalWordsReadTimeInMinutes,\n totalImageReadTimeInMinutes,\n totalReadTimeInMinutes\n }\n}\n\n/**\n * Same as `estimatePageReadTime`, except it returns the total time estimate as\n * a human-readable string.\n *\n * For example, \"9 minutes\" or \"less than a minute\".\n */\nexport function estimatePageReadTimeAsHumanizedString(\n block: Block,\n recordMap: ExtendedRecordMap,\n opts: EstimatePageReadTimeOptions\n) {\n const estimate = estimatePageReadTime(block, recordMap, opts)\n return humanizeReadTime(estimate.totalReadTimeInMinutes)\n}\n\nfunction getBlockContentStats(\n block: Block,\n recordMap: ExtendedRecordMap\n): ContentStats {\n const stats: ContentStats = {\n numWords: 0,\n numImages: 0\n }\n\n if (!block) {\n return stats\n }\n\n for (const childId of block.content || []) {\n const child = recordMap.block[childId]?.value\n let recurse = false\n if (!child) continue\n\n switch (child.type) {\n case 'quote':\n // fallthrough\n case 'alias':\n // fallthrough\n case 'header':\n // fallthrough\n case 'sub_header':\n // fallthrough\n case 'sub_sub_header': {\n const title = getBlockTitle(child, recordMap)\n stats.numWords += countWordsInText(title)\n break\n }\n\n case 'callout':\n // fallthrough\n case 'toggle':\n // fallthrough\n case 'to_do':\n // fallthrough\n case 'bulleted_list':\n // fallthrough\n case 'numbered_list':\n // fallthrough\n case 'text': {\n const title = getBlockTitle(child, recordMap)\n stats.numWords += countWordsInText(title)\n recurse = true\n break\n }\n\n case 'embed':\n // fallthrough\n case 'tweet':\n // fallthrough\n case 'maps':\n // fallthrough\n case 'pdf':\n // fallthrough\n case 'figma':\n // fallthrough\n case 'typeform':\n // fallthrough\n case 'codepen':\n // fallthrough\n case 'excalidraw':\n // fallthrough\n case 'gist':\n // fallthrough\n case 'video':\n // fallthrough\n case 'drive':\n // fallthrough\n case 'audio':\n // fallthrough\n case 'file':\n // fallthrough\n case 'image':\n // treat all embeds as images\n stats.numImages += 1\n break\n\n case 'bookmark':\n // treat bookmarks as quarter images since they aren't as content-ful as embedd images\n stats.numImages += 0.25\n break\n\n case 'code':\n // treat code blocks as double the complexity of images\n stats.numImages += 2\n break\n\n case 'table':\n // fallthrough\n case 'collection_view':\n // treat collection views as double the complexity of images\n stats.numImages += 2\n break\n\n case 'column':\n // fallthrough\n case 'column_list':\n // fallthrough\n case 'transclusion_container':\n recurse = true\n break\n\n case 'table_of_contents': {\n const page = block as PageBlock\n if (!page) continue\n\n const toc = getPageTableOfContents(page, recordMap)\n for (const tocItem of toc) {\n stats.numWords += countWordsInText(tocItem.text)\n }\n\n break\n }\n\n case 'transclusion_reference': {\n const referencePointerId =\n child?.format?.transclusion_reference_pointer?.id\n\n if (!referencePointerId) {\n continue\n }\n const referenceBlock = recordMap.block[referencePointerId]?.value\n if (referenceBlock) {\n mergeContentStats(\n stats,\n getBlockContentStats(referenceBlock, recordMap)\n )\n }\n break\n }\n\n default:\n // ignore unrecognized blocks\n break\n }\n\n if (recurse) {\n mergeContentStats(stats, getBlockContentStats(child, recordMap))\n }\n }\n\n return stats\n}\n\nfunction mergeContentStats(statsA: ContentStats, statsB: ContentStats) {\n statsA.numWords += statsB.numWords\n statsA.numImages += statsB.numImages\n}\n\nfunction countWordsInText(text: string): number {\n if (!text) {\n return 0\n }\n\n return (text.match(/\\w+/g) || []).length\n}\n\nfunction humanizeReadTime(time: number): string {\n if (time < 0.5) {\n return 'less than a minute'\n }\n\n if (time < 1.5) {\n return '1 minute'\n }\n\n return `${Math.ceil(time)} minutes`\n}\n","import { type Block, type ExtendedRecordMap } from 'notion-types'\n\nimport { getBlockCollectionId } from './get-block-collection-id'\nimport { getTextContent } from './get-text-content'\n\nexport function getBlockTitle(block: Block, recordMap: ExtendedRecordMap) {\n if (block.properties?.title) {\n return getTextContent(block.properties.title)\n }\n\n if (\n block.type === 'collection_view_page' ||\n block.type === 'collection_view'\n ) {\n const collectionId = getBlockCollectionId(block, recordMap)\n\n if (collectionId) {\n const collection = recordMap.collection[collectionId]?.value\n\n if (collection) {\n return getTextContent(collection.name)\n }\n }\n }\n\n return ''\n}\n","import { type Block, type ExtendedRecordMap } from 'notion-types'\n\nexport function getBlockCollectionId(\n block: Block,\n recordMap: ExtendedRecordMap\n): string | null {\n const collectionId =\n (block as any).collection_id ||\n (block as any).format?.collection_pointer?.id\n\n if (collectionId) {\n return collectionId\n }\n\n const collectionViewId = (block as any)?.view_ids?.[0]\n if (collectionViewId) {\n const collectionView = recordMap.collection_view?.[collectionViewId]?.value\n if (collectionView) {\n const collectionId = collectionView.format?.collection_pointer?.id\n return collectionId\n }\n }\n\n return null\n}\n","import type * as types from 'notion-types'\n\n/**\n * Gets the raw, unformatted text content of a block's content value.\n *\n * This is useful, for instance, for extracting a block's `title` without any\n * rich text formatting.\n */\nexport const getTextContent = (text?: types.Decoration[]): string => {\n if (!text) {\n return ''\n } else if (Array.isArray(text)) {\n return (\n text?.reduce(\n (prev, current) =>\n prev + (current[0] !== '⁍' && current[0] !== '‣' ? current[0] : ''),\n ''\n ) ?? ''\n )\n } else {\n return text\n }\n}\n","import type * as types from 'notion-types'\n\nimport { getTextContent } from './get-text-content'\n\nexport interface TableOfContentsEntry {\n id: types.ID\n type: types.BlockType\n text: string\n indentLevel: number\n}\n\nconst indentLevels = {\n header: 0,\n sub_header: 1,\n sub_sub_header: 2\n}\n\n/**\n * Gets the metadata for a table of contents block by parsing the page's\n * H1, H2, and H3 elements.\n */\nexport const getPageTableOfContents = (\n page: types.PageBlock,\n recordMap: types.ExtendedRecordMap\n): Array<TableOfContentsEntry> => {\n type MapResult = TableOfContentsEntry | null | MapResult[]\n\n // Maps `content` property to TOC entries.\n // Pages and transclusion containers (synced blocks) both have the property.\n function mapContentToEntries(content?: string[]): MapResult[] {\n return (content ?? []).map((blockId: string) => {\n const block = recordMap.block[blockId]?.value\n\n if (block) {\n const { type } = block\n\n if (\n type === 'header' ||\n type === 'sub_header' ||\n type === 'sub_sub_header'\n ) {\n return {\n id: blockId,\n type,\n text: getTextContent(block.properties?.title),\n indentLevel: indentLevels[type]\n }\n }\n\n if (type === 'transclusion_container') {\n return mapContentToEntries(block.content)\n }\n }\n\n return null\n })\n }\n\n const toc = mapContentToEntries(page.content)\n // Synced blocks cannot be nested. So theoretically a 1-level flattening is enough.\n .flat()\n .filter(Boolean) as Array<TableOfContentsEntry>\n\n const indentLevelStack = [\n {\n actual: -1,\n effective: -1\n }\n ]\n\n // Adjust indent levels to always change smoothly.\n // This is a little tricky, but the key is that when increasing indent levels,\n // they should never jump more than one at a time.\n for (const tocItem of toc) {\n const { indentLevel } = tocItem\n const actual = indentLevel\n\n do {\n const prevIndent = indentLevelStack.at(-1)!\n const { actual: prevActual, effective: prevEffective } = prevIndent\n\n if (actual > prevActual) {\n tocItem.indentLevel = prevEffective + 1\n indentLevelStack.push({\n actual,\n effective: tocItem.indentLevel\n })\n } else if (actual === prevActual) {\n tocItem.indentLevel = prevEffective\n break\n } else {\n indentLevelStack.pop()\n }\n } while (true)\n }\n\n return toc\n}\n","export const formatDate = (\n input: string | number,\n { month = 'short' }: { month?: 'long' | 'short' } = {}\n) => {\n const date = new Date(input)\n const monthLocale = date.toLocaleString('en-US', { month })\n return `${monthLocale} ${date.getUTCDate()}, ${date.getUTCFullYear()}`\n}\n","import { formatDate } from './format-date'\n\nexport interface NotionDateTime {\n type: 'datetime'\n start_date: string\n start_time?: string\n time_zone?: string\n}\n\nexport const formatNotionDateTime = (datetime: NotionDateTime) => {\n // Adding +00:00 preserve the time in UTC.\n const dateString = `${datetime.start_date}T${\n datetime.start_time || '00:00'\n }+00:00`\n return formatDate(dateString)\n}\n","import { type ExtendedRecordMap, type PageMap } from 'notion-types'\nimport PQueue from 'p-queue'\n\nimport { parsePageId } from './parse-page-id'\n\n/**\n * Performs a traversal over a given Notion workspace starting from a seed page.\n *\n * Returns a map containing all of the pages that are reachable from the seed\n * page in the space.\n *\n * If `rootSpaceId` is not defined, the space ID of the root page will be used\n * to scope traversal.\n *\n * @param rootPageId - Page ID to start from.\n * @param rootSpaceId - Space ID to scope traversal.\n * @param getPage - Function used to fetch a single page.\n * @param opts - Optional config\n */\nexport async function getAllPagesInSpace(\n rootPageId: string,\n rootSpaceId: string | undefined,\n getPage: (pageId: string) => Promise<ExtendedRecordMap>,\n {\n concurrency = 4,\n traverseCollections = true,\n targetPageId,\n maxDepth = Number.POSITIVE_INFINITY\n }: {\n concurrency?: number\n traverseCollections?: boolean\n targetPageId?: string\n maxDepth?: number\n } = {}\n): Promise<PageMap> {\n const pages: PageMap = {}\n const pendingPageIds = new Set<string>()\n const queue = new PQueue({ concurrency })\n\n async function processPage(pageId: string, depth = 0) {\n if (depth > maxDepth) {\n return\n }\n\n if (targetPageId && pendingPageIds.has(targetPageId)) {\n return\n }\n\n pageId = parsePageId(pageId) as string\n\n if (pageId && !pages[pageId] && !pendingPageIds.has(pageId)) {\n pendingPageIds.add(pageId)\n\n void queue.add(async () => {\n try {\n if (\n targetPageId &&\n pendingPageIds.has(targetPageId) &&\n pageId !== targetPageId\n ) {\n return\n }\n\n const page = await getPage(pageId)\n if (!page) {\n return\n }\n\n const spaceId = page.block[pageId]?.value?.space_id\n\n if (spaceId) {\n if (!rootSpaceId) {\n rootSpaceId = spaceId\n } else if (rootSpaceId !== spaceId) {\n return\n }\n }\n\n for (const subPageId of Object.keys(page.block).filter((key) => {\n const block = page.block[key]?.value\n if (!block || block.alive === false) return false\n\n if (\n block.type !== 'page' &&\n block.type !== 'collection_view_page'\n ) {\n return false\n }\n\n // the space id check is important to limit traversal because pages\n // can reference pages in other spaces\n if (\n rootSpaceId &&\n block.space_id &&\n block.space_id !== rootSpaceId\n ) {\n return false\n }\n\n return true\n })) {\n void processPage(subPageId, depth + 1)\n }\n\n // traverse collection item pages as they may contain subpages as well\n if (traverseCollections) {\n for (const collectionViews of Object.values(\n page.collection_query\n )) {\n for (const collectionData of Object.values(collectionViews)) {\n const { blockIds } = collectionData\n\n if (blockIds) {\n for (const collectionItemId of blockIds) {\n void processPage(collectionItemId, depth + 1)\n }\n }\n }\n }\n }\n\n pages[pageId] = page\n } catch (err: any) {\n console.warn(\n 'page load error',\n { pageId, spaceId: rootSpaceId },\n err.statusCode,\n err.message\n )\n pages[pageId] = null\n }\n\n pendingPageIds.delete(pageId)\n })\n }\n }\n\n await processPage(rootPageId)\n await queue.onIdle()\n\n return pages\n}\n","export const idToUuid = (id = '') =>\n `${id.slice(0, 8)}-${id.slice(8, 12)}-${id.slice(12, 16)}-${id.slice(\n 16,\n 20\n )}-${id.slice(20)}`\n","import { idToUuid } from './id-to-uuid'\n\nconst pageIdRe = /\\b([\\da-f]{32})\\b/\n\n// TODO\n// eslint-disable-next-line security/detect-unsafe-regex\nconst pageId2Re = /\\b([\\da-f]{8}(?:-[\\da-f]{4}){3}-[\\da-f]{12})\\b/\n\n/**\n * Robustly extracts the notion page ID from a notion URL or pathname suffix.\n *\n * Defaults to returning a UUID (with dashes).\n */\nexport const parsePageId = (\n id: string | undefined | null = '',\n { uuid = true }: { uuid?: boolean } = {}\n): string | undefined => {\n if (!id) return\n\n id = id.split('?')[0]!\n if (!id) return\n\n const match = id.match(pageIdRe)\n\n if (match) {\n return uuid ? idToUuid(match[1]) : match[1]\n }\n\n const match2 = id.match(pageId2Re)\n if (match2) {\n return uuid ? match2[1] : match2[1]!.replaceAll('-', '')\n }\n\n return\n}\n","import {\n type Block,\n type ExtendedRecordMap,\n type PageBlock\n} from 'notion-types'\n\nimport { getBlockCollectionId } from './get-block-collection-id'\n\nexport function getBlockIcon(block: Block, recordMap: ExtendedRecordMap) {\n if ((block as PageBlock).format?.page_icon) {\n return (block as PageBlock).format?.page_icon\n }\n\n if (\n block.type === 'collection_view_page' ||\n block.type === 'collection_view'\n ) {\n const collectionId = getBlockCollectionId(block, recordMap)\n if (collectionId) {\n const collection = recordMap.collection[collectionId]?.value\n\n if (collection) {\n return collection.icon\n }\n }\n }\n\n return null\n}\n","import type * as types from 'notion-types'\n\n/**\n * Returns the parent page block containing a given page.\n *\n * Note that many times this will not be the direct parent block since\n * some non-page content blocks can contain sub-blocks.\n */\nexport const getBlockParentPage = (\n block: types.Block,\n recordMap: types.ExtendedRecordMap,\n {\n inclusive = false\n }: {\n inclusive?: boolean\n } = {}\n): types.PageBlock | null => {\n let currentRecord: types.Block | types.Collection | undefined = block\n\n while (currentRecord) {\n if (inclusive && (currentRecord as types.Block)?.type === 'page') {\n return currentRecord as types.PageBlock\n }\n\n const parentId: string = currentRecord.parent_id\n const parentTable = currentRecord.parent_table\n\n if (!parentId) {\n break\n }\n\n if (parentTable === 'collection') {\n currentRecord = recordMap.collection[parentId]?.value\n } else {\n currentRecord = recordMap.block[parentId]?.value\n\n if ((currentRecord as types.Block)?.type === 'page') {\n return currentRecord as types.PageBlock\n }\n }\n }\n\n return null\n}\n","import { type ExtendedRecordMap } from 'notion-types'\n\nimport { getBlockTitle } from './get-block-title'\nimport { getPageProperty } from './get-page-property'\nimport { normalizeTitle } from './normalize-title'\nimport { uuidToId } from './uuid-to-id'\n\n/**\n * Gets the canonical, display-friendly version of a page's ID for use in URLs.\n */\nexport const getCanonicalPageId = (\n pageId: string,\n recordMap: ExtendedRecordMap,\n { uuid = true }: { uuid?: boolean } = {}\n): string | null => {\n if (!pageId || !recordMap) return null\n\n const id = uuidToId(pageId)\n const block = recordMap.block[pageId]?.value\n\n if (block) {\n const slug =\n (getPageProperty('slug', block, recordMap) as string | null) ||\n (getPageProperty('Slug', block, recordMap) as string | null) ||\n normalizeTitle(getBlockTitle(block, recordMap))\n\n if (slug) {\n if (uuid) {\n return `${slug}-${id}`\n } else {\n return slug\n }\n }\n }\n\n return id\n}\n","import {\n type Block,\n type DateFormat,\n type ExtendedRecordMap\n} from 'notion-types'\n\nimport { getTextContent } from './get-text-content'\n\n/**\n * Gets the value of a collection property for a given page (collection item).\n *\n * @param propertyName property name\n * @param block Page block, often be first block in blockMap\n * @param recordMap\n * @returns - The return value types will follow the following principles:\n * 1. if property is date type, it will return `number` or `number[]`(depends on `End Date` switch)\n * 2. property is text-like will return `string`\n * 3. multi select property will return `string[]`\n * 4. checkbox property return `boolean`\n * @todo complete all no-text property type\n */\nexport function getPageProperty<\n T = string | number | boolean | string[] | number[]\n>(propertyName: string, block: Block, recordMap: ExtendedRecordMap): T\nexport function getPageProperty(\n propertyName: string,\n block: Block,\n recordMap: ExtendedRecordMap\n) {\n try {\n if (!block.properties || !Object.keys(recordMap.collection)) {\n // console.warn(\n // `block ${block.id} has no properties or this recordMap has no collection record`\n // )\n return null\n }\n\n const collection = recordMap.collection[block.parent_id]?.value\n\n if (collection) {\n const propertyNameL = propertyName.toLowerCase()\n const propertyId = Object.keys(collection.schema).find(\n (key) => collection.schema[key]?.name?.toLowerCase() === propertyNameL\n )\n\n if (!propertyId) {\n return null\n }\n\n const s = collection.schema[propertyId]\n if (!s) {\n return null\n }\n\n const { type } = s\n const content = getTextContent(block.properties[propertyId])\n\n switch (type) {\n case 'created_time':\n return block.created_time\n\n case 'multi_select':\n return content.split(',')\n\n case 'date': {\n const property = block.properties[propertyId] as [['‣', [DateFormat]]]\n const formatDate = property[0][1][0][1]\n\n if (formatDate.type === 'datetime') {\n return new Date(\n `${formatDate.start_date} ${formatDate.start_time}`\n ).getTime()\n } else if (formatDate.type === 'date') {\n return new Date(formatDate.start_date).getTime()\n } else if (formatDate.type === 'datetimerange') {\n const { start_date, start_time, end_date, end_time } = formatDate\n const startTime = new Date(`${start_date} ${start_time}`).getTime()\n const endTime = new Date(`${end_date} ${end_time}`).getTime()\n return [startTime, endTime]\n } else {\n const startTime = new Date(formatDate.start_date).getTime()\n const endTime = new Date(formatDate.end_date!).getTime()\n return [startTime, endTime]\n }\n }\n\n case 'checkbox':\n return content === 'Yes'\n\n case 'last_edited_time':\n return block.last_edited_time\n\n default:\n return content\n }\n }\n } catch {\n // ensure that no matter what, we don't throw errors because of an unexpected\n // collection data format\n }\n\n return null\n}\n","export const normalizeTitle = (title?: string | null): string => {\n return (title || '')\n .replaceAll(' ', '-')\n .replaceAll(\n /[^\\dA-Za-z\\u3000-\\u303F\\u3041-\\u3096\\u30A1-\\u30FC\\u4E00-\\u9FFF\\uAC00-\\uD7AF-]/g,\n ''\n )\n .replaceAll('--', '-')\n .replace(/-$/, '')\n .replace(/^-/, '')\n .trim()\n .toLowerCase()\n}\n","export const uuidToId = (uuid: string) => uuid.replaceAll('-', '')\n","import type * as types from 'notion-types'\n\n/**\n * Attempts to find a valid date from a given property.\n */\nexport const getDateValue = (prop: any[]): types.FormattedDate | null => {\n if (prop && Array.isArray(prop)) {\n if (prop[0] === 'd') {\n return prop[1] as types.FormattedDate\n } else {\n for (const v of prop) {\n const value = getDateValue(v as any[])\n if (value) {\n return value\n }\n }\n }\n }\n\n return null\n}\n","import type * as types from 'notion-types'\n\nimport { getBlockIcon } from './get-block-icon'\nimport { getBlockParentPage } from './get-block-parent-page'\nimport { getBlockTitle } from './get-block-title'\n\nexport const getPageBreadcrumbs = (\n recordMap: types.ExtendedRecordMap,\n activePageId: string\n): Array<any> | null => {\n const blockMap = recordMap.block\n const breadcrumbs = []\n\n let currentPageId = activePageId\n\n do {\n const block = blockMap[currentPageId]?.value\n if (!block) {\n break\n }\n\n const title = getBlockTitle(block, recordMap)\n const icon = getBlockIcon(block, recordMap)\n\n if (!(title || icon)) {\n break\n }\n\n breadcrumbs.push({\n block,\n active: currentPageId === activePageId,\n pageId: currentPageId,\n title,\n icon\n })\n\n const parentBlock = getBlockParentPage(block, recordMap)\n const parentId = parentBlock?.id\n\n if (!parentId) {\n break\n }\n\n currentPageId = parentId\n } while (true)\n\n breadcrumbs.reverse()\n\n return breadcrumbs\n}\n","import type * as types from 'notion-types'\n\n/**\n * Gets the IDs of all blocks contained on a page starting from a root block ID.\n */\nexport const getPageContentBlockIds = (\n recordMap: types.ExtendedRecordMap,\n blockId?: string\n): string[] => {\n const rootBlockId = blockId || Object.keys(recordMap.block)[0]!\n const contentBlockIds = new Set<string>()\n\n function addContentBlocks(blockId: string) {\n if (contentBlockIds.has(blockId)) return\n contentBlockIds.add(blockId)\n\n const block = recordMap.block[blockId]?.value\n if (!block) return\n\n const { content, type, properties, format } = block\n if (properties) {\n // TODO: this needs some love, especially for resolving relation properties\n // see this collection_view_page for an example: 8a586d253f984b85b48254da84465d23\n for (const key of Object.keys(properties)) {\n const p = properties[key]\n if (!p) continue\n\n for (const d of p) {\n const value = d?.[0]?.[1]?.[0]\n if (value?.[0] === 'p' && value[1]) {\n addContentBlocks(value[1])\n }\n }\n\n // [[\"‣\", [[\"p\", \"841918aa-f2a3-4d4c-b5ad-64b0f57c47b8\"]]]]\n const value = p?.[0]?.[1]?.[0]\n\n if (value?.[0] === 'p' && value[1]) {\n addContentBlocks(value[1])\n }\n }\n }\n\n if (format) {\n const referenceId = format.transclusion_reference_pointer?.id\n if (referenceId) {\n addContentBlocks(referenceId)\n }\n }\n\n if (!content || !Array.isArray(content)) {\n // no child content blocks to recurse on\n return\n }\n\n if (blockId !== rootBlockId) {\n if (type === 'page' || type === 'collection_view_page') {\n // ignore the content of other pages and collections\n return\n }\n }\n\n for (const blockId of content) {\n addContentBlocks(blockId)\n }\n }\n\n addContentBlocks(rootBlockId)\n return Array.from(contentBlockIds)\n}\n","export { default as isUrl } from 'is-url-superb'\n","import type * as types from 'notion-types'\n\nimport { getBlockIcon } from './get-block-icon'\nimport { isUrl } from './is-url'\n\n/**\n * Gets URLs of all images contained on the given page.\n */\nexport const getPageImageUrls = (\n recordMap: types.ExtendedRecordMap,\n {\n mapImageUrl\n }: {\n mapImageUrl: (url: string, block: types.Block) => string | undefined\n }\n): string[] => {\n const blockIds = Object.keys(recordMap.block)\n const imageUrls: string[] = blockIds\n .flatMap((blockId) => {\n const block = recordMap.block[blockId]?.value\n const images: Array<{ block: types.Block; url: string }> = []\n\n if (block) {\n if (block.type === 'image') {\n const signedUrl = recordMap.signed_urls?.[block.id]\n let source = signedUrl || block.properties?.source?.[0]?.[0]\n if (source?.includes('file.notion.so')) {\n source = block.properties?.source?.[0]?.[0]\n }\n\n if (source) {\n images.push({\n block,\n url: source\n })\n }\n }\n\n if ((block.format as any)?.page_cover) {\n const source = (block.format as any).page_cover\n\n images.push({\n block,\n url: source\n })\n }\n\n if ((block.format as any)?.bookmark_cover) {\n const source = (block.format as any).bookmark_cover\n\n images.push({\n block,\n url: source\n })\n }\n\n if ((block.format as any)?.bookmark_icon) {\n const source = (block.format as any).bookmark_icon\n\n images.push({\n block,\n url: source\n })\n }\n\n const pageIcon = getBlockIcon(block, recordMap)\n if (pageIcon && isUrl(pageIcon)) {\n images.push({\n block,\n url: pageIcon\n })\n }\n }\n\n return images\n })\n .filter(Boolean)\n .map(({ block, url }) => mapImageUrl(url, block))\n .filter(Boolean)\n\n return Array.from(new Set(imageUrls))\n}\n","import { type ExtendedRecordMap } from 'notion-types'\n\nimport { getBlockTitle } from './get-block-title'\n\nexport function getPageTitle(recordMap: ExtendedRecordMap) {\n const rootBlockId = Object.keys(recordMap.block)[0]\n if (!rootBlockId) return null\n\n const pageBlock = recordMap.block[rootBlockId]?.value\n\n if (pageBlock) {\n return getBlockTitle(pageBlock, recordMap)\n }\n\n return null\n}\n","import type * as types from 'notion-types'\n\n/**\n * Gets the URLs of all tweets embedded on a page.\n */\nexport const getPageTweetUrls = (\n recordMap: types.ExtendedRecordMap\n): string[] => {\n const blockIds = Object.keys(recordMap.block)\n const tweetUrls: string[] = blockIds\n .map((blockId) => {\n const block = recordMap.block[blockId]?.value\n\n if (block?.type === 'tweet') {\n const tweetUrl = block.properties?.source?.[0]?.[0]\n\n if (tweetUrl) {\n return tweetUrl\n }\n }\n })\n .filter(Boolean)\n\n return Array.from(new Set(tweetUrls))\n}\n","import type * as types from 'notion-types'\n\nimport { getPageTweetUrls } from './get-page-tweet-urls'\n\n/**\n * Gets the IDs of all tweets embedded on a page.\n */\nexport const getPageTweetIds = (\n recordMap: types.ExtendedRecordMap\n): string[] => {\n const tweetUrls = getPageTweetUrls(recordMap)\n return tweetUrls\n .map((url) => {\n try {\n const u = new URL(url)\n const parts = u.pathname.split('/')\n return parts.at(-1)\n } catch {\n return\n }\n })\n .filter(Boolean)\n}\n","import { type Block } from 'notion-types'\n\nexport const defaultMapImageUrl = (\n url: string | undefined,\n block: Block\n): string | undefined => {\n if (!url) {\n return undefined\n }\n\n if (url.startsWith('data:')) {\n return url\n }\n\n // more recent versions of notion don't proxy unsplash images\n if (url.startsWith('https://images.unsplash.com')) {\n return url\n }\n\n try {\n const u = new URL(url)\n\n if (\n u.pathname.startsWith('/secure.notion-static.com') &&\n u.hostname.endsWith('.amazonaws.com')\n ) {\n if (\n u.searchParams.has('X-Amz-Credential') &&\n u.searchParams.has('X-Amz-Signature') &&\n u.searchParams.has('X-Amz-Algorithm')\n ) {\n // if the URL is already signed, then use it as-is\n return url\n }\n }\n\n if (u.hostname === 'img.notionusercontent.com') {\n return url\n }\n } catch {\n // ignore invalid urls\n }\n\n if (url.startsWith('/images')) {\n url = `https://www.notion.so${url}`\n }\n\n url = `https://www.notion.so${\n url.startsWith('/image') ? url : `/image/${encodeURIComponent(url)}`\n }`\n\n const notionImageUrlV2 = new URL(url)\n let table = block.parent_table === 'space' ? 'block' : block.parent_table\n if (table === 'collection' || table === 'team') {\n table = 'block'\n }\n notionImageUrlV2.searchParams.set('table', table)\n notionImageUrlV2.searchParams.set('id', block.id)\n notionImageUrlV2.searchParams.set('cache', 'v2')\n\n url = notionImageUrlV2.toString()\n\n return url\n}\n","export const defaultMapPageUrl = (rootPageId?: string) => (pageId: string) => {\n pageId = (pageId || '').replaceAll('-', '')\n\n if (rootPageId && pageId === rootPageId) {\n return '/'\n } else {\n return `/${pageId}`\n }\n}\n","import { type ExtendedRecordMap } from 'notion-types'\n\nexport function mergeRecordMaps(\n recordMapA: ExtendedRecordMap,\n recordMapB: ExtendedRecordMap\n): ExtendedRecordMap {\n const mergedRecordMap: ExtendedRecordMap = {\n block: {\n ...recordMapA.block,\n ...recordMapB.block\n },\n collection: {\n ...recordMapA.collection,\n ...recordMapB.collection\n },\n collection_view: {\n ...recordMapA.collection_view,\n ...recordMapB.collection_view\n },\n notion_user: {\n ...recordMapA.notion_user,\n ...recordMapB.notion_user\n },\n collection_query: {\n ...recordMapA.collection_query,\n ...recordMapB.collection_query\n },\n signed_urls: {\n ...recordMapA.signed_urls,\n ...recordMapB.signed_urls\n },\n preview_images: {\n ...recordMapA.preview_images,\n ...recordMapB.preview_images\n }\n }\n\n return mergedRecordMap\n}\n","import memoize from 'memoize'\nimport normalizeUrlImpl from 'normalize-url'\n\nexport const normalizeUrl = memoize((url?: string) => {\n if (!url) {\n return ''\n }\n\n try {\n if (url.startsWith('https://www.notion.so/image/')) {\n const u = new URL(url)\n const subUrl = decodeURIComponent(u.pathname.slice('/image/'.length))\n const normalizedSubUrl = normalizeUrl(subUrl)\n u.pathname = `/image/${encodeURIComponent(normalizedSubUrl)}`\n url = u.toString()\n }\n\n return normalizeUrlImpl(url, {\n stripProtocol: true,\n stripWWW: true,\n stripHash: true,\n stripTextFragment: true,\n removeQueryParameters: true\n })\n } catch {\n return ''\n }\n})\n"],"mappings":";AAAA,OAIO;;;ACJP,OAAmD;;;ACAnD,OAAmD;AAE5C,SAAS,qBACd,OACA,WACe;AALjB;AAME,QAAM,eACH,MAAc,mBACd,iBAAc,WAAd,mBAAsB,uBAAtB,mBAA0C;AAE7C,MAAI,cAAc;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,oBAAoB,oCAAe,aAAf,mBAA0B;AACpD,MAAI,kBAAkB;AACpB,UAAM,kBAAiB,qBAAU,oBAAV,mBAA4B,sBAA5B,mBAA+C;AACtE,QAAI,gBAAgB;AAClB,YAAMA,iBAAe,0BAAe,WAAf,mBAAuB,uBAAvB,mBAA2C;AAChE,aAAOA;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;;;AChBO,IAAM,iBAAiB,CAAC,SAAsC;AARrE;AASE,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT,WAAW,MAAM,QAAQ,IAAI,GAAG;AAC9B,YACE,kCAAM;AAAA,MACJ,CAAC,MAAM,YACL,QAAQ,QAAQ,CAAC,MAAM,YAAO,QAAQ,CAAC,MAAM,WAAM,QAAQ,CAAC,IAAI;AAAA,MAClE;AAAA,UAHF,YAIK;AAAA,EAET,OAAO;AACL,WAAO;AAAA,EACT;AACF;;;AFjBO,SAAS,cAAc,OAAc,WAA8B;AAL1E;AAME,OAAI,WAAM,eAAN,mBAAkB,OAAO;AAC3B,WAAO,eAAe,MAAM,WAAW,KAAK;AAAA,EAC9C;AAEA,MACE,MAAM,SAAS,0BACf,MAAM,SAAS,mBACf;AACA,UAAM,eAAe,qBAAqB,OAAO,SAAS;AAE1D,QAAI,cAAc;AAChB,YAAM,cAAa,eAAU,WAAW,YAAY,MAAjC,mBAAoC;AAEvD,UAAI,YAAY;AACd,eAAO,eAAe,WAAW,IAAI;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AGfA,IAAM,eAAe;AAAA,EACnB,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,gBAAgB;AAClB;AAMO,IAAM,yBAAyB,CACpC,MACA,cACgC;AAKhC,WAAS,oBAAoB,SAAiC;AAC5D,YAAQ,4BAAW,CAAC,GAAG,IAAI,CAAC,YAAoB;AA9BpD;AA+BM,YAAM,SAAQ,eAAU,MAAM,OAAO,MAAvB,mBAA0B;AAExC,UAAI,OAAO;AACT,cAAM,EAAE,KAAK,IAAI;AAEjB,YACE,SAAS,YACT,SAAS,gBACT,SAAS,kBACT;AACA,iBAAO;AAAA,YACL,IAAI;AAAA,YACJ;AAAA,YACA,MAAM,gBAAe,WAAM,eAAN,mBAAkB,KAAK;AAAA,YAC5C,aAAa,aAAa,IAAI;AAAA,UAChC;AAAA,QACF;AAEA,YAAI,SAAS,0BAA0B;AACrC,iBAAO,oBAAoB,MAAM,OAAO;AAAA,QAC1C;AAAA,MACF;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,MAAM,oBAAoB,KAAK,OAAO,EAEzC,KAAK,EACL,OAAO,OAAO;AAEjB,QAAM,mBAAmB;AAAA,IACvB;AAAA,MACE,QAAQ;AAAA,MACR,WAAW;AAAA,IACb;AAAA,EACF;AAKA,aAAW,WAAW,KAAK;AACzB,UAAM,EAAE,YAAY,IAAI;AACxB,UAAM,SAAS;AAEf,OAAG;AACD,YAAM,aAAa,iBAAiB,GAAG,EAAE;AACzC,YAAM,EAAE,QAAQ,YAAY,WAAW,cAAc,IAAI;AAEzD,UAAI,SAAS,YAAY;AACvB,gBAAQ,cAAc,gBAAgB;AACtC,yBAAiB,KAAK;AAAA,UACpB;AAAA,UACA,WAAW,QAAQ;AAAA,QACrB,CAAC;AAAA,MACH,WAAW,WAAW,YAAY;AAChC,gBAAQ,cAAc;AACtB;AAAA,MACF,OAAO;AACL,yBAAiB,IAAI;AAAA,MACvB;AAAA,IACF,SAAS;AAAA,EACX;AAEA,SAAO;AACT;;;AJ7DO,SAAS,qBACd,OACA,WACA;AAAA,EACE,iBAAiB;AAAA,EACjB,yBAAyB;AAC3B,IAAiC,CAAC,GACZ;AACtB,QAAM,QAAQ,qBAAqB,OAAO,SAAS;AACnD,QAAM,8BAA8B,MAAM,WAAW;AACrD,QAAM,8BACJ,MAAM,YAAY,KACb,MAAM,YAAY,KAAM,yBAAyB,MACjD,MAAM,YAAY,MAAM,IACxB,MAAM,YAAY,KAClB,IAAI,0BAA0B,IAAI,MAAM;AAC/C,QAAM,8BAA8B,8BAA8B;AAElE,QAAM,yBACJ,8BAA8B;AAEhC,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAQO,SAAS,sCACd,OACA,WACA,MACA;AACA,QAAM,WAAW,qBAAqB,OAAO,WAAW,IAAI;AAC5D,SAAO,iBAAiB,SAAS,sBAAsB;AACzD;AAEA,SAAS,qBACP,OACA,WACc;AAnFhB;AAoFE,QAAM,QAAsB;AAAA,IAC1B,UAAU;AAAA,IACV,WAAW;AAAA,EACb;AAEA,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,aAAW,WAAW,MAAM,WAAW,CAAC,GAAG;AACzC,UAAM,SAAQ,eAAU,MAAM,OAAO,MAAvB,mBAA0B;AACxC,QAAI,UAAU;AACd,QAAI,CAAC,MAAO;AAEZ,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK,kBAAkB;AACrB,cAAM,QAAQ,cAAc,OAAO,SAAS;AAC5C,cAAM,YAAY,iBAAiB,KAAK;AACxC;AAAA,MACF;AAAA,MAEA,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK,QAAQ;AACX,cAAM,QAAQ,cAAc,OAAO,SAAS;AAC5C,cAAM,YAAY,iBAAiB,KAAK;AACxC,kBAAU;AACV;AAAA,MACF;AAAA,MAEA,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AAEH,cAAM,aAAa;AACnB;AAAA,MAEF,KAAK;AAEH,cAAM,aAAa;AACnB;AAAA,MAEF,KAAK;AAEH,cAAM,aAAa;AACnB;AAAA,MAEF,KAAK;AAAA;AAAA,MAEL,KAAK;AAEH,cAAM,aAAa;AACnB;AAAA,MAEF,KAAK;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL,KAAK;AACH,kBAAU;AACV;AAAA,MAEF,KAAK,qBAAqB;AACxB,cAAM,OAAO;AACb,YAAI,CAAC,KAAM;AAEX,cAAM,MAAM,uBAAuB,MAAM,SAAS;AAClD,mBAAW,WAAW,KAAK;AACzB,gBAAM,YAAY,iBAAiB,QAAQ,IAAI;AAAA,QACjD;AAEA;AAAA,MACF;AAAA,MAEA,KAAK,0BAA0B;AAC7B,cAAM,sBACJ,0CAAO,WAAP,mBAAe,mCAAf,mBAA+C;AAEjD,YAAI,CAAC,oBAAoB;AACvB;AAAA,QACF;AACA,cAAM,kBAAiB,eAAU,MAAM,kBAAkB,MAAlC,mBAAqC;AAC5D,YAAI,gBAAgB;AAClB;AAAA,YACE;AAAA,YACA,qBAAqB,gBAAgB,SAAS;AAAA,UAChD;AAAA,QACF;AACA;AAAA,MACF;AAAA,MAEA;AAEE;AAAA,IACJ;AAEA,QAAI,SAAS;AACX,wBAAkB,OAAO,qBAAqB,OAAO,SAAS,CAAC;AAAA,IACjE;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,kBAAkB,QAAsB,QAAsB;AACrE,SAAO,YAAY,OAAO;AAC1B,SAAO,aAAa,OAAO;AAC7B;AAEA,SAAS,iBAAiB,MAAsB;AAC9C,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,UAAQ,KAAK,MAAM,MAAM,KAAK,CAAC,GAAG;AACpC;AAEA,SAAS,iBAAiB,MAAsB;AAC9C,MAAI,OAAO,KAAK;AACd,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,KAAK;AACd,WAAO;AAAA,EACT;AAEA,SAAO,GAAG,KAAK,KAAK,IAAI,CAAC;AAC3B;;;AK3PO,IAAM,aAAa,CACxB,OACA,EAAE,QAAQ,QAAQ,IAAkC,CAAC,MAClD;AACH,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,QAAM,cAAc,KAAK,eAAe,SAAS,EAAE,MAAM,CAAC;AAC1D,SAAO,GAAG,WAAW,IAAI,KAAK,WAAW,CAAC,KAAK,KAAK,eAAe,CAAC;AACtE;;;ACEO,IAAM,uBAAuB,CAAC,aAA6B;AAEhE,QAAM,aAAa,GAAG,SAAS,UAAU,IACvC,SAAS,cAAc,OACzB;AACA,SAAO,WAAW,UAAU;AAC9B;;;ACfA,OAAqD;AACrD,OAAO,YAAY;;;ACDZ,IAAM,WAAW,CAAC,KAAK,OAC5B,GAAG,GAAG,MAAM,GAAG,CAAC,CAAC,IAAI,GAAG,MAAM,GAAG,EAAE,CAAC,IAAI,GAAG,MAAM,IAAI,EAAE,CAAC,IAAI,GAAG;AAAA,EAC7D;AAAA,EACA;AACF,CAAC,IAAI,GAAG,MAAM,EAAE,CAAC;;;ACFnB,IAAM,WAAW;AAIjB,IAAM,YAAY;AAOX,IAAM,cAAc,CACzB,KAAgC,IAChC,EAAE,OAAO,KAAK,IAAwB,CAAC,MAChB;AACvB,MAAI,CAAC,GAAI;AAET,OAAK,GAAG,MAAM,GAAG,EAAE,CAAC;AACpB,MAAI,CAAC,GAAI;AAET,QAAM,QAAQ,GAAG,MAAM,QAAQ;AAE/B,MAAI,OAAO;AACT,WAAO,OAAO,SAAS,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC;AAAA,EAC5C;AAEA,QAAM,SAAS,GAAG,MAAM,SAAS;AACjC,MAAI,QAAQ;AACV,WAAO,OAAO,OAAO,CAAC,IAAI,OAAO,CAAC,EAAG,WAAW,KAAK,EAAE;AAAA,EACzD;AAEA;AACF;;;AFfA,eAAsB,mBACpB,YACA,aACA,SACA;AAAA,EACE,cAAc;AAAA,EACd,sBAAsB;AAAA,EACtB;AAAA,EACA,WAAW,OAAO;AACpB,IAKI,CAAC,GACa;AAClB,QAAM,QAAiB,CAAC;AACxB,QAAM,iBAAiB,oBAAI,IAAY;AACvC,QAAM,QAAQ,IAAI,OAAO,EAAE,YAAY,CAAC;AAExC,iBAAe,YAAY,QAAgB,QAAQ,GAAG;AACpD,QAAI,QAAQ,UAAU;AACpB;AAAA,IACF;AAEA,QAAI,gBAAgB,eAAe,IAAI,YAAY,GAAG;AACpD;AAAA,IACF;AAEA,aAAS,YAAY,MAAM;AAE3B,QAAI,UAAU,CAAC,MAAM,MAAM,KAAK,CAAC,eAAe,IAAI,MAAM,GAAG;AAC3D,qBAAe,IAAI,MAAM;AAEzB,WAAK,MAAM,IAAI,YAAY;AArDjC;AAsDQ,YAAI;AACF,cACE,gBACA,eAAe,IAAI,YAAY,KAC/B,WAAW,cACX;AACA;AAAA,UACF;AAEA,gBAAM,OAAO,MAAM,QAAQ,MAAM;AACjC,cAAI,CAAC,MAAM;AACT;AAAA,UACF;AAEA,gBAAM,WAAU,gBAAK,MAAM,MAAM,MAAjB,mBAAoB,UAApB,mBAA2B;AAE3C,cAAI,SAAS;AACX,gBAAI,CAAC,aAAa;AAChB,4BAAc;AAAA,YAChB,WAAW,gBAAgB,SAAS;AAClC;AAAA,YACF;AAAA,UACF;AAEA,qBAAW,aAAa,OAAO,KAAK,KAAK,KAAK,EAAE,OAAO,CAAC,QAAQ;AA9E1E,gBAAAC;AA+EY,kBAAM,SAAQA,MAAA,KAAK,MAAM,GAAG,MAAd,gBAAAA,IAAiB;AAC/B,gBAAI,CAAC,SAAS,MAAM,UAAU,MAAO,QAAO;AAE5C,gBACE,MAAM,SAAS,UACf,MAAM,SAAS,wBACf;AACA,qBAAO;AAAA,YACT;AAIA,gBACE,eACA,MAAM,YACN,MAAM,aAAa,aACnB;AACA,qBAAO;AAAA,YACT;AAEA,mBAAO;AAAA,UACT,CAAC,GAAG;AACF,iBAAK,YAAY,WAAW,QAAQ,CAAC;AAAA,UACvC;AAGA,cAAI,qBAAqB;AACvB,uBAAW,mBAAmB,OAAO;AAAA,cACnC,KAAK;AAAA,YACP,GAAG;AACD,yBAAW,kBAAkB,OAAO,OAAO,eAAe,GAAG;AAC3D,sBAAM,EAAE,SAAS,IAAI;AAErB,oBAAI,UAAU;AACZ,6BAAW,oBAAoB,UAAU;AACvC,yBAAK,YAAY,kBAAkB,QAAQ,CAAC;AAAA,kBAC9C;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAEA,gBAAM,MAAM,IAAI;AAAA,QAClB,SAAS,KAAU;AACjB,kBAAQ;AAAA,YACN;AAAA,YACA,EAAE,QAAQ,SAAS,YAAY;AAAA,YAC/B,IAAI;AAAA,YACJ,IAAI;AAAA,UACN;AACA,gBAAM,MAAM,IAAI;AAAA,QAClB;AAEA,uBAAe,OAAO,MAAM;AAAA,MAC9B,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,YAAY,UAAU;AAC5B,QAAM,MAAM,OAAO;AAEnB,SAAO;AACT;;;AG7IA,OAIO;AAIA,SAAS,aAAa,OAAc,WAA8B;AARzE;AASE,OAAK,WAAoB,WAApB,mBAA4B,WAAW;AAC1C,YAAQ,WAAoB,WAApB,mBAA4B;AAAA,EACtC;AAEA,MACE,MAAM,SAAS,0BACf,MAAM,SAAS,mBACf;AACA,UAAM,eAAe,qBAAqB,OAAO,SAAS;AAC1D,QAAI,cAAc;AAChB,YAAM,cAAa,eAAU,WAAW,YAAY,MAAjC,mBAAoC;AAEvD,UAAI,YAAY;AACd,eAAO,WAAW;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;ACpBO,IAAM,qBAAqB,CAChC,OACA,WACA;AAAA,EACE,YAAY;AACd,IAEI,CAAC,MACsB;AAhB7B;AAiBE,MAAI,gBAA4D;AAEhE,SAAO,eAAe;AACpB,QAAI,cAAc,+CAA+B,UAAS,QAAQ;AAChE,aAAO;AAAA,IACT;AAEA,UAAM,WAAmB,cAAc;AACvC,UAAM,cAAc,cAAc;AAElC,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AAEA,QAAI,gBAAgB,cAAc;AAChC,uBAAgB,eAAU,WAAW,QAAQ,MAA7B,mBAAgC;AAAA,IAClD,OAAO;AACL,uBAAgB,eAAU,MAAM,QAAQ,MAAxB,mBAA2B;AAE3C,WAAK,+CAA+B,UAAS,QAAQ;AACnD,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AC3CA,OAAuC;;;ACAvC,OAIO;AAoBA,SAAS,gBACd,cACA,OACA,WACA;AA5BF;AA6BE,MAAI;AACF,QAAI,CAAC,MAAM,cAAc,CAAC,OAAO,KAAK,UAAU,UAAU,GAAG;AAI3D,aAAO;AAAA,IACT;AAEA,UAAM,cAAa,eAAU,WAAW,MAAM,SAAS,MAApC,mBAAuC;AAE1D,QAAI,YAAY;AACd,YAAM,gBAAgB,aAAa,YAAY;AAC/C,YAAM,aAAa,OAAO,KAAK,WAAW,MAAM,EAAE;AAAA,QAChD,CAAC,QAAK;AA1Cd,cAAAC,KAAA;AA0CiB,yBAAAA,MAAA,WAAW,OAAO,GAAG,MAArB,gBAAAA,IAAwB,SAAxB,mBAA8B,mBAAkB;AAAA;AAAA,MAC3D;AAEA,UAAI,CAAC,YAAY;AACf,eAAO;AAAA,MACT;AAEA,YAAM,IAAI,WAAW,OAAO,UAAU;AACtC,UAAI,CAAC,GAAG;AACN,eAAO;AAAA,MACT;AAEA,YAAM,EAAE,KAAK,IAAI;AACjB,YAAM,UAAU,eAAe,MAAM,WAAW,UAAU,CAAC;AAE3D,cAAQ,MAAM;AAAA,QACZ,KAAK;AACH,iBAAO,MAAM;AAAA,QAEf,KAAK;AACH,iBAAO,QAAQ,MAAM,GAAG;AAAA,QAE1B,KAAK,QAAQ;AACX,gBAAM,WAAW,MAAM,WAAW,UAAU;AAC5C,gBAAMC,cAAa,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAEtC,cAAIA,YAAW,SAAS,YAAY;AAClC,oBAAO,oBAAI;AAAA,cACT,GAAGA,YAAW,UAAU,IAAIA,YAAW,UAAU;AAAA,YACnD,GAAE,QAAQ;AAAA,UACZ,WAAWA,YAAW,SAAS,QAAQ;AACrC,mBAAO,IAAI,KAAKA,YAAW,UAAU,EAAE,QAAQ;AAAA,UACjD,WAAWA,YAAW,SAAS,iBAAiB;AAC9C,kBAAM,EAAE,YAAY,YAAY,UAAU,SAAS,IAAIA;AACvD,kBAAM,aAAY,oBAAI,KAAK,GAAG,UAAU,IAAI,UAAU,EAAE,GAAE,QAAQ;AAClE,kBAAM,WAAU,oBAAI,KAAK,GAAG,QAAQ,IAAI,QAAQ,EAAE,GAAE,QAAQ;AAC5D,mBAAO,CAAC,WAAW,OAAO;AAAA,UAC5B,OAAO;AACL,kBAAM,YAAY,IAAI,KAAKA,YAAW,UAAU,EAAE,QAAQ;AAC1D,kBAAM,UAAU,IAAI,KAAKA,YAAW,QAAS,EAAE,QAAQ;AACvD,mBAAO,CAAC,WAAW,OAAO;AAAA,UAC5B;AAAA,QACF;AAAA,QAEA,KAAK;AACH,iBAAO,YAAY;AAAA,QAErB,KAAK;AACH,iBAAO,MAAM;AAAA,QAEf;AACE,iBAAO;AAAA,MACX;AAAA,IACF;AAAA,EACF,SAAQ;AAAA,EAGR;AAEA,SAAO;AACT;;;ACtGO,IAAM,iBAAiB,CAAC,UAAkC;AAC/D,UAAQ,SAAS,IACd,WAAW,KAAK,GAAG,EACnB;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,WAAW,MAAM,GAAG,EACpB,QAAQ,MAAM,EAAE,EAChB,QAAQ,MAAM,EAAE,EAChB,KAAK,EACL,YAAY;AACjB;;;ACZO,IAAM,WAAW,CAAC,SAAiB,KAAK,WAAW,KAAK,EAAE;;;AHU1D,IAAM,qBAAqB,CAChC,QACA,WACA,EAAE,OAAO,KAAK,IAAwB,CAAC,MACrB;AAdpB;AAeE,MAAI,CAAC,UAAU,CAAC,UAAW,QAAO;AAElC,QAAM,KAAK,SAAS,MAAM;AAC1B,QAAM,SAAQ,eAAU,MAAM,MAAM,MAAtB,mBAAyB;AAEvC,MAAI,OAAO;AACT,UAAM,OACH,gBAAgB,QAAQ,OAAO,SAAS,KACxC,gBAAgB,QAAQ,OAAO,SAAS,KACzC,eAAe,cAAc,OAAO,SAAS,CAAC;AAEhD,QAAI,MAAM;AACR,UAAI,MAAM;AACR,eAAO,GAAG,IAAI,IAAI,EAAE;AAAA,MACtB,OAAO;AACL,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AI/BO,IAAM,eAAe,CAAC,SAA4C;AACvE,MAAI,QAAQ,MAAM,QAAQ,IAAI,GAAG;AAC/B,QAAI,KAAK,CAAC,MAAM,KAAK;AACnB,aAAO,KAAK,CAAC;AAAA,IACf,OAAO;AACL,iBAAW,KAAK,MAAM;AACpB,cAAM,QAAQ,aAAa,CAAU;AACrC,YAAI,OAAO;AACT,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;ACdO,IAAM,qBAAqB,CAChC,WACA,iBACsB;AATxB;AAUE,QAAM,WAAW,UAAU;AAC3B,QAAM,cAAc,CAAC;AAErB,MAAI,gBAAgB;AAEpB,KAAG;AACD,UAAM,SAAQ,cAAS,aAAa,MAAtB,mBAAyB;AACvC,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AAEA,UAAM,QAAQ,cAAc,OAAO,SAAS;AAC5C,UAAM,OAAO,aAAa,OAAO,SAAS;AAE1C,QAAI,EAAE,SAAS,OAAO;AACpB;AAAA,IACF;AAEA,gBAAY,KAAK;AAAA,MACf;AAAA,MACA,QAAQ,kBAAkB;AAAA,MAC1B,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,cAAc,mBAAmB,OAAO,SAAS;AACvD,UAAM,WAAW,2CAAa;AAE9B,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AAEA,oBAAgB;AAAA,EAClB,SAAS;AAET,cAAY,QAAQ;AAEpB,SAAO;AACT;;;AC5CO,IAAM,yBAAyB,CACpC,WACA,YACa;AACb,QAAM,cAAc,WAAW,OAAO,KAAK,UAAU,KAAK,EAAE,CAAC;AAC7D,QAAM,kBAAkB,oBAAI,IAAY;AAExC,WAAS,iBAAiBC,UAAiB;AAZ7C;AAaI,QAAI,gBAAgB,IAAIA,QAAO,EAAG;AAClC,oBAAgB,IAAIA,QAAO;AAE3B,UAAM,SAAQ,eAAU,MAAMA,QAAO,MAAvB,mBAA0B;AACxC,QAAI,CAAC,MAAO;AAEZ,UAAM,EAAE,SAAS,MAAM,YAAY,OAAO,IAAI;AAC9C,QAAI,YAAY;AAGd,iBAAW,OAAO,OAAO,KAAK,UAAU,GAAG;AACzC,cAAM,IAAI,WAAW,GAAG;AACxB,YAAI,CAAC,EAAG;AAER,mBAAW,KAAK,GAAG;AACjB,gBAAMC,UAAQ,kCAAI,OAAJ,mBAAS,OAAT,mBAAc;AAC5B,eAAIA,UAAA,gBAAAA,OAAQ,QAAO,OAAOA,OAAM,CAAC,GAAG;AAClC,6BAAiBA,OAAM,CAAC,CAAC;AAAA,UAC3B;AAAA,QACF;AAGA,cAAM,SAAQ,kCAAI,OAAJ,mBAAS,OAAT,mBAAc;AAE5B,aAAI,+BAAQ,QAAO,OAAO,MAAM,CAAC,GAAG;AAClC,2BAAiB,MAAM,CAAC,CAAC;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAEA,QAAI,QAAQ;AACV,YAAM,eAAc,YAAO,mCAAP,mBAAuC;AAC3D,UAAI,aAAa;AACf,yBAAiB,WAAW;AAAA,MAC9B;AAAA,IACF;AAEA,QAAI,CAAC,WAAW,CAAC,MAAM,QAAQ,OAAO,GAAG;AAEvC;AAAA,IACF;AAEA,QAAID,aAAY,aAAa;AAC3B,UAAI,SAAS,UAAU,SAAS,wBAAwB;AAEtD;AAAA,MACF;AAAA,IACF;AAEA,eAAWA,YAAW,SAAS;AAC7B,uBAAiBA,QAAO;AAAA,IAC1B;AAAA,EACF;AAEA,mBAAiB,WAAW;AAC5B,SAAO,MAAM,KAAK,eAAe;AACnC;;;ACrEA,SAAoB,WAAXE,gBAAwB;;;ACQ1B,IAAM,mBAAmB,CAC9B,WACA;AAAA,EACE;AACF,MAGa;AACb,QAAM,WAAW,OAAO,KAAK,UAAU,KAAK;AAC5C,QAAM,YAAsB,SACzB,QAAQ,CAAC,YAAY;AAlB1B;AAmBM,UAAM,SAAQ,eAAU,MAAM,OAAO,MAAvB,mBAA0B;AACxC,UAAM,SAAqD,CAAC;AAE5D,QAAI,OAAO;AACT,UAAI,MAAM,SAAS,SAAS;AAC1B,cAAM,aAAY,eAAU,gBAAV,mBAAwB,MAAM;AAChD,YAAI,SAAS,eAAa,uBAAM,eAAN,mBAAkB,WAAlB,mBAA2B,OAA3B,mBAAgC;AAC1D,YAAI,iCAAQ,SAAS,mBAAmB;AACtC,oBAAS,uBAAM,eAAN,mBAAkB,WAAlB,mBAA2B,OAA3B,mBAAgC;AAAA,QAC3C;AAEA,YAAI,QAAQ;AACV,iBAAO,KAAK;AAAA,YACV;AAAA,YACA,KAAK;AAAA,UACP,CAAC;AAAA,QACH;AAAA,MACF;AAEA,WAAK,WAAM,WAAN,mBAAsB,YAAY;AACrC,cAAM,SAAU,MAAM,OAAe;AAErC,eAAO,KAAK;AAAA,UACV;AAAA,UACA,KAAK;AAAA,QACP,CAAC;AAAA,MACH;AAEA,WAAK,WAAM,WAAN,mBAAsB,gBAAgB;AACzC,cAAM,SAAU,MAAM,OAAe;AAErC,eAAO,KAAK;AAAA,UACV;AAAA,UACA,KAAK;AAAA,QACP,CAAC;AAAA,MACH;AAEA,WAAK,WAAM,WAAN,mBAAsB,eAAe;AACxC,cAAM,SAAU,MAAM,OAAe;AAErC,eAAO,KAAK;AAAA,UACV;AAAA,UACA,KAAK;AAAA,QACP,CAAC;AAAA,MACH;AAEA,YAAM,WAAW,aAAa,OAAO,SAAS;AAC9C,UAAI,YAAYC,SAAM,QAAQ,GAAG;AAC/B,eAAO,KAAK;AAAA,UACV;AAAA,UACA,KAAK;AAAA,QACP,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC,EACA,OAAO,OAAO,EACd,IAAI,CAAC,EAAE,OAAO,IAAI,MAAM,YAAY,KAAK,KAAK,CAAC,EAC/C,OAAO,OAAO;AAEjB,SAAO,MAAM,KAAK,IAAI,IAAI,SAAS,CAAC;AACtC;;;ACjFA,OAAuC;AAIhC,SAAS,aAAa,WAA8B;AAJ3D;AAKE,QAAM,cAAc,OAAO,KAAK,UAAU,KAAK,EAAE,CAAC;AAClD,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,aAAY,eAAU,MAAM,WAAW,MAA3B,mBAA8B;AAEhD,MAAI,WAAW;AACb,WAAO,cAAc,WAAW,SAAS;AAAA,EAC3C;AAEA,SAAO;AACT;;;ACVO,IAAM,mBAAmB,CAC9B,cACa;AACb,QAAM,WAAW,OAAO,KAAK,UAAU,KAAK;AAC5C,QAAM,YAAsB,SACzB,IAAI,CAAC,YAAY;AAVtB;AAWM,UAAM,SAAQ,eAAU,MAAM,OAAO,MAAvB,mBAA0B;AAExC,SAAI,+BAAO,UAAS,SAAS;AAC3B,YAAM,YAAW,uBAAM,eAAN,mBAAkB,WAAlB,mBAA2B,OAA3B,mBAAgC;AAEjD,UAAI,UAAU;AACZ,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,CAAC,EACA,OAAO,OAAO;AAEjB,SAAO,MAAM,KAAK,IAAI,IAAI,SAAS,CAAC;AACtC;;;ACjBO,IAAM,kBAAkB,CAC7B,cACa;AACb,QAAM,YAAY,iBAAiB,SAAS;AAC5C,SAAO,UACJ,IAAI,CAAC,QAAQ;AACZ,QAAI;AACF,YAAM,IAAI,IAAI,IAAI,GAAG;AACrB,YAAM,QAAQ,EAAE,SAAS,MAAM,GAAG;AAClC,aAAO,MAAM,GAAG,EAAE;AAAA,IACpB,SAAQ;AACN;AAAA,IACF;AAAA,EACF,CAAC,EACA,OAAO,OAAO;AACnB;;;ACtBA,OAA2B;AAEpB,IAAM,qBAAqB,CAChC,KACA,UACuB;AACvB,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,EACT;AAEA,MAAI,IAAI,WAAW,OAAO,GAAG;AAC3B,WAAO;AAAA,EACT;AAGA,MAAI,IAAI,WAAW,6BAA6B,GAAG;AACjD,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,IAAI,IAAI,IAAI,GAAG;AAErB,QACE,EAAE,SAAS,WAAW,2BAA2B,KACjD,EAAE,SAAS,SAAS,gBAAgB,GACpC;AACA,UACE,EAAE,aAAa,IAAI,kBAAkB,KACrC,EAAE,aAAa,IAAI,iBAAiB,KACpC,EAAE,aAAa,IAAI,iBAAiB,GACpC;AAEA,eAAO;AAAA,MACT;AAAA,IACF;AAEA,QAAI,EAAE,aAAa,6BAA6B;AAC9C,aAAO;AAAA,IACT;AAAA,EACF,SAAQ;AAAA,EAER;AAEA,MAAI,IAAI,WAAW,SAAS,GAAG;AAC7B,UAAM,wBAAwB,GAAG;AAAA,EACnC;AAEA,QAAM,wBACJ,IAAI,WAAW,QAAQ,IAAI,MAAM,UAAU,mBAAmB,GAAG,CAAC,EACpE;AAEA,QAAM,mBAAmB,IAAI,IAAI,GAAG;AACpC,MAAI,QAAQ,MAAM,iBAAiB,UAAU,UAAU,MAAM;AAC7D,MAAI,UAAU,gBAAgB,UAAU,QAAQ;AAC9C,YAAQ;AAAA,EACV;AACA,mBAAiB,aAAa,IAAI,SAAS,KAAK;AAChD,mBAAiB,aAAa,IAAI,MAAM,MAAM,EAAE;AAChD,mBAAiB,aAAa,IAAI,SAAS,IAAI;AAE/C,QAAM,iBAAiB,SAAS;AAEhC,SAAO;AACT;;;AC/DO,IAAM,oBAAoB,CAAC,eAAwB,CAAC,WAAmB;AAC5E,YAAU,UAAU,IAAI,WAAW,KAAK,EAAE;AAE1C,MAAI,cAAc,WAAW,YAAY;AACvC,WAAO;AAAA,EACT,OAAO;AACL,WAAO,IAAI,MAAM;AAAA,EACnB;AACF;;;ACRA,OAAuC;AAEhC,SAAS,gBACd,YACA,YACmB;AACnB,QAAM,kBAAqC;AAAA,IACzC,OAAO;AAAA,MACL,GAAG,WAAW;AAAA,MACd,GAAG,WAAW;AAAA,IAChB;AAAA,IACA,YAAY;AAAA,MACV,GAAG,WAAW;AAAA,MACd,GAAG,WAAW;AAAA,IAChB;AAAA,IACA,iBAAiB;AAAA,MACf,GAAG,WAAW;AAAA,MACd,GAAG,WAAW;AAAA,IAChB;AAAA,IACA,aAAa;AAAA,MACX,GAAG,WAAW;AAAA,MACd,GAAG,WAAW;AAAA,IAChB;AAAA,IACA,kBAAkB;AAAA,MAChB,GAAG,WAAW;AAAA,MACd,GAAG,WAAW;AAAA,IAChB;AAAA,IACA,aAAa;AAAA,MACX,GAAG,WAAW;AAAA,MACd,GAAG,WAAW;AAAA,IAChB;AAAA,IACA,gBAAgB;AAAA,MACd,GAAG,WAAW;AAAA,MACd,GAAG,WAAW;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;;;ACtCA,OAAO,aAAa;AACpB,OAAO,sBAAsB;AAEtB,IAAM,eAAe,QAAQ,CAAC,QAAiB;AACpD,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,EACT;AAEA,MAAI;AACF,QAAI,IAAI,WAAW,8BAA8B,GAAG;AAClD,YAAM,IAAI,IAAI,IAAI,GAAG;AACrB,YAAM,SAAS,mBAAmB,EAAE,SAAS,MAAM,UAAU,MAAM,CAAC;AACpE,YAAM,mBAAmB,aAAa,MAAM;AAC5C,QAAE,WAAW,UAAU,mBAAmB,gBAAgB,CAAC;AAC3D,YAAM,EAAE,SAAS;AAAA,IACnB;AAEA,WAAO,iBAAiB,KAAK;AAAA,MAC3B,eAAe;AAAA,MACf,UAAU;AAAA,MACV,WAAW;AAAA,MACX,mBAAmB;AAAA,MACnB,uBAAuB;AAAA,IACzB,CAAC;AAAA,EACH,SAAQ;AACN,WAAO;AAAA,EACT;AACF,CAAC;","names":["collectionId","_a","_a","formatDate","blockId","value","default","default"]} | ||
| {"version":3,"sources":["../src/estimate-page-read-time.ts","../src/get-block-title.ts","../src/get-block-collection-id.ts","../src/get-text-content.ts","../src/get-page-table-of-contents.ts","../src/format-date.ts","../src/format-notion-date-time.ts","../src/get-all-pages-in-space.ts","../src/id-to-uuid.ts","../src/parse-page-id.ts","../src/get-block-icon.ts","../src/get-block-parent-page.ts","../src/get-canonical-page-id.ts","../src/get-page-property.ts","../src/normalize-title.ts","../src/uuid-to-id.ts","../src/get-date-value.ts","../src/get-page-breadcrumbs.ts","../src/get-page-content-block-ids.ts","../src/is-url.ts","../src/get-page-image-urls.ts","../src/get-page-title.ts","../src/get-page-tweet-urls.ts","../src/get-page-tweet-ids.ts","../src/map-image-url.ts","../src/map-page-url.ts","../src/merge-record-maps.ts","../src/normalize-url.ts"],"sourcesContent":["import {\n type Block,\n type ExtendedRecordMap,\n type PageBlock\n} from 'notion-types'\n\nimport { getBlockTitle } from './get-block-title'\nimport { getPageTableOfContents } from './get-page-table-of-contents'\n\ntype EstimatePageReadTimeOptions = {\n wordsPerMinute?: number\n imageReadTimeInSeconds?: number\n}\n\ntype ContentStats = {\n numWords: number\n numImages: number\n}\n\ntype PageReadTimeEstimate = ContentStats & {\n totalWordsReadTimeInMinutes: number\n totalImageReadTimeInMinutes: number\n totalReadTimeInMinutes: number\n}\n\n/**\n * Returns an estimate for the time it would take for a person to read the content\n * in the given Notion page.\n *\n * Uses Medium for inspiration.\n *\n * @see https://blog.medium.com/read-time-and-you-bc2048ab620c\n * @see https://github.com/ngryman/reading-time\n *\n * TODO: handle non-english content.\n */\nexport function estimatePageReadTime(\n block: Block,\n recordMap: ExtendedRecordMap,\n {\n wordsPerMinute = 275,\n imageReadTimeInSeconds = 12\n }: EstimatePageReadTimeOptions = {}\n): PageReadTimeEstimate {\n const stats = getBlockContentStats(block, recordMap)\n const totalWordsReadTimeInMinutes = stats.numWords / wordsPerMinute\n const totalImageReadTimeInSeconds =\n stats.numImages > 10\n ? (stats.numImages / 2) * (imageReadTimeInSeconds + 3) +\n (stats.numImages - 10) * 3 // n/2(a+b) + 3 sec/image\n : (stats.numImages / 2) *\n (2 * imageReadTimeInSeconds + (1 - stats.numImages)) // n/2[2a+(n-1)d]\n const totalImageReadTimeInMinutes = totalImageReadTimeInSeconds / 60\n\n const totalReadTimeInMinutes =\n totalWordsReadTimeInMinutes + totalImageReadTimeInMinutes\n\n return {\n ...stats,\n totalWordsReadTimeInMinutes,\n totalImageReadTimeInMinutes,\n totalReadTimeInMinutes\n }\n}\n\n/**\n * Same as `estimatePageReadTime`, except it returns the total time estimate as\n * a human-readable string.\n *\n * For example, \"9 minutes\" or \"less than a minute\".\n */\nexport function estimatePageReadTimeAsHumanizedString(\n block: Block,\n recordMap: ExtendedRecordMap,\n opts: EstimatePageReadTimeOptions\n) {\n const estimate = estimatePageReadTime(block, recordMap, opts)\n return humanizeReadTime(estimate.totalReadTimeInMinutes)\n}\n\nfunction getBlockContentStats(\n block: Block,\n recordMap: ExtendedRecordMap\n): ContentStats {\n const stats: ContentStats = {\n numWords: 0,\n numImages: 0\n }\n\n if (!block) {\n return stats\n }\n\n for (const childId of block.content || []) {\n const child = recordMap.block[childId]?.value\n let recurse = false\n if (!child) continue\n\n switch (child.type) {\n case 'quote':\n // fallthrough\n case 'alias':\n // fallthrough\n case 'header':\n // fallthrough\n case 'sub_header':\n // fallthrough\n case 'sub_sub_header': {\n const title = getBlockTitle(child, recordMap)\n stats.numWords += countWordsInText(title)\n break\n }\n\n case 'callout':\n // fallthrough\n case 'toggle':\n // fallthrough\n case 'to_do':\n // fallthrough\n case 'bulleted_list':\n // fallthrough\n case 'numbered_list':\n // fallthrough\n case 'text': {\n const title = getBlockTitle(child, recordMap)\n stats.numWords += countWordsInText(title)\n recurse = true\n break\n }\n\n case 'embed':\n // fallthrough\n case 'tweet':\n // fallthrough\n case 'maps':\n // fallthrough\n case 'pdf':\n // fallthrough\n case 'figma':\n // fallthrough\n case 'typeform':\n // fallthrough\n case 'codepen':\n // fallthrough\n case 'excalidraw':\n // fallthrough\n case 'gist':\n // fallthrough\n case 'video':\n // fallthrough\n case 'drive':\n // fallthrough\n case 'audio':\n // fallthrough\n case 'file':\n // fallthrough\n case 'image':\n // treat all embeds as images\n stats.numImages += 1\n break\n\n case 'bookmark':\n // treat bookmarks as quarter images since they aren't as content-ful as embedd images\n stats.numImages += 0.25\n break\n\n case 'code':\n // treat code blocks as double the complexity of images\n stats.numImages += 2\n break\n\n case 'table':\n // fallthrough\n case 'collection_view':\n // treat collection views as double the complexity of images\n stats.numImages += 2\n break\n\n case 'column':\n // fallthrough\n case 'column_list':\n // fallthrough\n case 'transclusion_container':\n recurse = true\n break\n\n case 'table_of_contents': {\n const page = block as PageBlock\n if (!page) continue\n\n const toc = getPageTableOfContents(page, recordMap)\n for (const tocItem of toc) {\n stats.numWords += countWordsInText(tocItem.text)\n }\n\n break\n }\n\n case 'transclusion_reference': {\n const referencePointerId =\n child?.format?.transclusion_reference_pointer?.id\n\n if (!referencePointerId) {\n continue\n }\n const referenceBlock = recordMap.block[referencePointerId]?.value\n if (referenceBlock) {\n mergeContentStats(\n stats,\n getBlockContentStats(referenceBlock, recordMap)\n )\n }\n break\n }\n\n default:\n // ignore unrecognized blocks\n break\n }\n\n if (recurse) {\n mergeContentStats(stats, getBlockContentStats(child, recordMap))\n }\n }\n\n return stats\n}\n\nfunction mergeContentStats(statsA: ContentStats, statsB: ContentStats) {\n statsA.numWords += statsB.numWords\n statsA.numImages += statsB.numImages\n}\n\nfunction countWordsInText(text: string): number {\n if (!text) {\n return 0\n }\n\n return (text.match(/\\w+/g) || []).length\n}\n\nfunction humanizeReadTime(time: number): string {\n if (time < 0.5) {\n return 'less than a minute'\n }\n\n if (time < 1.5) {\n return '1 minute'\n }\n\n return `${Math.ceil(time)} minutes`\n}\n","import { type Block, type ExtendedRecordMap } from 'notion-types'\n\nimport { getBlockCollectionId } from './get-block-collection-id'\nimport { getTextContent } from './get-text-content'\n\nexport function getBlockTitle(block: Block, recordMap: ExtendedRecordMap) {\n if (block.properties?.title) {\n return getTextContent(block.properties.title)\n }\n\n if (\n block.type === 'collection_view_page' ||\n block.type === 'collection_view'\n ) {\n const collectionId = getBlockCollectionId(block, recordMap)\n\n if (collectionId) {\n const collection = recordMap.collection[collectionId]?.value\n\n if (collection) {\n return getTextContent(collection.name)\n }\n }\n }\n\n return ''\n}\n","import { type Block, type ExtendedRecordMap } from 'notion-types'\n\nexport function getBlockCollectionId(\n block: Block,\n recordMap: ExtendedRecordMap\n): string | null {\n const collectionId =\n (block as any).collection_id ||\n (block as any).format?.collection_pointer?.id\n\n if (collectionId) {\n return collectionId\n }\n\n const collectionViewId = (block as any)?.view_ids?.[0]\n if (collectionViewId) {\n const collectionView = recordMap.collection_view?.[collectionViewId]?.value\n if (collectionView) {\n const collectionId = collectionView.format?.collection_pointer?.id\n return collectionId\n }\n }\n\n return null\n}\n","import type * as types from 'notion-types'\n\n/**\n * Gets the raw, unformatted text content of a block's content value.\n *\n * This is useful, for instance, for extracting a block's `title` without any\n * rich text formatting.\n */\nexport const getTextContent = (text?: types.Decoration[]): string => {\n if (!text) {\n return ''\n } else if (Array.isArray(text)) {\n return (\n text?.reduce(\n (prev, current) =>\n prev + (current[0] !== '⁍' && current[0] !== '‣' ? current[0] : ''),\n ''\n ) ?? ''\n )\n } else {\n return text\n }\n}\n","import type * as types from 'notion-types'\n\nimport { getTextContent } from './get-text-content'\n\nexport interface TableOfContentsEntry {\n id: types.ID\n type: types.BlockType\n text: string\n indentLevel: number\n}\n\nconst indentLevels = {\n header: 0,\n sub_header: 1,\n sub_sub_header: 2\n}\n\n/**\n * Gets the metadata for a table of contents block by parsing the page's\n * H1, H2, and H3 elements.\n */\nexport const getPageTableOfContents = (\n page: types.PageBlock,\n recordMap: types.ExtendedRecordMap\n): Array<TableOfContentsEntry> => {\n type MapResult = TableOfContentsEntry | null | MapResult[]\n\n // Maps `content` property to TOC entries.\n // Pages and transclusion containers (synced blocks) both have the property.\n function mapContentToEntries(content?: string[]): MapResult[] {\n return (content ?? []).map((blockId: string) => {\n const block = recordMap.block[blockId]?.value\n\n if (block) {\n const { type } = block\n\n if (\n type === 'header' ||\n type === 'sub_header' ||\n type === 'sub_sub_header'\n ) {\n return {\n id: blockId,\n type,\n text: getTextContent(block.properties?.title),\n indentLevel: indentLevels[type]\n }\n }\n\n if (type === 'transclusion_container') {\n return mapContentToEntries(block.content)\n }\n }\n\n return null\n })\n }\n\n const toc = mapContentToEntries(page.content)\n // Synced blocks cannot be nested. So theoretically a 1-level flattening is enough.\n .flat()\n .filter(Boolean) as Array<TableOfContentsEntry>\n\n const indentLevelStack = [\n {\n actual: -1,\n effective: -1\n }\n ]\n\n // Adjust indent levels to always change smoothly.\n // This is a little tricky, but the key is that when increasing indent levels,\n // they should never jump more than one at a time.\n for (const tocItem of toc) {\n const { indentLevel } = tocItem\n const actual = indentLevel\n\n do {\n const prevIndent = indentLevelStack.at(-1)!\n const { actual: prevActual, effective: prevEffective } = prevIndent\n\n if (actual > prevActual) {\n tocItem.indentLevel = prevEffective + 1\n indentLevelStack.push({\n actual,\n effective: tocItem.indentLevel\n })\n } else if (actual === prevActual) {\n tocItem.indentLevel = prevEffective\n break\n } else {\n indentLevelStack.pop()\n }\n } while (true)\n }\n\n return toc\n}\n","export const formatDate = (\n input: string | number,\n { month = 'short' }: { month?: 'long' | 'short' } = {}\n) => {\n const date = new Date(input)\n const monthLocale = date.toLocaleString('en-US', { month })\n return `${monthLocale} ${date.getUTCDate()}, ${date.getUTCFullYear()}`\n}\n","import { formatDate } from './format-date'\n\nexport interface NotionDateTime {\n type: 'datetime'\n start_date: string\n start_time?: string\n time_zone?: string\n}\n\nexport const formatNotionDateTime = (datetime: NotionDateTime) => {\n // Adding +00:00 preserve the time in UTC.\n const dateString = `${datetime.start_date}T${\n datetime.start_time || '00:00'\n }+00:00`\n return formatDate(dateString)\n}\n","import { type ExtendedRecordMap, type PageMap } from 'notion-types'\nimport PQueue from 'p-queue'\n\nimport { parsePageId } from './parse-page-id'\n\n/**\n * Performs a traversal over a given Notion workspace starting from a seed page.\n *\n * Returns a map containing all of the pages that are reachable from the seed\n * page in the space.\n *\n * If `rootSpaceId` is not defined, the space ID of the root page will be used\n * to scope traversal.\n *\n * @param rootPageId - Page ID to start from.\n * @param rootSpaceId - Space ID to scope traversal.\n * @param getPage - Function used to fetch a single page.\n * @param opts - Optional config\n */\nexport async function getAllPagesInSpace(\n rootPageId: string,\n rootSpaceId: string | undefined,\n getPage: (pageId: string) => Promise<ExtendedRecordMap>,\n {\n concurrency = 4,\n traverseCollections = true,\n targetPageId,\n maxDepth = Number.POSITIVE_INFINITY\n }: {\n concurrency?: number\n traverseCollections?: boolean\n targetPageId?: string\n maxDepth?: number\n } = {}\n): Promise<PageMap> {\n const pages: PageMap = {}\n const pendingPageIds = new Set<string>()\n const queue = new PQueue({ concurrency })\n\n async function processPage(pageId: string, depth = 0) {\n if (depth > maxDepth) {\n return\n }\n\n if (targetPageId && pendingPageIds.has(targetPageId)) {\n return\n }\n\n pageId = parsePageId(pageId) as string\n\n if (pageId && !pages[pageId] && !pendingPageIds.has(pageId)) {\n pendingPageIds.add(pageId)\n\n void queue.add(async () => {\n try {\n if (\n targetPageId &&\n pendingPageIds.has(targetPageId) &&\n pageId !== targetPageId\n ) {\n return\n }\n\n const page = await getPage(pageId)\n if (!page) {\n return\n }\n\n const spaceId = page.block[pageId]?.value?.space_id\n\n if (spaceId) {\n if (!rootSpaceId) {\n rootSpaceId = spaceId\n } else if (rootSpaceId !== spaceId) {\n return\n }\n }\n\n for (const subPageId of Object.keys(page.block).filter((key) => {\n const block = page.block[key]?.value\n if (!block || block.alive === false) return false\n\n if (\n block.type !== 'page' &&\n block.type !== 'collection_view_page'\n ) {\n return false\n }\n\n // the space id check is important to limit traversal because pages\n // can reference pages in other spaces\n if (\n rootSpaceId &&\n block.space_id &&\n block.space_id !== rootSpaceId\n ) {\n return false\n }\n\n return true\n })) {\n void processPage(subPageId, depth + 1)\n }\n\n // traverse collection item pages as they may contain subpages as well\n if (traverseCollections) {\n for (const collectionViews of Object.values(\n page.collection_query\n )) {\n for (const collectionData of Object.values(collectionViews)) {\n const blockIds = Array.from(\n new Set([\n ...(collectionData?.collection_group_results?.blockIds ||\n []),\n ...collectionData.blockIds\n ])\n )\n\n if (blockIds) {\n for (const collectionItemId of blockIds) {\n void processPage(collectionItemId, depth + 1)\n }\n }\n }\n }\n }\n\n pages[pageId] = page\n } catch (err: any) {\n console.warn(\n 'page load error',\n { pageId, spaceId: rootSpaceId },\n err.statusCode,\n err.message\n )\n pages[pageId] = null\n }\n\n pendingPageIds.delete(pageId)\n })\n }\n }\n\n await processPage(rootPageId)\n await queue.onIdle()\n\n return pages\n}\n","export const idToUuid = (id = '') =>\n `${id.slice(0, 8)}-${id.slice(8, 12)}-${id.slice(12, 16)}-${id.slice(\n 16,\n 20\n )}-${id.slice(20)}`\n","import { idToUuid } from './id-to-uuid'\n\nconst pageIdRe = /\\b([\\da-f]{32})\\b/\n\n// TODO\n// eslint-disable-next-line security/detect-unsafe-regex\nconst pageId2Re = /\\b([\\da-f]{8}(?:-[\\da-f]{4}){3}-[\\da-f]{12})\\b/\n\n/**\n * Robustly extracts the notion page ID from a notion URL or pathname suffix.\n *\n * Defaults to returning a UUID (with dashes).\n */\nexport const parsePageId = (\n id: string | undefined | null = '',\n { uuid = true }: { uuid?: boolean } = {}\n): string | undefined => {\n if (!id) return\n\n id = id.split('?')[0]!\n if (!id) return\n\n const match = id.match(pageIdRe)\n\n if (match) {\n return uuid ? idToUuid(match[1]) : match[1]\n }\n\n const match2 = id.match(pageId2Re)\n if (match2) {\n return uuid ? match2[1] : match2[1]!.replaceAll('-', '')\n }\n\n return\n}\n","import {\n type Block,\n type ExtendedRecordMap,\n type PageBlock\n} from 'notion-types'\n\nimport { getBlockCollectionId } from './get-block-collection-id'\n\nexport function getBlockIcon(block: Block, recordMap: ExtendedRecordMap) {\n if ((block as PageBlock).format?.page_icon) {\n return (block as PageBlock).format?.page_icon\n }\n\n if (\n block.type === 'collection_view_page' ||\n block.type === 'collection_view'\n ) {\n const collectionId = getBlockCollectionId(block, recordMap)\n if (collectionId) {\n const collection = recordMap.collection[collectionId]?.value\n\n if (collection) {\n return collection.icon\n }\n }\n }\n\n return null\n}\n","import type * as types from 'notion-types'\n\n/**\n * Returns the parent page block containing a given page.\n *\n * Note that many times this will not be the direct parent block since\n * some non-page content blocks can contain sub-blocks.\n */\nexport const getBlockParentPage = (\n block: types.Block,\n recordMap: types.ExtendedRecordMap,\n {\n inclusive = false\n }: {\n inclusive?: boolean\n } = {}\n): types.PageBlock | null => {\n let currentRecord: types.Block | types.Collection | undefined = block\n\n while (currentRecord) {\n if (inclusive && (currentRecord as types.Block)?.type === 'page') {\n return currentRecord as types.PageBlock\n }\n\n const parentId: string = currentRecord.parent_id\n const parentTable = currentRecord.parent_table\n\n if (!parentId) {\n break\n }\n\n if (parentTable === 'collection') {\n currentRecord = recordMap.collection[parentId]?.value\n } else {\n currentRecord = recordMap.block[parentId]?.value\n\n if ((currentRecord as types.Block)?.type === 'page') {\n return currentRecord as types.PageBlock\n }\n }\n }\n\n return null\n}\n","import { type ExtendedRecordMap } from 'notion-types'\n\nimport { getBlockTitle } from './get-block-title'\nimport { getPageProperty } from './get-page-property'\nimport { normalizeTitle } from './normalize-title'\nimport { uuidToId } from './uuid-to-id'\n\n/**\n * Gets the canonical, display-friendly version of a page's ID for use in URLs.\n */\nexport const getCanonicalPageId = (\n pageId: string,\n recordMap: ExtendedRecordMap,\n { uuid = true }: { uuid?: boolean } = {}\n): string | null => {\n if (!pageId || !recordMap) return null\n\n const id = uuidToId(pageId)\n const block = recordMap.block[pageId]?.value\n\n if (block) {\n const slug =\n (getPageProperty('slug', block, recordMap) as string | null) ||\n (getPageProperty('Slug', block, recordMap) as string | null) ||\n normalizeTitle(getBlockTitle(block, recordMap))\n\n if (slug) {\n if (uuid) {\n return `${slug}-${id}`\n } else {\n return slug\n }\n }\n }\n\n return id\n}\n","import {\n type Block,\n type DateFormat,\n type ExtendedRecordMap\n} from 'notion-types'\n\nimport { getTextContent } from './get-text-content'\n\n/**\n * Gets the value of a collection property for a given page (collection item).\n *\n * @param propertyName property name\n * @param block Page block, often be first block in blockMap\n * @param recordMap\n * @returns - The return value types will follow the following principles:\n * 1. if property is date type, it will return `number` or `number[]`(depends on `End Date` switch)\n * 2. property is text-like will return `string`\n * 3. multi select property will return `string[]`\n * 4. checkbox property return `boolean`\n * @todo complete all no-text property type\n */\nexport function getPageProperty<\n T = string | number | boolean | string[] | number[]\n>(propertyName: string, block: Block, recordMap: ExtendedRecordMap): T\nexport function getPageProperty(\n propertyName: string,\n block: Block,\n recordMap: ExtendedRecordMap\n) {\n try {\n if (!block.properties || !Object.keys(recordMap.collection)) {\n // console.warn(\n // `block ${block.id} has no properties or this recordMap has no collection record`\n // )\n return null\n }\n\n const collection = recordMap.collection[block.parent_id]?.value\n\n if (collection) {\n const propertyNameL = propertyName.toLowerCase()\n const propertyId = Object.keys(collection.schema).find(\n (key) => collection.schema[key]?.name?.toLowerCase() === propertyNameL\n )\n\n if (!propertyId) {\n return null\n }\n\n const s = collection.schema[propertyId]\n if (!s) {\n return null\n }\n\n const { type } = s\n const content = getTextContent(block.properties[propertyId])\n\n switch (type) {\n case 'created_time':\n return block.created_time\n\n case 'multi_select':\n return content.split(',')\n\n case 'date': {\n const property = block.properties[propertyId] as [['‣', [DateFormat]]]\n const formatDate = property[0][1][0][1]\n\n if (formatDate.type === 'datetime') {\n return new Date(\n `${formatDate.start_date} ${formatDate.start_time}`\n ).getTime()\n } else if (formatDate.type === 'date') {\n return new Date(formatDate.start_date).getTime()\n } else if (formatDate.type === 'datetimerange') {\n const { start_date, start_time, end_date, end_time } = formatDate\n const startTime = new Date(`${start_date} ${start_time}`).getTime()\n const endTime = new Date(`${end_date} ${end_time}`).getTime()\n return [startTime, endTime]\n } else {\n const startTime = new Date(formatDate.start_date).getTime()\n const endTime = new Date(formatDate.end_date!).getTime()\n return [startTime, endTime]\n }\n }\n\n case 'checkbox':\n return content === 'Yes'\n\n case 'last_edited_time':\n return block.last_edited_time\n\n default:\n return content\n }\n }\n } catch {\n // ensure that no matter what, we don't throw errors because of an unexpected\n // collection data format\n }\n\n return null\n}\n","export const normalizeTitle = (title?: string | null): string => {\n return (title || '')\n .replaceAll(' ', '-')\n .replaceAll(\n /[^\\dA-Za-z\\u3000-\\u303F\\u3041-\\u3096\\u30A1-\\u30FC\\u4E00-\\u9FFF\\uAC00-\\uD7AF-]/g,\n ''\n )\n .replaceAll('--', '-')\n .replace(/-$/, '')\n .replace(/^-/, '')\n .trim()\n .toLowerCase()\n}\n","export const uuidToId = (uuid: string) => uuid.replaceAll('-', '')\n","import type * as types from 'notion-types'\n\n/**\n * Attempts to find a valid date from a given property.\n */\nexport const getDateValue = (prop: any[]): types.FormattedDate | null => {\n if (prop && Array.isArray(prop)) {\n if (prop[0] === 'd') {\n return prop[1] as types.FormattedDate\n } else {\n for (const v of prop) {\n const value = getDateValue(v as any[])\n if (value) {\n return value\n }\n }\n }\n }\n\n return null\n}\n","import type * as types from 'notion-types'\n\nimport { getBlockIcon } from './get-block-icon'\nimport { getBlockParentPage } from './get-block-parent-page'\nimport { getBlockTitle } from './get-block-title'\n\nexport const getPageBreadcrumbs = (\n recordMap: types.ExtendedRecordMap,\n activePageId: string\n): Array<any> | null => {\n const blockMap = recordMap.block\n const breadcrumbs = []\n\n let currentPageId = activePageId\n\n do {\n const block = blockMap[currentPageId]?.value\n if (!block) {\n break\n }\n\n const title = getBlockTitle(block, recordMap)\n const icon = getBlockIcon(block, recordMap)\n\n if (!(title || icon)) {\n break\n }\n\n breadcrumbs.push({\n block,\n active: currentPageId === activePageId,\n pageId: currentPageId,\n title,\n icon\n })\n\n const parentBlock = getBlockParentPage(block, recordMap)\n const parentId = parentBlock?.id\n\n if (!parentId) {\n break\n }\n\n currentPageId = parentId\n } while (true)\n\n breadcrumbs.reverse()\n\n return breadcrumbs\n}\n","import type * as types from 'notion-types'\n\n/**\n * Gets the IDs of all blocks contained on a page starting from a root block ID.\n */\nexport const getPageContentBlockIds = (\n recordMap: types.ExtendedRecordMap,\n blockId?: string\n): string[] => {\n const rootBlockId = blockId || Object.keys(recordMap.block)[0]!\n const contentBlockIds = new Set<string>()\n\n function addContentBlocks(blockId: string) {\n if (contentBlockIds.has(blockId)) return\n contentBlockIds.add(blockId)\n\n const block = recordMap.block[blockId]?.value\n if (!block) return\n\n const { content, type, properties, format } = block\n if (properties) {\n // TODO: this needs some love, especially for resolving relation properties\n // see this collection_view_page for an example: 8a586d253f984b85b48254da84465d23\n for (const key of Object.keys(properties)) {\n const p = properties[key]\n if (!p) continue\n\n for (const d of p) {\n const value = d?.[0]?.[1]?.[0]\n if (value?.[0] === 'p' && value[1]) {\n addContentBlocks(value[1])\n }\n }\n\n // [[\"‣\", [[\"p\", \"841918aa-f2a3-4d4c-b5ad-64b0f57c47b8\"]]]]\n const value = p?.[0]?.[1]?.[0]\n\n if (value?.[0] === 'p' && value[1]) {\n addContentBlocks(value[1])\n }\n }\n }\n\n if (format) {\n const referenceId = format.transclusion_reference_pointer?.id\n if (referenceId) {\n addContentBlocks(referenceId)\n }\n }\n\n if (!content || !Array.isArray(content)) {\n // no child content blocks to recurse on\n return\n }\n\n if (blockId !== rootBlockId) {\n if (type === 'page' || type === 'collection_view_page') {\n // ignore the content of other pages and collections\n return\n }\n }\n\n for (const blockId of content) {\n addContentBlocks(blockId)\n }\n }\n\n addContentBlocks(rootBlockId)\n return Array.from(contentBlockIds)\n}\n","export { default as isUrl } from 'is-url-superb'\n","import type * as types from 'notion-types'\n\nimport { getBlockIcon } from './get-block-icon'\nimport { isUrl } from './is-url'\n\n/**\n * Gets URLs of all images contained on the given page.\n */\nexport const getPageImageUrls = (\n recordMap: types.ExtendedRecordMap,\n {\n mapImageUrl\n }: {\n mapImageUrl: (url: string, block: types.Block) => string | undefined\n }\n): string[] => {\n const blockIds = Object.keys(recordMap.block)\n const imageUrls: string[] = blockIds\n .flatMap((blockId) => {\n const block = recordMap.block[blockId]?.value\n const images: Array<{ block: types.Block; url: string }> = []\n\n if (block) {\n if (block.type === 'image') {\n const signedUrl = recordMap.signed_urls?.[block.id]\n let source = signedUrl || block.properties?.source?.[0]?.[0]\n if (source?.includes('file.notion.so')) {\n source = block.properties?.source?.[0]?.[0]\n }\n\n if (source) {\n images.push({\n block,\n url: source\n })\n }\n }\n\n if ((block.format as any)?.page_cover) {\n const source = (block.format as any).page_cover\n\n images.push({\n block,\n url: source\n })\n }\n\n if ((block.format as any)?.bookmark_cover) {\n const source = (block.format as any).bookmark_cover\n\n images.push({\n block,\n url: source\n })\n }\n\n if ((block.format as any)?.bookmark_icon) {\n const source = (block.format as any).bookmark_icon\n\n images.push({\n block,\n url: source\n })\n }\n\n const pageIcon = getBlockIcon(block, recordMap)\n if (pageIcon && isUrl(pageIcon)) {\n images.push({\n block,\n url: pageIcon\n })\n }\n }\n\n return images\n })\n .filter(Boolean)\n .map(({ block, url }) => mapImageUrl(url, block))\n .filter(Boolean)\n\n return Array.from(new Set(imageUrls))\n}\n","import { type ExtendedRecordMap } from 'notion-types'\n\nimport { getBlockTitle } from './get-block-title'\n\nexport function getPageTitle(recordMap: ExtendedRecordMap) {\n const rootBlockId = Object.keys(recordMap.block)[0]\n if (!rootBlockId) return null\n\n const pageBlock = recordMap.block[rootBlockId]?.value\n\n if (pageBlock) {\n return getBlockTitle(pageBlock, recordMap)\n }\n\n return null\n}\n","import type * as types from 'notion-types'\n\n/**\n * Gets the URLs of all tweets embedded on a page.\n */\nexport const getPageTweetUrls = (\n recordMap: types.ExtendedRecordMap\n): string[] => {\n const blockIds = Object.keys(recordMap.block)\n const tweetUrls: string[] = blockIds\n .map((blockId) => {\n const block = recordMap.block[blockId]?.value\n\n if (block?.type === 'tweet') {\n const tweetUrl = block.properties?.source?.[0]?.[0]\n\n if (tweetUrl) {\n return tweetUrl\n }\n }\n })\n .filter(Boolean)\n\n return Array.from(new Set(tweetUrls))\n}\n","import type * as types from 'notion-types'\n\nimport { getPageTweetUrls } from './get-page-tweet-urls'\n\n/**\n * Gets the IDs of all tweets embedded on a page.\n */\nexport const getPageTweetIds = (\n recordMap: types.ExtendedRecordMap\n): string[] => {\n const tweetUrls = getPageTweetUrls(recordMap)\n return tweetUrls\n .map((url) => {\n try {\n const u = new URL(url)\n const parts = u.pathname.split('/')\n return parts.at(-1)\n } catch {\n return\n }\n })\n .filter(Boolean)\n}\n","import { type Block } from 'notion-types'\n\nexport const defaultMapImageUrl = (\n url: string | undefined,\n block: Block\n): string | undefined => {\n if (!url) {\n return undefined\n }\n\n if (url.startsWith('data:')) {\n return url\n }\n\n // more recent versions of notion don't proxy unsplash images\n if (url.startsWith('https://images.unsplash.com')) {\n return url\n }\n\n try {\n const u = new URL(url)\n\n if (\n u.pathname.startsWith('/secure.notion-static.com') &&\n u.hostname.endsWith('.amazonaws.com')\n ) {\n if (\n u.searchParams.has('X-Amz-Credential') &&\n u.searchParams.has('X-Amz-Signature') &&\n u.searchParams.has('X-Amz-Algorithm')\n ) {\n // if the URL is already signed, then use it as-is\n return url\n }\n }\n\n if (u.hostname === 'img.notionusercontent.com') {\n return url\n }\n } catch {\n // ignore invalid urls\n }\n\n if (url.startsWith('/images')) {\n url = `https://www.notion.so${url}`\n }\n\n url = `https://www.notion.so${\n url.startsWith('/image') ? url : `/image/${encodeURIComponent(url)}`\n }`\n\n const notionImageUrlV2 = new URL(url)\n let table = block.parent_table === 'space' ? 'block' : block.parent_table\n if (table === 'collection' || table === 'team') {\n table = 'block'\n }\n notionImageUrlV2.searchParams.set('table', table)\n notionImageUrlV2.searchParams.set('id', block.id)\n notionImageUrlV2.searchParams.set('cache', 'v2')\n\n url = notionImageUrlV2.toString()\n\n return url\n}\n","export const defaultMapPageUrl = (rootPageId?: string) => (pageId: string) => {\n pageId = (pageId || '').replaceAll('-', '')\n\n if (rootPageId && pageId === rootPageId) {\n return '/'\n } else {\n return `/${pageId}`\n }\n}\n","import { type ExtendedRecordMap } from 'notion-types'\n\nexport function mergeRecordMaps(\n recordMapA: ExtendedRecordMap,\n recordMapB: ExtendedRecordMap\n): ExtendedRecordMap {\n const mergedRecordMap: ExtendedRecordMap = {\n block: {\n ...recordMapA.block,\n ...recordMapB.block\n },\n collection: {\n ...recordMapA.collection,\n ...recordMapB.collection\n },\n collection_view: {\n ...recordMapA.collection_view,\n ...recordMapB.collection_view\n },\n notion_user: {\n ...recordMapA.notion_user,\n ...recordMapB.notion_user\n },\n collection_query: {\n ...recordMapA.collection_query,\n ...recordMapB.collection_query\n },\n signed_urls: {\n ...recordMapA.signed_urls,\n ...recordMapB.signed_urls\n },\n preview_images: {\n ...recordMapA.preview_images,\n ...recordMapB.preview_images\n }\n }\n\n return mergedRecordMap\n}\n","import memoize from 'memoize'\nimport normalizeUrlImpl from 'normalize-url'\n\nexport const normalizeUrl = memoize((url?: string) => {\n if (!url) {\n return ''\n }\n\n try {\n if (url.startsWith('https://www.notion.so/image/')) {\n const u = new URL(url)\n const subUrl = decodeURIComponent(u.pathname.slice('/image/'.length))\n const normalizedSubUrl = normalizeUrl(subUrl)\n u.pathname = `/image/${encodeURIComponent(normalizedSubUrl)}`\n url = u.toString()\n }\n\n return normalizeUrlImpl(url, {\n stripProtocol: true,\n stripWWW: true,\n stripHash: true,\n stripTextFragment: true,\n removeQueryParameters: true\n })\n } catch {\n return ''\n }\n})\n"],"mappings":"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","names":["collectionId","_a","_a","formatDate","blockId","value","default","default"]} |
+2
-2
| { | ||
| "name": "notion-utils", | ||
| "version": "7.4.3", | ||
| "version": "7.5.0", | ||
| "type": "module", | ||
@@ -30,3 +30,3 @@ "description": "Useful utilities for working with Notion data. Isomorphic.", | ||
| "p-queue": "^8.1.0", | ||
| "notion-types": "7.4.3" | ||
| "notion-types": "7.5.0" | ||
| }, | ||
@@ -33,0 +33,0 @@ "scripts": { |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
87932
0.69%1025
0.49%+ Added
- Removed
Updated