@texonom/nutils 1.4.7 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/get-text-content.ts","../src/get-block-collection-id.ts","../src/get-block-title.ts","../src/get-block-icon.ts","../src/get-page-title.ts","../src/get-page-property.ts","../src/get-date-value.ts","../src/get-block-parent-page.ts","../src/get-page-table-of-contents.ts","../src/get-page-content-block-ids.ts","../src/id-to-uuid.ts","../src/parse-page-id.ts","../src/uuid-to-id.ts","../src/find-ancestors.ts","../src/get-all-in-space.ts","../src/normalize-title.ts","../src/get-canonical-page-id.ts","../src/get-page-breadcrumbs.ts","../src/is-url.ts","../src/get-page-image-urls.ts","../src/normalize-url.ts","../src/merge-record-maps.ts","../src/format-date.ts","../src/format-notion-date-time.ts","../src/estimate-page-read-time.ts","../src/map-image-url.ts","../src/map-page-url.ts"],"sourcesContent":["import type { Decoration } from '@texonom/ntypes'\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?: Decoration[]): string => {\n if (!text) return ''\n else if (Array.isArray(text))\n return text?.reduce((prev, current) => prev + (current[0] !== '⁍' && current[0] !== '‣' ? current[0] : ''), '') ?? ''\n else return text\n}\n","import type { Block, CollectionViewBlock, ExtendedRecordMap } from '@texonom/ntypes'\n\nexport function getBlockCollectionId(block: Block, recordMap: ExtendedRecordMap): string | null {\n const collectionId =\n (block as CollectionViewBlock).collection_id || (block as CollectionViewBlock).format?.collection_pointer?.id\n\n if (collectionId) return collectionId\n\n const collectionViewId = (block as CollectionViewBlock)?.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 { getBlockCollectionId } from './get-block-collection-id'\nimport { getTextContent } from './get-text-content'\n\nimport type { Block, ExtendedRecordMap } from '@texonom/ntypes'\n\nexport function getBlockTitle(block: Block, recordMap: ExtendedRecordMap) {\n if (block.properties?.title) return getTextContent(block.properties.title)\n\n if (block.type === 'collection_view_page' || block.type === 'collection_view') {\n const collectionId = getBlockCollectionId(block, recordMap)\n if (collectionId) {\n const collection = recordMap.collection[collectionId]?.value\n if (collection) return getTextContent(collection.name)\n }\n }\n return ''\n}\n","import { getBlockCollectionId } from './get-block-collection-id'\n\nimport type { Block, ExtendedRecordMap, PageBlock } from '@texonom/ntypes'\n\nexport function getBlockIcon(block: Block, recordMap: ExtendedRecordMap) {\n if ((block as PageBlock).format?.page_icon) return (block as PageBlock).format?.page_icon\n\n if (block.type === 'collection_view_page' || block.type === 'collection_view') {\n const collectionId = getBlockCollectionId(block, recordMap)\n if (collectionId) {\n const collection = recordMap.collection[collectionId]?.value\n\n if (collection) return collection.icon\n }\n }\n\n return null\n}\n","import type { ExtendedRecordMap } from '@texonom/ntypes'\n\nimport { getBlockTitle } from './get-block-title'\n\nexport function getPageTitle(recordMap: ExtendedRecordMap) {\n const pageBlock = recordMap.block[Object.keys(recordMap.block)[0]]?.value\n\n if (pageBlock) return getBlockTitle(pageBlock, recordMap)\n\n return null\n}\n","import { Block, DateFormat, ExtendedRecordMap } from '@texonom/ntypes'\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<T = string | number | boolean | string[] | number[]>(\n propertyName: string,\n block: Block,\n recordMap: ExtendedRecordMap\n): T\nexport function getPageProperty(propertyName: string, block: Block, recordMap: ExtendedRecordMap) {\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 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) return null\n\n const { type } = collection.schema[propertyId]\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(`${formatDate.start_date} ${formatDate.start_time}`).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","import type { FormattedDate } from '@texonom/ntypes'\n\n/**\n * Attempts to find a valid date from a given property.\n */\nexport const getDateValue = (prop: any[]): FormattedDate | null => {\n if (prop && Array.isArray(prop))\n if (prop[0] === 'd') return prop[1]\n else\n for (const v of prop) {\n const value = getDateValue(v)\n if (value) return value\n }\n\n return null\n}\n","import type { Block, ExtendedRecordMap, PageBlock, Collection, Space } from '@texonom/ntypes'\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: Block,\n recordMap: ExtendedRecordMap,\n {\n inclusive = false\n }: {\n inclusive?: boolean\n } = {}\n): PageBlock | null => {\n let currentRecord: Block | Collection = block\n\n while (currentRecord != null) {\n if (inclusive && (currentRecord as Block)?.type === 'page') return currentRecord as PageBlock\n\n const parentId: string = currentRecord.parent_id\n const parentTable = currentRecord.parent_table\n\n if (!parentId) break\n\n if (parentTable === 'collection') {\n currentRecord = recordMap.collection[parentId]?.value\n } else {\n currentRecord = recordMap.block[parentId]?.value\n if ((currentRecord as Block)?.type === 'page') return currentRecord as PageBlock\n }\n }\n return null\n}\n\nexport const getBlockParent = (\n block: Block,\n recordMap: ExtendedRecordMap,\n {\n inclusive = false\n }: {\n inclusive?: boolean\n } = {}\n): PageBlock | Collection | Space => {\n let currentRecord: Block | Collection | Space = block\n\n while (currentRecord != null) {\n if (inclusive && (currentRecord as Block)?.type === 'page') return currentRecord as PageBlock\n\n const parentId: string = currentRecord.parent_id\n const parentTable = currentRecord.parent_table\n\n if (!parentId) break\n\n if (parentTable === 'collection') {\n return recordMap.collection[parentId]?.value\n } else if (parentTable === 'space') {\n return recordMap.space?.[parentId]?.value\n } else {\n currentRecord = recordMap.block[parentId]?.value\n if ((currentRecord as Block)?.type === 'page') return currentRecord as PageBlock\n }\n }\n return null\n}\n","import { getTextContent } from './get-text-content'\n\nimport type { ID, BlockType, PageBlock, ExtendedRecordMap } from '@texonom/ntypes'\n\nexport interface TableOfContentsEntry {\n id: ID\n type: 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 = (page: PageBlock, recordMap: ExtendedRecordMap): Array<TableOfContentsEntry> => {\n const toc = (page.content ?? [])\n .map((blockId: string) => {\n const block = recordMap.block[blockId]?.value\n\n if (block) {\n const { type } = block\n\n if (type === 'header' || type === 'sub_header' || type === 'sub_sub_header')\n return {\n id: blockId,\n type,\n text: getTextContent(block.properties?.title),\n indentLevel: indentLevels[type]\n }\n }\n\n return null\n })\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[indentLevelStack.length - 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\n // eslint-disable-next-line no-constant-condition\n } while (true)\n }\n\n return toc\n}\n","import type { ExtendedRecordMap, Decoration } from '@texonom/ntypes'\n\n/**\n * Gets the IDs of all blocks contained on a page starting from a root block ID.\n */\nexport const getPageContentBlockIds = (recordMap: ExtendedRecordMap, blockId?: string, locust = false): 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 const { content, type, properties, format } = block\n if (properties)\n for (const key of Object.keys(properties)) {\n const p = properties[key]\n p.map((d: Decoration) => {\n const value = d?.[0]?.[1]?.[0]\n if (value?.[0] === 'p' && value[1]) addContentBlocks(value[1])\n })\n p.map((d: Decoration) => {\n const value = d?.[1]?.[0]\n if ((value?.[0] === 'p' || value?.[0] === 'eoi') && value[1]) addContentBlocks(value[1])\n })\n }\n\n if (format) {\n const referenceId = format.transclusion_reference_pointer?.id\n if (referenceId) addContentBlocks(referenceId)\n }\n // no child content blocks to recurse on\n if (!content || !Array.isArray(content)) return\n // ignore the content of other pages and collections\n if (blockId !== rootBlockId && !locust) if (type === 'page' || type === 'collection_view_page') return\n for (const blockId of content) addContentBlocks(blockId)\n }\n addContentBlocks(rootBlockId)\n return Array.from(contentBlockIds)\n}\n\n/**\n * Gets the IDs of all blocks contained on a page starting from a root block ID.\n */\nexport const getPageContentUserIds = (recordMap: ExtendedRecordMap, blockId?: string): string[] => {\n const rootBlockId = blockId || Object.keys(recordMap.block)[0]\n const contentUserIDs = new Set<string>()\n const block = recordMap.block[rootBlockId]?.value\n\n if (block?.created_by_id) contentUserIDs.add(block?.created_by_id)\n if (block?.last_edited_by_id) contentUserIDs.add(block?.last_edited_by_id)\n\n // Property\n const { properties } = block\n if (properties)\n for (const key of Object.keys(properties)) {\n const p = properties[key]\n p.map((d: Decoration) => {\n const value = d?.[1]?.[0]\n if (value?.[0] === 'u' && value[1]) contentUserIDs.add(value[1])\n })\n }\n\n return Array.from(contentUserIDs)\n}\n","export const idToUuid = (id = '') =>\n `${id.substr(0, 8)}-${id.substr(8, 4)}-${id.substr(12, 4)}-${id.substr(16, 4)}-${id.substr(20)}`\n","import { idToUuid } from './id-to-uuid'\n\nconst pageIdRe = /\\b([a-f0-9]{32})\\b/\nconst pageId2Re = /\\b([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{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 = (id: string | null = '', { uuid = true }: { uuid?: boolean } = {}) => {\n if (!id) return null\n\n id = id.split('?')[0]\n const match = id.match(pageIdRe)\n\n if (match) return uuid ? idToUuid(match[1]) : match[1]\n\n const match2 = id.match(pageId2Re)\n if (match2) return uuid ? match2[1] : match2[1].replace(/-/g, '')\n\n return null\n}\n","export const uuidToId = (uuid: string) => uuid.replace(/-/g, '')\n","import type { ExtendedRecordMap, Block, Collection } from '@texonom/ntypes'\n\nexport function findAncestors(recordMap: ExtendedRecordMap, block: Block | Collection, list: string[] = []): string[] {\n if (block.parent_id) {\n list.push(block.parent_id)\n const table = block.parent_table as 'block' | 'collection'\n if (recordMap[table]?.[block.parent_id]?.value)\n return findAncestors(recordMap, recordMap[table][block.parent_id].value, list)\n }\n return list\n}\n","import { findAncestors } from './find-ancestors'\nimport { getPageContentBlockIds } from './get-page-content-block-ids'\nimport { getBlockTitle } from './get-block-title'\n\nimport type { ExtendedRecordMap, PageMap, PageChunk, BlockMap } from '@texonom/ntypes'\n\nexport type PageTree = {\n id: string\n type: string\n title: string\n blocks: number\n pages: number\n parent?: PageTree\n children: PageTree[]\n}\n\ntype FetchOption = RequestInit & { timeout?: number }\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 *\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 getAllInSpace(\n startPageId: string,\n getPage: (pageId: string, { fetchOption }?: { fetchOption?: FetchOption }) => Promise<ExtendedRecordMap>,\n getBlocks: (blockIds: string[], fetchOption?: FetchOption) => Promise<PageChunk>,\n fetchCollections: (\n contentBlockIds: string[],\n recordMap: ExtendedRecordMap,\n pageId?: string,\n {\n fetchOption,\n concurrency,\n collectionConcurrency\n }?: { fetchOption?: FetchOption; concurrency: number; collectionConcurrency?: number }\n ) => Promise<ExtendedRecordMap>,\n {\n startRecordMap,\n fetchOption = { timeout: 100000 },\n maxPage,\n debug,\n concurrency = 100,\n collectionConcurrency = 100\n }: {\n startRecordMap?: ExtendedRecordMap\n fetchOption?: FetchOption\n concurrency?: number\n maxPage?: number\n debug?: boolean\n collectionConcurrency?: number\n } = {}\n): Promise<{ recordMap: ExtendedRecordMap; pageMap: PageMap; pageTree: PageTree }> {\n const pageMap: PageMap = {}\n const recordMap = startRecordMap ? startRecordMap : await getPage(startPageId, { fetchOption })\n\n let tempRecordMap: ExtendedRecordMap = JSON.parse(JSON.stringify(recordMap))\n\n if (debug) console.time('Total fetch time')\n let iteration = 1\n while (true) {\n if (debug) console.debug(`Iteration ${iteration}`)\n if (debug) console.debug('block length ', Object.keys(recordMap.block).length)\n\n if (debug) console.time('getPageContentBlockIds')\n const targetBlocks = Object.keys(tempRecordMap.block)\n const missing = Object.keys(\n targetBlocks.reduce((blockMap, root) => {\n const contentBlockIds = getPageContentBlockIds(recordMap, root, true)\n for (const contentBlockID of contentBlockIds) if (!recordMap.block[contentBlockID]) blockMap[contentBlockID] = true\n return blockMap\n }, {})\n )\n for (const { value: block } of Object.values(tempRecordMap.block))\n if (block && !recordMap.block[block.parent_id] && block.parent_table === 'block') missing.push(block.parent_id)\n if (debug) console.timeEnd('getPageContentBlockIds')\n\n if (debug) console.time('getBlocks')\n tempRecordMap = (await getBlocks(missing, fetchOption)).recordMap as ExtendedRecordMap\n if (debug) console.timeEnd('getBlocks')\n if (!tempRecordMap?.block) break\n\n if (debug) console.time('mapBlocks')\n const contentBlockIds = Object.values(recordMap.block)\n .map(obj => obj.value?.id)\n .filter(Boolean)\n recordMap.block = { ...recordMap.block, ...tempRecordMap.block }\n if (debug) console.timeEnd('mapBlocks')\n\n if (debug) console.time('fetchCollections')\n await fetchCollections(contentBlockIds, recordMap, undefined, { fetchOption, concurrency, collectionConcurrency })\n if (debug) console.timeEnd('fetchCollections')\n if (debug) console.debug('collection query length ' + Object.keys(recordMap.collection_query).length)\n\n if (debug) console.debug('new block length ', Object.keys(tempRecordMap.block).length)\n const pageLength = Object.values(recordMap.block)\n .map(obj => obj.value?.type)\n .filter(type => type === 'page').length\n if (debug) console.debug('page length ', pageLength)\n if (Number.isInteger(maxPage) && pageLength >= maxPage) break\n\n if (debug) console.debug(`memory usage ${process.memoryUsage().rss / 1024 / 1024}MB`)\n iteration += 1\n if (debug) console.debug()\n }\n if (debug) console.timeEnd('Total fetch time')\n\n if (debug) console.time('get page map')\n if (debug) console.debug('Total block length ', Object.keys(recordMap.block).length)\n const blockIds = Object.keys(recordMap.block)\n\n const promises = []\n for (const blockId of blockIds)\n if (recordMap.block[blockId].value?.type === 'page') {\n promises.push(getPageSync(blockId, recordMap, getBlocks).then(pageRecordMap => (pageMap[blockId] = pageRecordMap)))\n await sleep(1)\n }\n await Promise.all(promises)\n\n if (debug) console.timeEnd('get page map')\n if (debug) console.debug('Total page length ', Object.keys(pageMap).length)\n\n if (debug) console.time('get page tree')\n const pageTree = {\n id: startPageId,\n title: getBlockTitle(recordMap.block[startPageId].value, recordMap),\n blocks: 1,\n pages: 1,\n children: [],\n type: 'page'\n }\n recursivePageTree(recordMap, pageTree)\n if (debug) console.timeEnd('get page tree')\n\n return { pageMap, pageTree, recordMap }\n}\n\nexport function recursivePageTree(recordMap: ExtendedRecordMap, pageTree: PageTree): PageTree {\n // Save ancestors to update the count\n const ancestors = [pageTree]\n let ancestor = pageTree\n while (true)\n if (ancestor.parent) {\n ancestors.push(ancestor.parent)\n ancestor = ancestor.parent\n } else {\n break\n }\n\n const current = recordMap.block[pageTree.id]?.value\n if (!current) {\n console.warn(`No block value for ${pageTree.id}`)\n delete pageTree.parent\n return pageTree\n }\n\n if (current.content?.length) {\n for (const ancestor of ancestors) ancestor.blocks += current.content.length\n for (const contentBlockId of current.content) {\n const block = recordMap.block[contentBlockId]?.value\n if (!block) continue\n pageTree.children.push(\n recursivePageTree(recordMap, {\n id: contentBlockId,\n title: getBlockTitle(block, recordMap),\n blocks: 1,\n pages: 0,\n children: [],\n type: block.type,\n parent: pageTree\n })\n )\n if (block.type === 'page') for (const ancestor of ancestors) ancestor.pages++\n }\n } else if (current?.type === 'collection_view') {\n const collectionQuery = recordMap.collection_query[current.collection_id]?.[current.view_ids[0]]\n if (!collectionQuery) {\n console.warn(`No collection query for ${pageTree.id}`)\n delete pageTree.parent\n return pageTree\n }\n const childrenMap = {}\n for (const collectionQuery of Object.values(recordMap.collection_query[current.collection_id]))\n if (collectionQuery.collection_group_results.blockIds)\n for (const blockId of collectionQuery.collection_group_results.blockIds) childrenMap[blockId] = true\n const childrenPages = Object.keys(childrenMap)\n for (const ancestor of ancestors) ancestor.pages += childrenPages.length\n for (const ancestor of ancestors) ancestor.blocks += childrenPages.length\n for (const blockId of childrenPages)\n pageTree.children.push(\n recursivePageTree(recordMap, {\n id: blockId,\n title: getBlockTitle(recordMap.block[blockId].value, recordMap),\n blocks: childrenPages.length,\n pages: childrenPages.length,\n children: [],\n type: current.type,\n parent: pageTree\n })\n )\n }\n delete pageTree.parent\n return pageTree\n}\n\nexport async function getPageSync(\n pageId: string,\n recordMap: ExtendedRecordMap,\n getBlocks: (blockIds: string[], fetchOption?: FetchOption) => Promise<PageChunk>\n): Promise<ExtendedRecordMap> {\n let contentBlockIds = getPageContentBlockIds(recordMap, pageId)\n let blockMap: BlockMap = { [pageId]: { value: recordMap.block[pageId].value, role: 'reader' } }\n const collectionMap = {}\n const collectionViewMap = {}\n const collectionQueryMap = {}\n\n const missing = []\n for (const contentBlockId of contentBlockIds) {\n const block = recordMap.block[contentBlockId]?.value\n if (!block) {\n missing.push(contentBlockId)\n continue\n }\n blockMap[contentBlockId] = { value: block, role: 'reader' }\n if (block.type === 'collection_view' || block.type === 'collection_view_page') {\n if (recordMap.collection[block.collection_id])\n collectionMap[block.collection_id] = recordMap.collection[block.collection_id]\n if (recordMap.collection_query[block.collection_id])\n collectionQueryMap[block.collection_id] = recordMap.collection_query[block.collection_id]\n for (const viewId of block.view_ids)\n if (recordMap.collection_view[viewId]) {\n collectionViewMap[viewId] = recordMap.collection_view[viewId]\n const blockIds = recordMap.collection_query[block?.collection_id]?.[viewId]?.collection_group_results?.blockIds\n if (blockIds?.length)\n for (const blockId of blockIds) {\n const block = recordMap.block[blockId]?.value\n if (block) blockMap[blockId] = { value: block, role: 'reader' }\n else missing.push(blockId)\n }\n }\n }\n }\n\n // Ancestor\n const ancesters = findAncestors(recordMap, recordMap.block[pageId].value)\n for (const ancester of ancesters) {\n const block = recordMap.block[ancester]?.value\n if (block) blockMap[ancester] = { value: block, role: 'reader' }\n const collection = recordMap.collection[ancester]?.value\n if (collection) collectionMap[ancester] = { value: collection }\n }\n\n // Alias\n for (const blockId of Object.keys(blockMap)) {\n const block = blockMap[blockId].value\n let targetBlock = block\n if (block?.type === 'alias')\n while (true) {\n const alias = targetBlock?.format?.alias_pointer?.id\n if (!alias) break\n targetBlock = recordMap.block[alias]?.value\n if (!targetBlock) missing.push(alias)\n else blockMap[alias] = { value: targetBlock, role: 'reader' }\n }\n }\n\n // Missing\n if (missing.length) {\n const responseMap = (await getBlocks(missing).catch(() => ({ recordMap: { block: null } }))).recordMap\n if (responseMap?.block) {\n blockMap = { ...blockMap, ...responseMap.block }\n for (const blockId in responseMap.block) recordMap.block[blockId] = responseMap.block[blockId]\n } else {\n console.warn(`fetching ${missing.length} fail for ${pageId}`)\n }\n }\n\n contentBlockIds = getPageContentBlockIds(recordMap, pageId)\n for (const contentBlockId of contentBlockIds) {\n const block = recordMap.block[contentBlockId]?.value\n if (!block) continue\n blockMap[contentBlockId] = { value: block, role: 'reader' }\n if (block.type === 'collection_view' || block.type === 'collection_view_page') {\n if (recordMap.collection[block.collection_id])\n collectionMap[block.collection_id] = recordMap.collection[block.collection_id]\n if (recordMap.collection_query[block.collection_id])\n collectionQueryMap[block.collection_id] = recordMap.collection_query[block.collection_id]\n for (const viewId of block.view_ids)\n if (recordMap.collection_view[viewId]) {\n collectionViewMap[viewId] = recordMap.collection_view[viewId]\n const blockIds = recordMap.collection_query[block?.collection_id]?.[viewId]?.collection_group_results?.blockIds\n if (blockIds?.length)\n for (const blockId of blockIds) {\n const block = recordMap.block[blockId]?.value\n if (block) blockMap[blockId] = { value: block, role: 'reader' }\n }\n }\n }\n }\n\n return {\n block: blockMap,\n collection: collectionMap,\n collection_view: collectionViewMap,\n collection_query: collectionQueryMap,\n signed_urls: {},\n notion_user: {}\n }\n}\n\nconst sleep = async (ms: number) => new Promise(resolve => setTimeout(resolve, ms))\n","export const normalizeTitle = (title?: string | null): string => {\n return (title || '')\n .replace(/( |\\/)/g, '-') // Replace spaces and slashes with dashes\n .replace(/[^a-zA-Z0-9-\\u4e00-\\u9FFF\\uAC00-\\uD7AF\\u3130-\\u318F\\u3041-\\u3096\\u30A1-\\u30FC\\u3000-\\u303F]/g, '') // Retain Korean characters\n .replace(/--+/g, '-') // Replace multiple dashes with a single dash\n .replace(/^-+|-+$/g, '') // Trim leading and trailing dashes\n .trim()\n .toLowerCase()\n}\n","import { getBlockTitle } from './get-block-title'\nimport { getPageProperty } from './get-page-property'\nimport { normalizeTitle } from './normalize-title'\nimport { getTextContent } from './get-text-content'\nimport { uuidToId } from './uuid-to-id'\n\nimport type { ExtendedRecordMap } from '@texonom/ntypes'\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) || normalizeTitle(getBlockTitle(block, recordMap))\n\n if (slug)\n if (uuid) return `${slug}-${id}`\n else return slug\n } else {\n const collection = recordMap.collection[pageId]?.value\n if (collection) {\n const slug = normalizeTitle(getTextContent(collection.name))\n if (slug)\n if (uuid) return `${slug}-${id}`\n else return slug\n }\n }\n\n return id\n}\n","import { getBlockIcon } from './get-block-icon'\nimport { getBlockParentPage } from './get-block-parent-page'\nimport { getBlockTitle } from './get-block-title'\n\nimport type { ExtendedRecordMap } from '@texonom/ntypes'\n\nexport const getPageBreadcrumbs = (recordMap: ExtendedRecordMap, activePageId: string): 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) break\n\n const title = getBlockTitle(block, recordMap)\n const icon = getBlockIcon(block, recordMap)\n\n if (!(title || icon)) break\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) break\n\n currentPageId = parentId\n\n // eslint-disable-next-line no-constant-condition\n } while (true)\n\n breadcrumbs.reverse()\n\n return breadcrumbs\n}\n","import isUrl from 'is-url-superb'\n\nexport { isUrl }\n","import { getBlockIcon } from './get-block-icon'\nimport { isUrl } from './is-url'\n\nimport type { Block, ExtendedRecordMap } from '@texonom/ntypes'\n\n/**\n * Gets URLs of all images contained on the given page.\n */\nexport const getPageImageUrls = (\n recordMap: ExtendedRecordMap,\n {\n mapImageUrl\n }: {\n mapImageUrl: (url: string, block: Block) => string | null\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: 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')) source = block.properties?.source?.[0]?.[0]\n\n if (source)\n images.push({\n block,\n url: source\n })\n }\n\n if (block.format?.page_cover) {\n const source = block.format.page_cover\n\n images.push({\n block,\n url: source\n })\n }\n\n if (block.format?.bookmark_cover) {\n const source = block.format.bookmark_cover\n\n images.push({\n block,\n url: source\n })\n }\n\n if (block.format?.bookmark_icon) {\n const source = block.format.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 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 mem from 'mem'\nimport normalizeUrlImpl from 'normalize-url'\n\nexport const normalizeUrl = mem((url?: string) => {\n if (!url) return ''\n\n try {\n if (url.startsWith('https://www.notion.so/image/')) {\n const u = new URL(url)\n const subUrl = decodeURIComponent(u.pathname.substring('/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 (err) {\n return ''\n }\n})\n","import type { ExtendedRecordMap } from '@texonom/ntypes'\n\nexport function mergeRecordMaps(recordMapA: ExtendedRecordMap, recordMapB: ExtendedRecordMap): 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","export const formatDate = (input: string | number, { month = 'short' }: { month?: 'long' | 'short' } = {}) => {\n const date = new Date(input)\n const monthLocale = date.toLocaleString('en-US', { month })\n return `${date.getUTCFullYear()} ${monthLocale} ${date.getUTCDate()} ${date.getUTCHours()}:${date.getUTCMinutes()}`\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 const dateString = `${datetime.start_time || ''} ${datetime.start_date} ${datetime.time_zone || ''}`\n return formatDate(dateString)\n}\n","import { Block, ExtendedRecordMap, PageBlock } from '@texonom/ntypes'\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 { wordsPerMinute = 275, imageReadTimeInSeconds = 12 }: 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) + (stats.numImages - 10) * 3 // n/2(a+b) + 3 sec/image\n : (stats.numImages / 2) * (2 * imageReadTimeInSeconds + (1 - stats.numImages)) // n/2[2a+(n-1)d]\n const totalImageReadTimeInMinutes = totalImageReadTimeInSeconds / 60\n\n const totalReadTimeInMinutes = 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(block: Block, recordMap: ExtendedRecordMap): ContentStats {\n const stats: ContentStats = {\n numWords: 0,\n numImages: 0\n }\n\n if (!block) return stats\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) stats.numWords += countWordsInText(tocItem.text)\n\n break\n }\n\n case 'transclusion_reference': {\n const referencePointerId = child?.format?.transclusion_reference_pointer?.id\n\n if (!referencePointerId) continue\n\n const referenceBlock = recordMap.block[referencePointerId]?.value\n if (referenceBlock) mergeContentStats(stats, getBlockContentStats(referenceBlock, recordMap))\n\n break\n }\n\n default:\n // ignore unrecognized blocks\n break\n }\n\n if (recurse) mergeContentStats(stats, getBlockContentStats(child, recordMap))\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) return 0\n\n return (text.match(/\\w+/g) || []).length\n}\n\nfunction humanizeReadTime(time: number): string {\n if (time < 0.5) return 'less than a minute'\n\n if (time < 1.5) return '1 minute'\n\n return `${Math.ceil(time)} minutes`\n}\n","import { Block } from '@texonom/ntypes'\n\nexport const defaultMapImageUrl = (url: string, block: Block): string | null => {\n if (!url) return null\n\n if (url.startsWith('data:')) return url\n\n // more recent versions of notion don't proxy unsplash images\n if (url.startsWith('https://images.unsplash.com')) return url\n\n try {\n const u = new URL(url)\n\n if (u.pathname.startsWith('/secure.notion-static.com') && u.hostname.endsWith('.amazonaws.com'))\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 } catch {\n // ignore invalid urls\n }\n\n if (url.startsWith('/images')) url = `https://www.notion.so${url}`\n\n url = `https://www.notion.so${url.startsWith('/image') ? url : `/image/${encodeURIComponent(url)}`}`\n\n const notionImageUrlV2 = new URL(url)\n let table = block.parent_table === 'space' ? 'block' : block.parent_table\n if (table === 'collection' || table === 'team') 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 || '').replace(/-/g, '')\n\n if (rootPageId && pageId === rootPageId) return '/'\n else return `/${pageId}`\n}\n"],"mappings":"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","names":["getTextContent","text","_a","prev","current","getBlockCollectionId","block","recordMap","_a","_b","_c","_d","_e","_f","_g","collectionId","collectionViewId","collectionView","getBlockTitle","block","recordMap","_a","_b","getTextContent","collectionId","getBlockCollectionId","collection","getBlockIcon","block","recordMap","_a","_b","_c","collectionId","getBlockCollectionId","collection","getPageTitle","recordMap","_a","pageBlock","getBlockTitle","getPageProperty","propertyName","block","recordMap","_a","collection","propertyNameL","propertyId","key","_b","type","content","getTextContent","formatDate","start_date","start_time","end_date","end_time","startTime","endTime","e","getDateValue","prop","v","value","getBlockParentPage","block","recordMap","inclusive","_a","_b","currentRecord","parentId","parentTable","getBlockParent","_c","_d","indentLevels","getPageTableOfContents","page","recordMap","_a","toc","blockId","_b","block","type","getTextContent","indentLevelStack","tocItem","indentLevel","actual","prevIndent","prevActual","prevEffective","getPageContentBlockIds","recordMap","blockId","locust","rootBlockId","contentBlockIds","addContentBlocks","_a","_b","block","content","type","properties","format","key","d","value","referenceId","getPageContentUserIds","contentUserIDs","idToUuid","id","pageIdRe","pageId2Re","parsePageId","id","uuid","match","idToUuid","match2","uuidToId","uuid","findAncestors","recordMap","block","list","_a","_b","table","getAllInSpace","_0","_1","_2","_3","__async","startPageId","getPage","getBlocks","fetchCollections","startRecordMap","fetchOption","maxPage","debug","concurrency","collectionConcurrency","_a","pageMap","recordMap","tempRecordMap","iteration","targetBlocks","missing","blockMap","root","contentBlockIds","getPageContentBlockIds","contentBlockID","block","obj","__spreadValues","pageLength","type","blockIds","promises","blockId","getPageSync","pageRecordMap","sleep","pageTree","getBlockTitle","recursivePageTree","_b","_c","_d","ancestors","ancestor","current","contentBlockId","childrenMap","collectionQuery","childrenPages","pageId","_e","_f","_g","_h","_i","_j","_k","_l","_m","_n","_o","collectionMap","collectionViewMap","collectionQueryMap","viewId","ancesters","findAncestors","ancester","collection","targetBlock","alias","responseMap","ms","resolve","normalizeTitle","title","getCanonicalPageId","pageId","recordMap","uuid","_a","_b","id","uuidToId","block","slug","getPageProperty","normalizeTitle","getBlockTitle","collection","getTextContent","getPageBreadcrumbs","recordMap","activePageId","_a","blockMap","breadcrumbs","currentPageId","block","title","getBlockTitle","icon","getBlockIcon","parentBlock","getBlockParentPage","parentId","isUrl","getPageImageUrls","recordMap","mapImageUrl","imageUrls","blockId","_a","_b","_c","_d","_e","_f","_g","_h","_i","_j","_k","block","images","source","pageIcon","getBlockIcon","isUrl","url","mem","normalizeUrlImpl","normalizeUrl","url","u","subUrl","normalizedSubUrl","err","mergeRecordMaps","recordMapA","recordMapB","__spreadValues","formatDate","input","month","date","monthLocale","formatNotionDateTime","datetime","dateString","formatDate","estimatePageReadTime","block","recordMap","wordsPerMinute","imageReadTimeInSeconds","stats","getBlockContentStats","totalWordsReadTimeInMinutes","totalImageReadTimeInMinutes","totalReadTimeInMinutes","__spreadProps","__spreadValues","estimatePageReadTimeAsHumanizedString","opts","estimate","humanizeReadTime","_a","_b","_c","_d","childId","child","recurse","title","getBlockTitle","countWordsInText","page","toc","getPageTableOfContents","tocItem","referencePointerId","referenceBlock","mergeContentStats","statsA","statsB","text","time","defaultMapImageUrl","url","block","u","e","notionImageUrlV2","table","defaultMapPageUrl","rootPageId","pageId"]}
1
+ {"version":3,"file":"index.js","sources":["../src/get-text-content.ts","../src/get-block-collection-id.ts","../src/get-block-title.ts","../src/get-block-icon.ts","../src/get-page-title.ts","../src/get-page-property.ts","../src/get-date-value.ts","../src/get-block-parent-page.ts","../src/get-page-table-of-contents.ts","../src/get-page-content-block-ids.ts","../src/id-to-uuid.ts","../src/parse-page-id.ts","../src/uuid-to-id.ts","../src/find-ancestors.ts","../src/get-all-in-space.ts","../src/normalize-title.ts","../src/get-canonical-page-id.ts","../src/get-page-breadcrumbs.ts","../src/get-page-image-urls.ts","../src/normalize-url.ts","../src/merge-record-maps.ts","../src/format-date.ts","../src/format-notion-date-time.ts","../src/estimate-page-read-time.ts","../src/map-image-url.ts","../src/map-page-url.ts"],"sourcesContent":["import type { Decoration } from '@texonom/ntypes'\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?: Decoration[]): string => {\n if (!text) return ''\n else if (Array.isArray(text))\n return text?.reduce((prev, current) => prev + (current[0] !== '⁍' && current[0] !== '‣' ? current[0] : ''), '') ?? ''\n else return text\n}\n","import type { Block, CollectionViewBlock, ExtendedRecordMap } from '@texonom/ntypes'\n\nexport function getBlockCollectionId(block: Block, recordMap: ExtendedRecordMap): string | null {\n const collectionId =\n (block as CollectionViewBlock).collection_id || (block as CollectionViewBlock).format?.collection_pointer?.id\n\n if (collectionId) return collectionId\n\n const collectionViewId = (block as CollectionViewBlock)?.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 { getBlockCollectionId } from './get-block-collection-id'\nimport { getTextContent } from './get-text-content'\n\nimport type { Block, ExtendedRecordMap } from '@texonom/ntypes'\n\nexport function getBlockTitle(block: Block, recordMap: ExtendedRecordMap) {\n if (block.properties?.title) return getTextContent(block.properties.title)\n\n if (block.type === 'collection_view_page' || block.type === 'collection_view') {\n const collectionId = getBlockCollectionId(block, recordMap)\n if (collectionId) {\n const collection = recordMap.collection[collectionId]?.value\n if (collection) return getTextContent(collection.name)\n }\n }\n return ''\n}\n","import { getBlockCollectionId } from './get-block-collection-id'\n\nimport type { Block, ExtendedRecordMap, PageBlock } from '@texonom/ntypes'\n\nexport function getBlockIcon(block: Block, recordMap: ExtendedRecordMap) {\n if ((block as PageBlock).format?.page_icon) return (block as PageBlock).format?.page_icon\n\n if (block.type === 'collection_view_page' || block.type === 'collection_view') {\n const collectionId = getBlockCollectionId(block, recordMap)\n if (collectionId) {\n const collection = recordMap.collection[collectionId]?.value\n\n if (collection) return collection.icon\n }\n }\n\n return null\n}\n","import type { ExtendedRecordMap } from '@texonom/ntypes'\n\nimport { getBlockTitle } from './get-block-title'\n\nexport function getPageTitle(recordMap: ExtendedRecordMap) {\n const pageBlock = recordMap.block[Object.keys(recordMap.block)[0]]?.value\n\n if (pageBlock) return getBlockTitle(pageBlock, recordMap)\n\n return null\n}\n","import { Block, DateFormat, ExtendedRecordMap } from '@texonom/ntypes'\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<T = string | number | boolean | string[] | number[]>(\n propertyName: string,\n block: Block,\n recordMap: ExtendedRecordMap\n): T\nexport function getPageProperty(propertyName: string, block: Block, recordMap: ExtendedRecordMap) {\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 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) return null\n\n const { type } = collection.schema[propertyId]\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(`${formatDate.start_date} ${formatDate.start_time}`).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","import type { FormattedDate } from '@texonom/ntypes'\n\n/**\n * Attempts to find a valid date from a given property.\n */\nexport const getDateValue = (prop: any[]): FormattedDate | null => {\n if (prop && Array.isArray(prop))\n if (prop[0] === 'd') return prop[1]\n else\n for (const v of prop) {\n const value = getDateValue(v)\n if (value) return value\n }\n\n return null\n}\n","import type { Block, ExtendedRecordMap, PageBlock, Collection, Space } from '@texonom/ntypes'\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: Block,\n recordMap: ExtendedRecordMap,\n {\n inclusive = false\n }: {\n inclusive?: boolean\n } = {}\n): PageBlock | null => {\n let currentRecord: Block | Collection = block\n\n while (currentRecord != null) {\n if (inclusive && (currentRecord as Block)?.type === 'page') return currentRecord as PageBlock\n\n const parentId: string = currentRecord.parent_id\n const parentTable = currentRecord.parent_table\n\n if (!parentId) break\n\n if (parentTable === 'collection') {\n currentRecord = recordMap.collection[parentId]?.value\n } else {\n currentRecord = recordMap.block[parentId]?.value\n if ((currentRecord as Block)?.type === 'page') return currentRecord as PageBlock\n }\n }\n return null\n}\n\nexport const getBlockParent = (\n block: Block,\n recordMap: ExtendedRecordMap,\n {\n inclusive = false\n }: {\n inclusive?: boolean\n } = {}\n): PageBlock | Collection | Space => {\n let currentRecord: Block | Collection | Space = block\n\n while (currentRecord != null) {\n if (inclusive && (currentRecord as Block)?.type === 'page') return currentRecord as PageBlock\n\n const parentId: string = currentRecord.parent_id\n const parentTable = currentRecord.parent_table\n\n if (!parentId) break\n\n if (parentTable === 'collection') {\n return recordMap.collection[parentId]?.value\n } else if (parentTable === 'space') {\n return recordMap.space?.[parentId]?.value\n } else {\n currentRecord = recordMap.block[parentId]?.value\n if ((currentRecord as Block)?.type === 'page') return currentRecord as PageBlock\n }\n }\n return null\n}\n","import { getTextContent } from './get-text-content'\n\nimport type { ID, BlockType, PageBlock, ExtendedRecordMap } from '@texonom/ntypes'\n\nexport interface TableOfContentsEntry {\n id: ID\n type: 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 = (page: PageBlock, recordMap: ExtendedRecordMap): Array<TableOfContentsEntry> => {\n const toc = (page.content ?? [])\n .map((blockId: string) => {\n const block = recordMap.block[blockId]?.value\n\n if (block) {\n const { type } = block\n\n if (type === 'header' || type === 'sub_header' || type === 'sub_sub_header')\n return {\n id: blockId,\n type,\n text: getTextContent(block.properties?.title),\n indentLevel: indentLevels[type]\n }\n }\n\n return null\n })\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[indentLevelStack.length - 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\n // eslint-disable-next-line no-constant-condition\n } while (true)\n }\n\n return toc\n}\n","import type { ExtendedRecordMap, Decoration } from '@texonom/ntypes'\n\n/**\n * Gets the IDs of all blocks contained on a page starting from a root block ID.\n */\nexport const getPageContentBlockIds = (recordMap: ExtendedRecordMap, blockId?: string, locust = false): 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 const { content, type, properties, format } = block\n if (properties)\n for (const key of Object.keys(properties)) {\n const p = properties[key]\n p.map((d: Decoration) => {\n const value = d?.[0]?.[1]?.[0]\n if (value?.[0] === 'p' && value[1]) addContentBlocks(value[1])\n })\n p.map((d: Decoration) => {\n const value = d?.[1]?.[0]\n if ((value?.[0] === 'p' || value?.[0] === 'eoi') && value[1]) addContentBlocks(value[1])\n })\n }\n\n if (format) {\n const referenceId = format.transclusion_reference_pointer?.id\n if (referenceId) addContentBlocks(referenceId)\n }\n // no child content blocks to recurse on\n if (!content || !Array.isArray(content)) return\n // ignore the content of other pages and collections\n if (blockId !== rootBlockId && !locust) if (type === 'page' || type === 'collection_view_page') return\n for (const blockId of content) addContentBlocks(blockId)\n }\n addContentBlocks(rootBlockId)\n return Array.from(contentBlockIds)\n}\n\n/**\n * Gets the IDs of all blocks contained on a page starting from a root block ID.\n */\nexport const getPageContentUserIds = (recordMap: ExtendedRecordMap, blockId?: string): string[] => {\n const rootBlockId = blockId || Object.keys(recordMap.block)[0]\n const contentUserIDs = new Set<string>()\n const block = recordMap.block[rootBlockId]?.value\n\n if (block?.created_by_id) contentUserIDs.add(block?.created_by_id)\n if (block?.last_edited_by_id) contentUserIDs.add(block?.last_edited_by_id)\n\n // Property\n const { properties } = block\n if (properties)\n for (const key of Object.keys(properties)) {\n const p = properties[key]\n p.map((d: Decoration) => {\n const value = d?.[1]?.[0]\n if (value?.[0] === 'u' && value[1]) contentUserIDs.add(value[1])\n })\n }\n\n return Array.from(contentUserIDs)\n}\n","export const idToUuid = (id = '') =>\n `${id.substr(0, 8)}-${id.substr(8, 4)}-${id.substr(12, 4)}-${id.substr(16, 4)}-${id.substr(20)}`\n","import { idToUuid } from './id-to-uuid'\n\nconst pageIdRe = /\\b([a-f0-9]{32})\\b/\nconst pageId2Re = /\\b([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{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 = (id: string | null = '', { uuid = true }: { uuid?: boolean } = {}) => {\n if (!id) return null\n\n id = id.split('?')[0]\n const match = id.match(pageIdRe)\n\n if (match) return uuid ? idToUuid(match[1]) : match[1]\n\n const match2 = id.match(pageId2Re)\n if (match2) return uuid ? match2[1] : match2[1].replace(/-/g, '')\n\n return null\n}\n","export const uuidToId = (uuid: string) => uuid.replace(/-/g, '')\n","import type { ExtendedRecordMap, Block, Collection } from '@texonom/ntypes'\n\nexport function findAncestors(recordMap: ExtendedRecordMap, block: Block | Collection, list: string[] = []): string[] {\n if (block.parent_id) {\n list.push(block.parent_id)\n const table = block.parent_table as 'block' | 'collection'\n if (recordMap[table]?.[block.parent_id]?.value)\n return findAncestors(recordMap, recordMap[table][block.parent_id].value, list)\n }\n return list\n}\n","import { findAncestors } from './find-ancestors'\nimport { getPageContentBlockIds } from './get-page-content-block-ids'\nimport { getBlockTitle } from './get-block-title'\n\nimport type { ExtendedRecordMap, PageMap, PageChunk, BlockMap } from '@texonom/ntypes'\n\nexport type PageTree = {\n id: string\n type: string\n title: string\n blocks: number\n pages: number\n parent?: PageTree\n children: PageTree[]\n}\n\ntype FetchOption = RequestInit & { timeout?: number }\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 *\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 getAllInSpace(\n startPageId: string,\n getPage: (pageId: string, { fetchOption }?: { fetchOption?: FetchOption }) => Promise<ExtendedRecordMap>,\n getBlocks: (blockIds: string[], fetchOption?: FetchOption) => Promise<PageChunk>,\n fetchCollections: (\n contentBlockIds: string[],\n recordMap: ExtendedRecordMap,\n pageId?: string,\n {\n fetchOption,\n concurrency,\n collectionConcurrency\n }?: { fetchOption?: FetchOption; concurrency: number; collectionConcurrency?: number }\n ) => Promise<ExtendedRecordMap>,\n {\n startRecordMap,\n fetchOption = { timeout: 100000 },\n maxPage,\n debug,\n concurrency = 100,\n collectionConcurrency = 100\n }: {\n startRecordMap?: ExtendedRecordMap\n fetchOption?: FetchOption\n concurrency?: number\n maxPage?: number\n debug?: boolean\n collectionConcurrency?: number\n } = {}\n): Promise<{ recordMap: ExtendedRecordMap; pageMap: PageMap; pageTree: PageTree }> {\n const pageMap: PageMap = {}\n const recordMap = startRecordMap ? startRecordMap : await getPage(startPageId, { fetchOption })\n\n let tempRecordMap: ExtendedRecordMap = JSON.parse(JSON.stringify(recordMap))\n\n if (debug) console.time('Total fetch time')\n let iteration = 1\n while (true) {\n if (debug) console.debug(`Iteration ${iteration}`)\n if (debug) console.debug('block length ', Object.keys(recordMap.block).length)\n\n if (debug) console.time('getPageContentBlockIds')\n const targetBlocks = Object.keys(tempRecordMap.block)\n const missing = Object.keys(\n targetBlocks.reduce((blockMap, root) => {\n const contentBlockIds = getPageContentBlockIds(recordMap, root, true)\n for (const contentBlockID of contentBlockIds) if (!recordMap.block[contentBlockID]) blockMap[contentBlockID] = true\n return blockMap\n }, {})\n )\n for (const { value: block } of Object.values(tempRecordMap.block))\n if (block && !recordMap.block[block.parent_id] && block.parent_table === 'block') missing.push(block.parent_id)\n if (debug) console.timeEnd('getPageContentBlockIds')\n\n if (debug) console.time('getBlocks')\n tempRecordMap = (await getBlocks(missing, fetchOption)).recordMap as ExtendedRecordMap\n if (debug) console.timeEnd('getBlocks')\n if (!tempRecordMap?.block) break\n\n if (debug) console.time('mapBlocks')\n const contentBlockIds = Object.values(recordMap.block)\n .map(obj => obj.value?.id)\n .filter(Boolean)\n recordMap.block = { ...recordMap.block, ...tempRecordMap.block }\n if (debug) console.timeEnd('mapBlocks')\n\n if (debug) console.time('fetchCollections')\n await fetchCollections(contentBlockIds, recordMap, undefined, { fetchOption, concurrency, collectionConcurrency })\n if (debug) console.timeEnd('fetchCollections')\n if (debug) console.debug('collection query length ' + Object.keys(recordMap.collection_query).length)\n\n if (debug) console.debug('new block length ', Object.keys(tempRecordMap.block).length)\n const pageLength = Object.values(recordMap.block)\n .map(obj => obj.value?.type)\n .filter(type => type === 'page').length\n if (debug) console.debug('page length ', pageLength)\n if (Number.isInteger(maxPage) && pageLength >= maxPage) break\n\n if (debug) console.debug(`memory usage ${process.memoryUsage().rss / 1024 / 1024}MB`)\n iteration += 1\n if (debug) console.debug()\n }\n if (debug) console.timeEnd('Total fetch time')\n\n if (debug) console.time('get page map')\n if (debug) console.debug('Total block length ', Object.keys(recordMap.block).length)\n const blockIds = Object.keys(recordMap.block)\n\n const promises = []\n for (const blockId of blockIds)\n if (recordMap.block[blockId].value?.type === 'page') {\n promises.push(getPageSync(blockId, recordMap, getBlocks).then(pageRecordMap => (pageMap[blockId] = pageRecordMap)))\n await sleep(1)\n }\n await Promise.all(promises)\n\n if (debug) console.timeEnd('get page map')\n if (debug) console.debug('Total page length ', Object.keys(pageMap).length)\n\n if (debug) console.time('get page tree')\n const pageTree = {\n id: startPageId,\n title: getBlockTitle(recordMap.block[startPageId].value, recordMap),\n blocks: 1,\n pages: 1,\n children: [],\n type: 'page'\n }\n recursivePageTree(recordMap, pageTree)\n if (debug) console.timeEnd('get page tree')\n\n return { pageMap, pageTree, recordMap }\n}\n\nexport function recursivePageTree(recordMap: ExtendedRecordMap, pageTree: PageTree): PageTree {\n // Save ancestors to update the count\n const ancestors = [pageTree]\n let ancestor = pageTree\n while (true)\n if (ancestor.parent) {\n ancestors.push(ancestor.parent)\n ancestor = ancestor.parent\n } else {\n break\n }\n\n const current = recordMap.block[pageTree.id]?.value\n if (!current) {\n console.warn(`No block value for ${pageTree.id}`)\n delete pageTree.parent\n return pageTree\n }\n\n if (current.content?.length) {\n for (const ancestor of ancestors) ancestor.blocks += current.content.length\n for (const contentBlockId of current.content) {\n const block = recordMap.block[contentBlockId]?.value\n if (!block) continue\n pageTree.children.push(\n recursivePageTree(recordMap, {\n id: contentBlockId,\n title: getBlockTitle(block, recordMap),\n blocks: 1,\n pages: 0,\n children: [],\n type: block.type,\n parent: pageTree\n })\n )\n if (block.type === 'page') for (const ancestor of ancestors) ancestor.pages++\n }\n } else if (current?.type === 'collection_view') {\n const collectionQuery = recordMap.collection_query[current.collection_id]?.[current.view_ids[0]]\n if (!collectionQuery) {\n console.warn(`No collection query for ${pageTree.id}`)\n delete pageTree.parent\n return pageTree\n }\n const childrenMap = {}\n for (const collectionQuery of Object.values(recordMap.collection_query[current.collection_id]))\n if (collectionQuery.collection_group_results.blockIds)\n for (const blockId of collectionQuery.collection_group_results.blockIds) childrenMap[blockId] = true\n const childrenPages = Object.keys(childrenMap)\n for (const ancestor of ancestors) ancestor.pages += childrenPages.length\n for (const ancestor of ancestors) ancestor.blocks += childrenPages.length\n for (const blockId of childrenPages)\n pageTree.children.push(\n recursivePageTree(recordMap, {\n id: blockId,\n title: getBlockTitle(recordMap.block[blockId].value, recordMap),\n blocks: childrenPages.length,\n pages: childrenPages.length,\n children: [],\n type: current.type,\n parent: pageTree\n })\n )\n }\n delete pageTree.parent\n return pageTree\n}\n\nexport async function getPageSync(\n pageId: string,\n recordMap: ExtendedRecordMap,\n getBlocks: (blockIds: string[], fetchOption?: FetchOption) => Promise<PageChunk>\n): Promise<ExtendedRecordMap> {\n let contentBlockIds = getPageContentBlockIds(recordMap, pageId)\n let blockMap: BlockMap = { [pageId]: { value: recordMap.block[pageId].value, role: 'reader' } }\n const collectionMap = {}\n const collectionViewMap = {}\n const collectionQueryMap = {}\n\n const missing = []\n for (const contentBlockId of contentBlockIds) {\n const block = recordMap.block[contentBlockId]?.value\n if (!block) {\n missing.push(contentBlockId)\n continue\n }\n blockMap[contentBlockId] = { value: block, role: 'reader' }\n if (block.type === 'collection_view' || block.type === 'collection_view_page') {\n if (recordMap.collection[block.collection_id])\n collectionMap[block.collection_id] = recordMap.collection[block.collection_id]\n if (recordMap.collection_query[block.collection_id])\n collectionQueryMap[block.collection_id] = recordMap.collection_query[block.collection_id]\n for (const viewId of block.view_ids)\n if (recordMap.collection_view[viewId]) {\n collectionViewMap[viewId] = recordMap.collection_view[viewId]\n const blockIds = recordMap.collection_query[block?.collection_id]?.[viewId]?.collection_group_results?.blockIds\n if (blockIds?.length)\n for (const blockId of blockIds) {\n const block = recordMap.block[blockId]?.value\n if (block) blockMap[blockId] = { value: block, role: 'reader' }\n else missing.push(blockId)\n }\n }\n }\n }\n\n // Ancestor\n const ancesters = findAncestors(recordMap, recordMap.block[pageId].value)\n for (const ancester of ancesters) {\n const block = recordMap.block[ancester]?.value\n if (block) blockMap[ancester] = { value: block, role: 'reader' }\n const collection = recordMap.collection[ancester]?.value\n if (collection) collectionMap[ancester] = { value: collection }\n }\n\n // Alias\n for (const blockId of Object.keys(blockMap)) {\n const block = blockMap[blockId].value\n let targetBlock = block\n if (block?.type === 'alias')\n while (true) {\n const alias = targetBlock?.format?.alias_pointer?.id\n if (!alias) break\n targetBlock = recordMap.block[alias]?.value\n if (!targetBlock) missing.push(alias)\n else blockMap[alias] = { value: targetBlock, role: 'reader' }\n }\n }\n\n // Missing\n if (missing.length) {\n const responseMap = (await getBlocks(missing).catch(() => ({ recordMap: { block: null } }))).recordMap\n if (responseMap?.block) {\n blockMap = { ...blockMap, ...responseMap.block }\n for (const blockId in responseMap.block) recordMap.block[blockId] = responseMap.block[blockId]\n } else {\n console.warn(`fetching ${missing.length} fail for ${pageId}`)\n }\n }\n\n contentBlockIds = getPageContentBlockIds(recordMap, pageId)\n for (const contentBlockId of contentBlockIds) {\n const block = recordMap.block[contentBlockId]?.value\n if (!block) continue\n blockMap[contentBlockId] = { value: block, role: 'reader' }\n if (block.type === 'collection_view' || block.type === 'collection_view_page') {\n if (recordMap.collection[block.collection_id])\n collectionMap[block.collection_id] = recordMap.collection[block.collection_id]\n if (recordMap.collection_query[block.collection_id])\n collectionQueryMap[block.collection_id] = recordMap.collection_query[block.collection_id]\n for (const viewId of block.view_ids)\n if (recordMap.collection_view[viewId]) {\n collectionViewMap[viewId] = recordMap.collection_view[viewId]\n const blockIds = recordMap.collection_query[block?.collection_id]?.[viewId]?.collection_group_results?.blockIds\n if (blockIds?.length)\n for (const blockId of blockIds) {\n const block = recordMap.block[blockId]?.value\n if (block) blockMap[blockId] = { value: block, role: 'reader' }\n }\n }\n }\n }\n\n return {\n block: blockMap,\n collection: collectionMap,\n collection_view: collectionViewMap,\n collection_query: collectionQueryMap,\n signed_urls: {},\n notion_user: {}\n }\n}\n\nconst sleep = async (ms: number) => new Promise(resolve => setTimeout(resolve, ms))\n","export const normalizeTitle = (title?: string | null): string => {\n return (title || '')\n .replace(/( |\\/)/g, '-') // Replace spaces and slashes with dashes\n .replace(/[^a-zA-Z0-9-\\u4e00-\\u9FFF\\uAC00-\\uD7AF\\u3130-\\u318F\\u3041-\\u3096\\u30A1-\\u30FC\\u3000-\\u303F]/g, '') // Retain Korean characters\n .replace(/--+/g, '-') // Replace multiple dashes with a single dash\n .replace(/^-+|-+$/g, '') // Trim leading and trailing dashes\n .trim()\n .toLowerCase()\n}\n","import { getBlockTitle } from './get-block-title'\nimport { getPageProperty } from './get-page-property'\nimport { normalizeTitle } from './normalize-title'\nimport { getTextContent } from './get-text-content'\nimport { uuidToId } from './uuid-to-id'\n\nimport type { ExtendedRecordMap } from '@texonom/ntypes'\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) || normalizeTitle(getBlockTitle(block, recordMap))\n\n if (slug)\n if (uuid) return `${slug}-${id}`\n else return slug\n } else {\n const collection = recordMap.collection[pageId]?.value\n if (collection) {\n const slug = normalizeTitle(getTextContent(collection.name))\n if (slug)\n if (uuid) return `${slug}-${id}`\n else return slug\n }\n }\n\n return id\n}\n","import { getBlockIcon } from './get-block-icon'\nimport { getBlockParentPage } from './get-block-parent-page'\nimport { getBlockTitle } from './get-block-title'\n\nimport type { ExtendedRecordMap } from '@texonom/ntypes'\n\nexport const getPageBreadcrumbs = (recordMap: ExtendedRecordMap, activePageId: string): 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) break\n\n const title = getBlockTitle(block, recordMap)\n const icon = getBlockIcon(block, recordMap)\n\n if (!(title || icon)) break\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) break\n\n currentPageId = parentId\n\n // eslint-disable-next-line no-constant-condition\n } while (true)\n\n breadcrumbs.reverse()\n\n return breadcrumbs\n}\n","import { getBlockIcon } from './get-block-icon'\nimport { isUrl } from './is-url'\n\nimport type { Block, ExtendedRecordMap } from '@texonom/ntypes'\n\n/**\n * Gets URLs of all images contained on the given page.\n */\nexport const getPageImageUrls = (\n recordMap: ExtendedRecordMap,\n {\n mapImageUrl\n }: {\n mapImageUrl: (url: string, block: Block) => string | null\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: 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')) source = block.properties?.source?.[0]?.[0]\n\n if (source)\n images.push({\n block,\n url: source\n })\n }\n\n if (block.format?.page_cover) {\n const source = block.format.page_cover\n\n images.push({\n block,\n url: source\n })\n }\n\n if (block.format?.bookmark_cover) {\n const source = block.format.bookmark_cover\n\n images.push({\n block,\n url: source\n })\n }\n\n if (block.format?.bookmark_icon) {\n const source = block.format.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 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 mem from 'mem'\nimport normalizeUrlImpl from 'normalize-url'\n\nexport const normalizeUrl = mem((url?: string) => {\n if (!url) return ''\n\n try {\n if (url.startsWith('https://www.notion.so/image/')) {\n const u = new URL(url)\n const subUrl = decodeURIComponent(u.pathname.substring('/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 (err) {\n return ''\n }\n})\n","import type { ExtendedRecordMap } from '@texonom/ntypes'\n\nexport function mergeRecordMaps(recordMapA: ExtendedRecordMap, recordMapB: ExtendedRecordMap): 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","export const formatDate = (input: string | number, { month = 'short' }: { month?: 'long' | 'short' } = {}) => {\n const date = new Date(input)\n const monthLocale = date.toLocaleString('en-US', { month })\n return `${date.getUTCFullYear()} ${monthLocale} ${date.getUTCDate()} ${date.getUTCHours()}:${date.getUTCMinutes()}`\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 const dateString = `${datetime.start_time || ''} ${datetime.start_date} ${datetime.time_zone || ''}`\n return formatDate(dateString)\n}\n","import { Block, ExtendedRecordMap, PageBlock } from '@texonom/ntypes'\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 { wordsPerMinute = 275, imageReadTimeInSeconds = 12 }: 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) + (stats.numImages - 10) * 3 // n/2(a+b) + 3 sec/image\n : (stats.numImages / 2) * (2 * imageReadTimeInSeconds + (1 - stats.numImages)) // n/2[2a+(n-1)d]\n const totalImageReadTimeInMinutes = totalImageReadTimeInSeconds / 60\n\n const totalReadTimeInMinutes = 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(block: Block, recordMap: ExtendedRecordMap): ContentStats {\n const stats: ContentStats = {\n numWords: 0,\n numImages: 0\n }\n\n if (!block) return stats\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) stats.numWords += countWordsInText(tocItem.text)\n\n break\n }\n\n case 'transclusion_reference': {\n const referencePointerId = child?.format?.transclusion_reference_pointer?.id\n\n if (!referencePointerId) continue\n\n const referenceBlock = recordMap.block[referencePointerId]?.value\n if (referenceBlock) mergeContentStats(stats, getBlockContentStats(referenceBlock, recordMap))\n\n break\n }\n\n default:\n // ignore unrecognized blocks\n break\n }\n\n if (recurse) mergeContentStats(stats, getBlockContentStats(child, recordMap))\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) return 0\n\n return (text.match(/\\w+/g) || []).length\n}\n\nfunction humanizeReadTime(time: number): string {\n if (time < 0.5) return 'less than a minute'\n\n if (time < 1.5) return '1 minute'\n\n return `${Math.ceil(time)} minutes`\n}\n","import { Block } from '@texonom/ntypes'\n\nexport const defaultMapImageUrl = (url: string, block: Block): string | null => {\n if (!url) return null\n\n if (url.startsWith('data:')) return url\n\n // more recent versions of notion don't proxy unsplash images\n if (url.startsWith('https://images.unsplash.com')) return url\n\n try {\n const u = new URL(url)\n\n if (u.pathname.startsWith('/secure.notion-static.com') && u.hostname.endsWith('.amazonaws.com'))\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 } catch {\n // ignore invalid urls\n }\n\n if (url.startsWith('/images')) url = `https://www.notion.so${url}`\n\n url = `https://www.notion.so${url.startsWith('/image') ? url : `/image/${encodeURIComponent(url)}`}`\n\n const notionImageUrlV2 = new URL(url)\n let table = block.parent_table === 'space' ? 'block' : block.parent_table\n if (table === 'collection' || table === 'team') 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 || '').replace(/-/g, '')\n\n if (rootPageId && pageId === rootPageId) return '/'\n else return `/${pageId}`\n}\n"],"names":["getTextContent","text","_a","prev","current","getBlockCollectionId","block","recordMap","collectionId","_b","collectionViewId","_c","collectionView","_e","_d","_g","_f","getBlockTitle","collection","getBlockIcon","getPageTitle","pageBlock","getPageProperty","propertyName","propertyNameL","propertyId","key","type","content","formatDate","start_date","start_time","end_date","end_time","startTime","endTime","e","getDateValue","prop","v","value","getBlockParentPage","inclusive","currentRecord","parentId","parentTable","getBlockParent","indentLevels","getPageTableOfContents","page","toc","blockId","indentLevelStack","tocItem","indentLevel","actual","prevIndent","prevActual","prevEffective","getPageContentBlockIds","locust","rootBlockId","contentBlockIds","addContentBlocks","properties","format","p","d","referenceId","getPageContentUserIds","contentUserIDs","idToUuid","id","pageIdRe","pageId2Re","parsePageId","uuid","match","match2","uuidToId","findAncestors","list","table","getAllInSpace","_0","_1","_2","_3","__async","startPageId","getPage","getBlocks","fetchCollections","startRecordMap","fetchOption","maxPage","debug","concurrency","collectionConcurrency","pageMap","tempRecordMap","iteration","targetBlocks","missing","blockMap","root","contentBlockID","obj","__spreadValues","pageLength","blockIds","promises","getPageSync","pageRecordMap","sleep","pageTree","recursivePageTree","ancestors","ancestor","contentBlockId","childrenMap","collectionQuery","childrenPages","pageId","collectionMap","collectionViewMap","collectionQueryMap","viewId","ancesters","ancester","targetBlock","alias","_i","_h","_j","responseMap","_k","_n","_m","_l","_o","ms","resolve","normalizeTitle","title","getCanonicalPageId","slug","getPageBreadcrumbs","activePageId","breadcrumbs","currentPageId","icon","parentBlock","getPageImageUrls","mapImageUrl","imageUrls","images","source","pageIcon","isUrl","url","normalizeUrl","mem","u","subUrl","normalizedSubUrl","normalizeUrlImpl","err","mergeRecordMaps","recordMapA","recordMapB","input","month","date","monthLocale","formatNotionDateTime","datetime","dateString","estimatePageReadTime","wordsPerMinute","imageReadTimeInSeconds","stats","getBlockContentStats","totalWordsReadTimeInMinutes","totalImageReadTimeInMinutes","totalReadTimeInMinutes","__spreadProps","estimatePageReadTimeAsHumanizedString","opts","estimate","humanizeReadTime","childId","child","recurse","countWordsInText","referencePointerId","referenceBlock","mergeContentStats","statsA","statsB","time","defaultMapImageUrl","notionImageUrlV2","defaultMapPageUrl","rootPageId"],"mappings":"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"}
package/build/is-url.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import isUrl from 'is-url-superb';
1
+ import { default as isUrl } from 'is-url-superb';
2
2
  export { isUrl };
3
3
  //# sourceMappingURL=is-url.d.ts.map
@@ -1,3 +1,3 @@
1
- import type { ExtendedRecordMap } from '@texonom/ntypes';
1
+ import { ExtendedRecordMap } from '@texonom/ntypes';
2
2
  export declare function mergeRecordMaps(recordMapA: ExtendedRecordMap, recordMapB: ExtendedRecordMap): ExtendedRecordMap;
3
3
  //# sourceMappingURL=merge-record-maps.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@texonom/nutils",
3
- "version": "1.4.7",
3
+ "version": "1.5.1",
4
4
  "type": "module",
5
5
  "description": "Useful utilities for working with Notion data. Isomorphic.",
6
6
  "repository": "texonom/notion-node",
@@ -20,14 +20,17 @@
20
20
  "build"
21
21
  ],
22
22
  "engines": {
23
- "node": ">=22.16.0"
23
+ "node": ">=22.22.0"
24
+ },
25
+ "devDependencies": {
26
+ "vite-plugin-dts": "^4.5.4"
24
27
  },
25
28
  "dependencies": {
26
29
  "is-url-superb": "^6.1.0",
27
30
  "mem": "^10.0.0",
28
- "normalize-url": "^8.0.1",
29
- "p-queue": "^8.1.0",
30
- "@texonom/ntypes": "^1.4.7"
31
+ "normalize-url": "^8.1.1",
32
+ "p-queue": "^9.1.0",
33
+ "@texonom/ntypes": "^1.5.1"
31
34
  },
32
35
  "standard-version": {
33
36
  "skip": {
@@ -36,8 +39,8 @@
36
39
  }
37
40
  },
38
41
  "scripts": {
39
- "build": "tsc && tsup",
40
- "watch": "tsup --watch --silent --onSuccess 'echo build successful'",
42
+ "build": "tsc && vite build",
43
+ "watch": "vite build --watch --mode development",
41
44
  "test": "vitest --run",
42
45
  "prerelease": "standard-version --skip.changelog --prerelease",
43
46
  "release": "standard-version --release-as",
package/readme.md ADDED
@@ -0,0 +1,73 @@
1
+ # nutils
2
+
3
+ Useful utilities for working with Notion data. Runs in Node.js and the browser.
4
+
5
+ [![NPM](https://img.shields.io/npm/v/@texonom/nutils.svg)](https://www.npmjs.com/package/@texonom/nutils) [![Build Status](https://github.com/texonom/notion-node/actions/workflows/test.yml/badge.svg)](https://github.com/texonom/notion-node/actions/workflows/test.yml) [![Prettier Code Formatting](https://img.shields.io/badge/code_style-prettier-brightgreen.svg)](https://prettier.io)
6
+
7
+ ## Features
8
+
9
+ - Convert between page IDs and UUIDs
10
+ - Map and normalize Notion URLs
11
+ - Helpers for reading page metadata
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pnpm i @texonom/nutils
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ```ts
22
+ import { parsePageId } from '@texonom/nutils'
23
+
24
+ parsePageId('https://www.notion.so/Notion-Tests-067dd719a912471ea9a3ac10710e7fdf')
25
+ // '067dd719-a912-471e-a9a3-ac10710e7fdf'
26
+
27
+ parsePageId('About-d9ae0c6e7cad49a78e21d240cf2e3d04', { uuid: false })
28
+ // 'd9ae0c6e7cad49a78e21d240cf2e3d04'
29
+
30
+ import { normalizeUrl } from '@texonom/nutils'
31
+ normalizeUrl('https://test.com/foo/bar?foo=bar')
32
+
33
+ import { defaultMapPageUrl, defaultMapImageUrl } from '@texonom/nutils'
34
+ const mapPage = defaultMapPageUrl('root')('067dd719a912471ea9a3ac10710e7fdf')
35
+ const mapImage = defaultMapImageUrl('/image.png', { id: 'id', parent_table: 'block' } as any)
36
+
37
+ import { getCanonicalPageId } from '@texonom/nutils'
38
+ getCanonicalPageId('067dd719-a912-471e-a9a3-ac10710e7fdf', recordMap)
39
+ ```
40
+
41
+ See the [full docs](https://github.com/texonom/notion-node) for more helpers.
42
+
43
+ ## API
44
+
45
+ The library exports many helpers. Each function works both in Node.js and the browser.
46
+
47
+ - `getTextContent(value)` – extract plain text from rich text values
48
+ - `getBlockTitle(block, recordMap)` – title of a block
49
+ - `getBlockIcon(block, recordMap)` – icon for a block
50
+ - `getBlockCollectionId(block, recordMap)` – collection id for collection view blocks
51
+ - `getPageTitle(recordMap)` – page title from a record map
52
+ - `getPageProperty(name, block, recordMap)` – any page property
53
+ - `getDateValue(value)` – normalize Notion date values
54
+ - `getBlockParentPage(block, recordMap)` – parent page block
55
+ - `getPageTableOfContents(recordMap)` – extract headers and links
56
+ - `getPageContentBlockIds(recordMap)` – list of block ids contained in a page
57
+ - `parsePageId(id, opts?)` – convert Notion URLs and ids
58
+ - `idToUuid(id)` – add dashes to a notion id
59
+ - `uuidToId(uuid)` – remove dashes from a uuid
60
+ - `getAllInSpace(api, spaceId)` – fetch every page in a workspace
61
+ - `getCanonicalPageId(pageId, recordMap)` – canonical slug for a page
62
+ - `getPageBreadcrumbs(block, recordMap)` – breadcrumb labels
63
+ - `getPageImageUrls(recordMap)` – all images used on a page
64
+ - `isUrl(value)` – check if a string is a URL
65
+ - `normalizeUrl(url)` – remove tracking params
66
+ - `normalizeTitle(title)` – cleanup page titles
67
+ - `mergeRecordMaps(a, b)` – combine multiple record maps
68
+ - `formatDate(value)` – format ISO date string
69
+ - `formatNotionDateTime(value)` – format Notion timestamps
70
+ - `findAncestors(blockId, recordMap)` – walk up the block tree
71
+ - `estimatePageReadTime(recordMap)` – count words for read time
72
+ - `mapImageUrl(url, block)` – default image URL mapper
73
+ - `mapPageUrl(id)` – default page URL mapper
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2022 Seonglae Cho
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/README.md DELETED
@@ -1,32 +0,0 @@
1
- # nutils
2
-
3
- > Useful utilities for working with Notion data. Isomorphic.
4
-
5
- [![NPM](https://img.shields.io/npm/v/@texonom/nutils.svg)](https://www.npmjs.com/package/@texonom/nutils) [![Build Status](https://github.com/texonom/notion-node/actions/workflows/test.yml/badge.svg)](https://github.com/texonom/notion-node/actions/workflows/test.yml) [![Prettier Code Formatting](https://img.shields.io/badge/code_style-prettier-brightgreen.svg)](https://prettier.io)
6
-
7
- ## Install
8
-
9
- ```bash
10
- pnpm i @texonom/nutils
11
- ```
12
-
13
- This package is compatible with both Node.js and client-side web usage.
14
-
15
- ## Usage
16
-
17
- ```ts
18
- import { parsePageId } from '@texonom/nutils'
19
-
20
- parsePageId('https://www.notion.so/Notion-Tests-067dd719a912471ea9a3ac10710e7fdf')
21
- // '067dd719-a912-471e-a9a3-ac10710e7fdf'
22
-
23
- parsePageId('About-d9ae0c6e7cad49a78e21d240cf2e3d04')
24
- // 'd9ae0c6e-7cad-49a7-8e21-d240cf2e3d04'
25
-
26
- parsePageId('About-d9ae0c6e7cad49a78e21d240cf2e3d04', { uuid: false })
27
- // 'd9ae0c6e7cad49a78e21d240cf2e3d04'
28
- ```
29
-
30
- ## Docs
31
-
32
- See the [full docs](https://github.com/texonom/notion-node).