notion-utils
Advanced tools
+4
-2
| import * as types from 'notion-types'; | ||
| import { Block, ExtendedRecordMap, PageMap } from 'notion-types'; | ||
| import { Block, ExtendedRecordMap, PageMap, Collection, CollectionView, User, NotionMapBox } from 'notion-types'; | ||
| export { default as isUrl } from 'is-url-superb'; | ||
@@ -87,2 +87,4 @@ | ||
| declare function getBlockValue<T extends Block | Collection | CollectionView | User>(block: T | NotionMapBox<T> | undefined): T | undefined; | ||
| /** | ||
@@ -184,2 +186,2 @@ * Gets the canonical, display-friendly version of a page's ID for use in URLs. | ||
| export { type NotionDateTime, type TableOfContentsEntry, defaultMapImageUrl, defaultMapPageUrl, estimatePageReadTime, estimatePageReadTimeAsHumanizedString, formatDate, formatNotionDateTime, getAllPagesInSpace, getBlockCollectionId, getBlockIcon, getBlockParentPage, getBlockTitle, getCanonicalPageId, getDateValue, getPageBreadcrumbs, getPageContentBlockIds, getPageImageUrls, getPageProperty, getPageTableOfContents, getPageTitle, getPageTweetIds, getPageTweetUrls, getTextContent, idToUuid, mergeRecordMaps, normalizeTitle, normalizeUrl, parsePageId, uuidToId }; | ||
| export { type NotionDateTime, type TableOfContentsEntry, defaultMapImageUrl, defaultMapPageUrl, estimatePageReadTime, estimatePageReadTimeAsHumanizedString, formatDate, formatNotionDateTime, getAllPagesInSpace, getBlockCollectionId, getBlockIcon, getBlockParentPage, getBlockTitle, getBlockValue, getCanonicalPageId, getDateValue, getPageBreadcrumbs, getPageContentBlockIds, getPageImageUrls, getPageProperty, getPageTableOfContents, getPageTitle, getPageTweetIds, getPageTweetUrls, getTextContent, idToUuid, mergeRecordMaps, normalizeTitle, normalizeUrl, parsePageId, uuidToId }; |
+63
-48
@@ -9,4 +9,20 @@ // src/estimate-page-read-time.ts | ||
| import "notion-types"; | ||
| // src/get-block-value.ts | ||
| function getBlockValue(block) { | ||
| if (!block) { | ||
| return void 0; | ||
| } | ||
| if (block.value) { | ||
| return getBlockValue(block.value); | ||
| } | ||
| if (!block.id) { | ||
| return void 0; | ||
| } | ||
| return block; | ||
| } | ||
| // src/get-block-collection-id.ts | ||
| function getBlockCollectionId(block, recordMap) { | ||
| var _a, _b, _c, _d, _e, _f, _g; | ||
| var _a, _b, _c, _d, _e, _f; | ||
| const collectionId = block.collection_id || ((_b = (_a = block.format) == null ? void 0 : _a.collection_pointer) == null ? void 0 : _b.id); | ||
@@ -18,5 +34,7 @@ if (collectionId) { | ||
| if (collectionViewId) { | ||
| const collectionView = (_e = (_d = recordMap.collection_view) == null ? void 0 : _d[collectionViewId]) == null ? void 0 : _e.value; | ||
| const collectionView = getBlockValue( | ||
| (_d = recordMap.collection_view) == null ? void 0 : _d[collectionViewId] | ||
| ); | ||
| if (collectionView) { | ||
| const collectionId2 = (_g = (_f = collectionView.format) == null ? void 0 : _f.collection_pointer) == null ? void 0 : _g.id; | ||
| const collectionId2 = (_f = (_e = collectionView.format) == null ? void 0 : _e.collection_pointer) == null ? void 0 : _f.id; | ||
| return collectionId2; | ||
@@ -45,3 +63,3 @@ } | ||
| function getBlockTitle(block, recordMap) { | ||
| var _a, _b; | ||
| var _a; | ||
| if ((_a = block.properties) == null ? void 0 : _a.title) { | ||
@@ -53,3 +71,3 @@ return getTextContent(block.properties.title); | ||
| if (collectionId) { | ||
| const collection = (_b = recordMap.collection[collectionId]) == null ? void 0 : _b.value; | ||
| const collection = getBlockValue(recordMap.collection[collectionId]); | ||
| if (collection) { | ||
@@ -72,4 +90,4 @@ return getTextContent(collection.name); | ||
| return (content != null ? content : []).map((blockId) => { | ||
| var _a, _b; | ||
| const block = (_a = recordMap.block[blockId]) == null ? void 0 : _a.value; | ||
| var _a; | ||
| const block = getBlockValue(recordMap.block[blockId]); | ||
| if (block) { | ||
@@ -81,3 +99,3 @@ const { type } = block; | ||
| type, | ||
| text: getTextContent((_b = block.properties) == null ? void 0 : _b.title), | ||
| text: getTextContent((_a = block.properties) == null ? void 0 : _a.title), | ||
| indentLevel: indentLevels[type] | ||
@@ -151,3 +169,3 @@ }; | ||
| function getBlockContentStats(block, recordMap) { | ||
| var _a, _b, _c, _d; | ||
| var _a, _b; | ||
| const stats = { | ||
@@ -161,3 +179,3 @@ numWords: 0, | ||
| for (const childId of block.content || []) { | ||
| const child = (_a = recordMap.block[childId]) == null ? void 0 : _a.value; | ||
| const child = getBlockValue(recordMap.block[childId]); | ||
| let recurse = false; | ||
@@ -252,7 +270,9 @@ if (!child) continue; | ||
| case "transclusion_reference": { | ||
| const referencePointerId = (_c = (_b = child == null ? void 0 : child.format) == null ? void 0 : _b.transclusion_reference_pointer) == null ? void 0 : _c.id; | ||
| const referencePointerId = (_b = (_a = child == null ? void 0 : child.format) == null ? void 0 : _a.transclusion_reference_pointer) == null ? void 0 : _b.id; | ||
| if (!referencePointerId) { | ||
| continue; | ||
| } | ||
| const referenceBlock = (_d = recordMap.block[referencePointerId]) == null ? void 0 : _d.value; | ||
| const referenceBlock = getBlockValue( | ||
| recordMap.block[referencePointerId] | ||
| ); | ||
| if (referenceBlock) { | ||
@@ -357,3 +377,3 @@ mergeContentStats( | ||
| void queue.add(async () => { | ||
| var _a, _b, _c; | ||
| var _a, _b; | ||
| try { | ||
@@ -367,3 +387,3 @@ if (targetPageId && pendingPageIds.has(targetPageId) && pageId !== targetPageId) { | ||
| } | ||
| const spaceId = (_b = (_a = page.block[pageId]) == null ? void 0 : _a.value) == null ? void 0 : _b.space_id; | ||
| const spaceId = (_a = getBlockValue(page.block[pageId])) == null ? void 0 : _a.space_id; | ||
| if (spaceId) { | ||
@@ -377,4 +397,3 @@ if (!rootSpaceId) { | ||
| for (const subPageId of Object.keys(page.block).filter((key) => { | ||
| var _a2; | ||
| const block = (_a2 = page.block[key]) == null ? void 0 : _a2.value; | ||
| const block = getBlockValue(page.block[key]); | ||
| if (!block || block.alive === false) return false; | ||
@@ -398,3 +417,3 @@ if (block.type !== "page" && block.type !== "collection_view_page") { | ||
| /* @__PURE__ */ new Set([ | ||
| ...((_c = collectionData == null ? void 0 : collectionData.collection_group_results) == null ? void 0 : _c.blockIds) || [], | ||
| ...((_b = collectionData == null ? void 0 : collectionData.collection_group_results) == null ? void 0 : _b.blockIds) || [], | ||
| ...collectionData.blockIds || [] | ||
@@ -433,3 +452,3 @@ ]) | ||
| function getBlockIcon(block, recordMap) { | ||
| var _a, _b, _c; | ||
| var _a, _b; | ||
| if ((_a = block.format) == null ? void 0 : _a.page_icon) { | ||
@@ -441,3 +460,3 @@ return (_b = block.format) == null ? void 0 : _b.page_icon; | ||
| if (collectionId) { | ||
| const collection = (_c = recordMap.collection[collectionId]) == null ? void 0 : _c.value; | ||
| const collection = getBlockValue(recordMap.collection[collectionId]); | ||
| if (collection) { | ||
@@ -455,3 +474,2 @@ return collection.icon; | ||
| } = {}) => { | ||
| var _a, _b; | ||
| let currentRecord = block; | ||
@@ -468,5 +486,5 @@ while (currentRecord) { | ||
| if (parentTable === "collection") { | ||
| currentRecord = (_a = recordMap.collection[parentId]) == null ? void 0 : _a.value; | ||
| currentRecord = getBlockValue(recordMap.collection[parentId]); | ||
| } else { | ||
| currentRecord = (_b = recordMap.block[parentId]) == null ? void 0 : _b.value; | ||
| currentRecord = getBlockValue(recordMap.block[parentId]); | ||
| if ((currentRecord == null ? void 0 : currentRecord.type) === "page") { | ||
@@ -486,3 +504,2 @@ return currentRecord; | ||
| function getPageProperty(propertyName, block, recordMap) { | ||
| var _a; | ||
| try { | ||
@@ -492,3 +509,3 @@ if (!block.properties || !Object.keys(recordMap.collection)) { | ||
| } | ||
| const collection = (_a = recordMap.collection[block.parent_id]) == null ? void 0 : _a.value; | ||
| const collection = getBlockValue(recordMap.collection[block.parent_id]); | ||
| if (collection) { | ||
@@ -498,4 +515,4 @@ const propertyNameL = propertyName.toLowerCase(); | ||
| (key) => { | ||
| var _a2, _b; | ||
| return ((_b = (_a2 = collection.schema[key]) == null ? void 0 : _a2.name) == null ? void 0 : _b.toLowerCase()) === propertyNameL; | ||
| var _a, _b; | ||
| return ((_b = (_a = collection.schema[key]) == null ? void 0 : _a.name) == null ? void 0 : _b.toLowerCase()) === propertyNameL; | ||
| } | ||
@@ -563,6 +580,5 @@ ); | ||
| var getCanonicalPageId = (pageId, recordMap, { uuid = true } = {}) => { | ||
| var _a; | ||
| if (!pageId || !recordMap) return null; | ||
| const id = uuidToId(pageId); | ||
| const block = (_a = recordMap.block[pageId]) == null ? void 0 : _a.value; | ||
| const block = getBlockValue(recordMap.block[pageId]); | ||
| if (block) { | ||
@@ -600,3 +616,2 @@ const slug = getPageProperty("slug", block, recordMap) || getPageProperty("Slug", block, recordMap) || normalizeTitle(getBlockTitle(block, recordMap)); | ||
| var getPageBreadcrumbs = (recordMap, activePageId) => { | ||
| var _a; | ||
| const blockMap = recordMap.block; | ||
@@ -606,3 +621,3 @@ const breadcrumbs = []; | ||
| do { | ||
| const block = (_a = blockMap[currentPageId]) == null ? void 0 : _a.value; | ||
| const block = getBlockValue(blockMap[currentPageId]); | ||
| if (!block) { | ||
@@ -639,6 +654,6 @@ break; | ||
| function addContentBlocks(blockId2) { | ||
| var _a, _b, _c, _d, _e, _f; | ||
| var _a, _b, _c, _d, _e; | ||
| if (contentBlockIds.has(blockId2)) return; | ||
| contentBlockIds.add(blockId2); | ||
| const block = (_a = recordMap.block[blockId2]) == null ? void 0 : _a.value; | ||
| const block = getBlockValue(recordMap.block[blockId2]); | ||
| if (!block) return; | ||
@@ -651,3 +666,3 @@ const { content, type, properties, format } = block; | ||
| for (const d of p) { | ||
| const value2 = (_c = (_b = d == null ? void 0 : d[0]) == null ? void 0 : _b[1]) == null ? void 0 : _c[0]; | ||
| const value2 = (_b = (_a = d == null ? void 0 : d[0]) == null ? void 0 : _a[1]) == null ? void 0 : _b[0]; | ||
| if ((value2 == null ? void 0 : value2[0]) === "p" && value2[1]) { | ||
@@ -657,3 +672,3 @@ addContentBlocks(value2[1]); | ||
| } | ||
| const value = (_e = (_d = p == null ? void 0 : p[0]) == null ? void 0 : _d[1]) == null ? void 0 : _e[0]; | ||
| const value = (_d = (_c = p == null ? void 0 : p[0]) == null ? void 0 : _c[1]) == null ? void 0 : _d[0]; | ||
| if ((value == null ? void 0 : value[0]) === "p" && value[1]) { | ||
@@ -665,3 +680,3 @@ addContentBlocks(value[1]); | ||
| if (format) { | ||
| const referenceId = (_f = format.transclusion_reference_pointer) == null ? void 0 : _f.id; | ||
| const referenceId = (_e = format.transclusion_reference_pointer) == null ? void 0 : _e.id; | ||
| if (referenceId) { | ||
@@ -696,11 +711,11 @@ addContentBlocks(referenceId); | ||
| const imageUrls = blockIds.flatMap((blockId) => { | ||
| var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k; | ||
| const block = (_a = recordMap.block[blockId]) == null ? void 0 : _a.value; | ||
| var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; | ||
| const block = getBlockValue(recordMap.block[blockId]); | ||
| const images = []; | ||
| if (block) { | ||
| if (block.type === "image") { | ||
| const signedUrl = (_b = recordMap.signed_urls) == null ? void 0 : _b[block.id]; | ||
| let source = signedUrl || ((_e = (_d = (_c = block.properties) == null ? void 0 : _c.source) == null ? void 0 : _d[0]) == null ? void 0 : _e[0]); | ||
| const signedUrl = (_a = recordMap.signed_urls) == null ? void 0 : _a[block.id]; | ||
| let source = signedUrl || ((_d = (_c = (_b = block.properties) == null ? void 0 : _b.source) == null ? void 0 : _c[0]) == null ? void 0 : _d[0]); | ||
| if (source == null ? void 0 : source.includes("file.notion.so")) { | ||
| source = (_h = (_g = (_f = block.properties) == null ? void 0 : _f.source) == null ? void 0 : _g[0]) == null ? void 0 : _h[0]; | ||
| source = (_g = (_f = (_e = block.properties) == null ? void 0 : _e.source) == null ? void 0 : _f[0]) == null ? void 0 : _g[0]; | ||
| } | ||
@@ -714,3 +729,3 @@ if (source) { | ||
| } | ||
| if ((_i = block.format) == null ? void 0 : _i.page_cover) { | ||
| if ((_h = block.format) == null ? void 0 : _h.page_cover) { | ||
| const source = block.format.page_cover; | ||
@@ -722,3 +737,3 @@ images.push({ | ||
| } | ||
| if ((_j = block.format) == null ? void 0 : _j.bookmark_cover) { | ||
| if ((_i = block.format) == null ? void 0 : _i.bookmark_cover) { | ||
| const source = block.format.bookmark_cover; | ||
@@ -730,3 +745,3 @@ images.push({ | ||
| } | ||
| if ((_k = block.format) == null ? void 0 : _k.bookmark_icon) { | ||
| if ((_j = block.format) == null ? void 0 : _j.bookmark_icon) { | ||
| const source = block.format.bookmark_icon; | ||
@@ -754,6 +769,5 @@ images.push({ | ||
| function getPageTitle(recordMap) { | ||
| var _a; | ||
| const rootBlockId = Object.keys(recordMap.block)[0]; | ||
| if (!rootBlockId) return null; | ||
| const pageBlock = (_a = recordMap.block[rootBlockId]) == null ? void 0 : _a.value; | ||
| const pageBlock = getBlockValue(recordMap.block[rootBlockId]); | ||
| if (pageBlock) { | ||
@@ -769,6 +783,6 @@ return getBlockTitle(pageBlock, recordMap); | ||
| const tweetUrls = blockIds.map((blockId) => { | ||
| var _a, _b, _c, _d; | ||
| const block = (_a = recordMap.block[blockId]) == null ? void 0 : _a.value; | ||
| var _a, _b, _c; | ||
| const block = getBlockValue(recordMap.block[blockId]); | ||
| if ((block == null ? void 0 : block.type) === "tweet") { | ||
| const tweetUrl = (_d = (_c = (_b = block.properties) == null ? void 0 : _b.source) == null ? void 0 : _c[0]) == null ? void 0 : _d[0]; | ||
| const tweetUrl = (_c = (_b = (_a = block.properties) == null ? void 0 : _a.source) == null ? void 0 : _b[0]) == null ? void 0 : _c[0]; | ||
| if (tweetUrl) { | ||
@@ -924,2 +938,3 @@ return tweetUrl; | ||
| getBlockTitle, | ||
| getBlockValue, | ||
| getCanonicalPageId, | ||
@@ -926,0 +941,0 @@ getDateValue, |
@@ -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 (\n type === 'transclusion_container' ||\n type === 'column_list' ||\n type === 'column'\n ) {\n return mapContentToEntries(block.content)\n }\n }\n\n return null\n })\n }\n\n // Helper function to flatten nested results recursively\n function flattenResults(results: MapResult[]): TableOfContentsEntry[] {\n return results.flatMap((r) => {\n if (r == null) return []\n return Array.isArray(r) ? flattenResults(r) : [r]\n })\n }\n\n const toc = flattenResults(mapContentToEntries(page.content))\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.length) {\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\n// eslint-disable-next-line security/detect-unsafe-regex\nconst GIF_REGEXP = /(?:https?:\\/\\/)?[^\\s]+\\.gif(?=$|\\?|#)/\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 if (GIF_REGEXP.test(url)) {\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"]} | ||
| {"version":3,"sources":["../src/estimate-page-read-time.ts","../src/get-block-title.ts","../src/get-block-collection-id.ts","../src/get-block-value.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 { getBlockValue } from './get-block-value'\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 = getBlockValue(recordMap.block[childId])\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 = getBlockValue(\n recordMap.block[referencePointerId]\n )\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 { getBlockValue } from './get-block-value'\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 = getBlockValue(recordMap.collection[collectionId])\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\nimport { getBlockValue } from './get-block-value'\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 = getBlockValue(\n recordMap.collection_view?.[collectionViewId]\n )\n\n if (collectionView) {\n const collectionId = collectionView.format?.collection_pointer?.id\n return collectionId\n }\n }\n\n return null\n}\n","import type {\n Block,\n Collection,\n CollectionView,\n NotionMapBox,\n User\n} from 'notion-types'\n\n// This helper unboxes a block value in a generic way which became necessary\n// after Notion changed their API for some blocks to be doubly-nested.\n// https://github.com/NotionX/react-notion-x/issues/682\n\nexport function getBlockValue<\n T extends Block | Collection | CollectionView | User\n>(block: T | NotionMapBox<T> | undefined): T | undefined {\n if (!block) {\n return undefined\n }\n\n if ((block as any).value) {\n return getBlockValue((block as any).value)\n }\n\n if (!(block as any).id) {\n return undefined\n }\n\n return block as any as T\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 { getBlockValue } from './get-block-value'\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 = getBlockValue(recordMap.block[blockId])\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 (\n type === 'transclusion_container' ||\n type === 'column_list' ||\n type === 'column'\n ) {\n return mapContentToEntries(block.content)\n }\n }\n\n return null\n })\n }\n\n // Helper function to flatten nested results recursively\n function flattenResults(results: MapResult[]): TableOfContentsEntry[] {\n return results.flatMap((r) => {\n if (r == null) return []\n return Array.isArray(r) ? flattenResults(r) : [r]\n })\n }\n\n const toc = flattenResults(mapContentToEntries(page.content))\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 { getBlockValue } from './get-block-value'\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 = getBlockValue(page.block[pageId])?.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 = getBlockValue(page.block[key])\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.length) {\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'\nimport { getBlockValue } from './get-block-value'\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 = getBlockValue(recordMap.collection[collectionId])\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\nimport { getBlockValue } from './get-block-value'\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 = getBlockValue(recordMap.collection[parentId])\n } else {\n currentRecord = getBlockValue(recordMap.block[parentId])\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 { getBlockValue } from './get-block-value'\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 = getBlockValue(recordMap.block[pageId])\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 { getBlockValue } from './get-block-value'\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 = getBlockValue(recordMap.collection[block.parent_id])\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'\nimport { getBlockValue } from './get-block-value'\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 = getBlockValue(blockMap[currentPageId])\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\nimport { getBlockValue } from './get-block-value'\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 = getBlockValue(recordMap.block[blockId])\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 { getBlockValue } from './get-block-value'\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 = getBlockValue(recordMap.block[blockId])\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'\nimport { getBlockValue } from './get-block-value'\n\nexport function getPageTitle(recordMap: ExtendedRecordMap) {\n const rootBlockId = Object.keys(recordMap.block)[0]\n if (!rootBlockId) return null\n\n const pageBlock = getBlockValue(recordMap.block[rootBlockId])\n\n if (pageBlock) {\n return getBlockTitle(pageBlock, recordMap)\n }\n\n return null\n}\n","import type * as types from 'notion-types'\n\nimport { getBlockValue } from './get-block-value'\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 = getBlockValue(recordMap.block[blockId])\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\n// eslint-disable-next-line security/detect-unsafe-regex\nconst GIF_REGEXP = /(?:https?:\\/\\/)?[^\\s]+\\.gif(?=$|\\?|#)/\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 if (GIF_REGEXP.test(url)) {\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","formatDate","blockId","value","default","default"]} |
+2
-2
| { | ||
| "name": "notion-utils", | ||
| "version": "7.7.3", | ||
| "version": "7.8.0", | ||
| "type": "module", | ||
@@ -30,3 +30,3 @@ "description": "Useful utilities for working with Notion data. Isomorphic.", | ||
| "p-queue": "^8.1.0", | ||
| "notion-types": "7.7.3" | ||
| "notion-types": "7.8.0" | ||
| }, | ||
@@ -33,0 +33,0 @@ "scripts": { |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
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
90666
1.94%1049
1.35%+ Added
- Removed
Updated