@texonom/cli 1.4.7 → 1.5.0

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/main.ts","../../package.json","../../src/notion/export.ts","../../src/notion/index.ts","../../src/treemap.ts","../../src/stats.ts"],"sourcesContent":["import { Cli, Builtins } from 'clipanion'\n\nimport { version, displayName } from '../package.json'\nimport { NotionExportCommand } from './notion/export'\n\nconst cli = new Cli({\n binaryName: 'notion',\n binaryLabel: displayName,\n binaryVersion: version\n})\n\ncli.register(NotionExportCommand)\ncli.register(Builtins.HelpCommand)\ncli.register(Builtins.VersionCommand)\ncli.runExit(process.argv.slice(2), Cli.defaultContext)\n\nexport * from './notion/export'\nexport * from './notion/index'\nexport * from './treemap'\nexport * from './stats'\n","{\n \"name\": \"@texonom/cli\",\n \"displayName\": \"Notion CLI\",\n \"version\": \"1.4.7\",\n \"type\": \"module\",\n \"description\": \"Texonom CLI which has ability to export data from Notion.so\",\n \"repository\": \"texonom/notion-node\",\n \"author\": \"Seonglae Cho <sungle3737@gmail.com>\",\n \"license\": \"MIT\",\n \"main\": \"./build/src/main.js\",\n \"module\": \"./build/src/main.js\",\n \"types\": \"./build/src/main.d.ts\",\n \"sideEffects\": false,\n \"files\": [\n \"build\"\n ],\n \"engines\": {\n \"node\": \">=22.16.0\"\n },\n \"bin\": {\n \"notion\": \"./build/src/main.js\"\n },\n \"scripts\": {\n \"build\": \"tsc && tsup\",\n \"watch\": \"tsup --watch --silent --onSuccess 'echo build successful'\",\n \"test\": \"vitest --run\",\n \"prerelease\": \"standard-version --skip.changelog --prerelease\",\n \"release\": \"standard-version --release-as\",\n \"pu\": \"pnpm publish\"\n },\n \"dependencies\": {\n \"@texonom/nclient\": \"workspace:^\",\n \"@texonom/ntypes\": \"workspace:^\",\n \"@texonom/nutils\": \"workspace:^\",\n \"JSONStream\": \"^1.3.5\",\n \"clipanion\": \"^3.2.1\",\n \"graceful-fs\": \"^4.2.11\",\n \"prettier\": \"^3.5.3\"\n },\n \"standard-version\": {\n \"skip\": {\n \"commit\": true,\n \"tag\": true\n }\n },\n \"devDependencies\": {\n \"@types/graceful-fs\": \"^4.1.9\",\n \"@types/jsonstream\": \"^0.8.33\"\n }\n}\n","import { Option, Command } from 'clipanion'\nimport { NotionExporter } from './index'\nimport { generateTreemaps, PageNode } from '../treemap'\nimport { computeStats, writeStats } from '../stats'\n\nexport class NotionExportCommand extends Command {\n static paths = [['export']]\n\n folder = Option.String('-o,--output', 'texonom-raw', {\n description: 'Target root folder to export folder'\n })\n md = Option.String('-m,--md', 'texonom-md', {\n description: 'Target folder to export markdown'\n })\n domain = Option.String('-d,--domain', 'https://texonom.com', {\n description: 'Domain to fill in the link'\n })\n validation = Option.Boolean('-v,--validation', {\n description: 'Validation exported data only'\n })\n update = Option.Boolean('-u,--update', {\n description: 'Update exported data and resave to the --root'\n })\n page = Option.String('-p,--page', {\n required: true,\n description: 'Target page to export'\n })\n recursive = Option.Boolean('-r,--recursive', {\n description: 'Recursively export children'\n })\n prefetch = Option.Boolean('-f, --prefetch', {\n description: 'Prefetch all space for faster export (recommended for exporting all pages in a space)'\n })\n load = Option.Boolean('-l, --load', {\n description: 'Load data from exported cache folder --root'\n })\n raw = Option.Boolean('--raw', {\n description: 'Export raw recordMap JSON data \\n Markdown format do not preserve all information'\n })\n dataset = Option.Boolean('-d, --dataset', {\n description: 'Export as dataset for LLM learning'\n })\n treemap = Option.Boolean('--treemap', {\n description: 'Generate HTML treemap after export'\n })\n stats = Option.Boolean('--stats', {\n description: 'Generate statistics JSON after export'\n })\n token = Option.String('-t,--token', {\n description: 'Notion Access Token'\n })\n wait = Option.Counter('-w,--wait', {\n description: 'Wait couter for missed collection view'\n })\n\n async execute() {\n const exporter = new NotionExporter({\n folder: this.folder,\n validation: this.validation,\n update: this.update,\n page: this.page,\n recursive: this.recursive,\n prefetch: this.prefetch,\n load: this.load,\n raw: this.raw,\n dataset: this.dataset,\n token: this.token\n })\n await exporter.execute()\n\n if (this.treemap || this.stats) if (!exporter.pageTree) await exporter.loadRaw()\n\n const tree = exporter.pageTree as unknown as PageNode\n if (this.treemap && tree) await generateTreemaps(this.folder, tree)\n\n if (this.stats && tree) {\n const stats = computeStats(tree)\n await writeStats(`${this.folder}/stats.json`, stats)\n }\n }\n}\n","import { NotionAPI } from '@texonom/nclient'\nimport {\n getBlockTitle,\n getCanonicalPageId,\n parsePageId,\n formatDate,\n getTextContent,\n getBlockParent,\n defaultMapImageUrl,\n getAllInSpace,\n getPageTitle,\n recursivePageTree\n} from '@texonom/nutils'\nimport { join } from 'path'\nimport { mkdir, readFile } from 'fs/promises'\nimport JSONStream from 'JSONStream'\nimport fs from 'graceful-fs'\nimport { promisify } from 'util'\nimport stream from 'stream'\nimport { format } from 'prettier'\nimport { isCollection, isSpace } from '@texonom/ntypes'\n\nimport type { PageTree } from '@texonom/nutils'\nimport type { ExtendedRecordMap, PageMap, PageBlock, Block, Decoration, CollectionViewBlock } from '@texonom/ntypes'\n\nlet writeFile = promisify(fs.writeFile)\n\nexport const getBlockLink = (blockId: string, recordMap: ExtendedRecordMap, domain = 'https://texonom.com') =>\n `${domain}/${getCanonicalPageId(blockId, recordMap)}`\n\nexport type Markdown = {\n [attre in string]: string\n}\n\nexport class NotionExporter {\n notion: NotionAPI\n recordMap: ExtendedRecordMap\n pageTree: PageTree\n pageMap: PageMap\n promises: Promise<unknown>[] = []\n\n // Options\n folder: string = 'texonom-raw'\n md: string = 'texonom-md'\n domain: string = 'https://texonom.com'\n validation: boolean = true\n update: boolean = false\n page: string\n recursive: boolean = false\n prefetch: boolean = false\n load: boolean = false\n raw: boolean = false\n dataset: boolean = false\n debug: boolean = false\n wait: number = 5\n token: string | undefined\n\n constructor(options: {\n folder?: string\n validation?: boolean\n update?: boolean\n page: string\n recursive?: boolean\n prefetch?: boolean\n md?: string\n domain?: string\n load?: boolean\n raw?: boolean\n dataset?: boolean\n token?: string\n }) {\n this.page = parsePageId(options.page)\n this.folder = options.folder ?? this.folder\n this.domain = options.domain ?? this.domain\n this.md = options.md ?? this.md\n this.validation = options.validation ?? this.validation\n this.update = options.update ?? this.update\n this.recursive = options.recursive ?? this.recursive\n this.prefetch = options.prefetch ?? this.prefetch\n this.load = options.load ?? this.load\n this.raw = options.raw ?? this.raw\n this.dataset = options.dataset ?? this.dataset\n this.token = options.token\n\n this.notion = new NotionAPI({ authToken: this.token })\n if (this.validation) writeFile = async () => {}\n }\n\n async execute() {\n const id = parsePageId(this.page)\n\n // Load\n if (this.load) {\n console.time('Load raw data')\n await this.loadRaw()\n console.timeEnd('Load raw data')\n }\n if (this.prefetch) {\n console.time('Fetch raw data')\n await this.fetchRawSpace(id)\n console.timeEnd('Fetch raw data')\n }\n\n // Save\n if (this.raw) {\n console.time('Export raw files')\n if (this.recursive) await this.saveRawSpace()\n else await this.saveRawPage(id)\n console.timeEnd('Export raw files')\n }\n // Export\n else {\n console.time('Extract markdown')\n await this.exportMd(id)\n console.timeEnd('Extract markdown')\n const pageTree = {\n id: this.page,\n title: getBlockTitle(this.recordMap.block[this.page].value, this.recordMap),\n blocks: 1,\n pages: 1,\n children: [],\n type: 'page'\n }\n recursivePageTree(this.recordMap, pageTree)\n this.pageTree = pageTree\n }\n await Promise.all(this.promises)\n // Update\n if (this.update)\n if (this.recursive) await this.saveRawSpace()\n else await this.saveRawPage(id)\n }\n\n async loadRaw() {\n const { recordMap, pageTree, pageMap } = await loadRaw(this.folder)\n this.recordMap = recordMap\n this.pageTree = pageTree\n this.pageMap = pageMap\n }\n\n async fetchRawSpace(startPage: string) {\n const { recordMap, pageTree, pageMap } = await getAllInSpace(\n startPage,\n this.notion.getPage.bind(this.notion),\n this.notion.getBlocks.bind(this.notion),\n this.notion.fetchCollections.bind(this.notion),\n {\n startRecordMap: this.recordMap,\n collectionConcurrency: 100,\n concurrency: 100,\n fetchOption: { timeout: 10000 },\n debug: this.debug\n }\n )\n this.pageMap = pageMap\n this.recordMap = recordMap\n this.pageTree = pageTree\n }\n\n async saveRawSpace() {\n if (this.validation) return\n await mkdir(this.folder, { recursive: true })\n const promises = []\n await mkdir(join(this.folder, 'recordMap'), { recursive: true })\n for (const table in this.recordMap) this.saveJson(join('recordMap', table), this.recordMap[table])\n this.saveJson('pageMap', this.pageMap)\n this.saveJson('pageTree', this.pageTree)\n await Promise.all(promises)\n }\n\n saveJson(filename: string, object: Record<string, unknown>) {\n if (this.validation) return\n const outputStream = fs.createWriteStream(`${join(this.folder, filename)}.json`)\n const transformStream = JSONStream.stringifyObject()\n transformStream.pipe(outputStream)\n // @ts-ignore\n for (const key in object) transformStream.write([key, object[key]])\n transformStream.end()\n }\n\n async saveRawPage(id: string) {\n if (this.validation) return\n await mkdir(this.folder, { recursive: true })\n const recordMap = await this.notion.getPage(id)\n const filename = `${getCanonicalPageId(id, recordMap)}`\n let target = JSON.stringify(recordMap)\n const ext = 'json'\n target = await format(target, { parser: 'json' })\n await this.writeFile(`${join(this.folder, filename)}.${ext}`, target)\n }\n\n async writeFile(path: string, target: string) {\n if (!this.folder) return\n else await writeFile(path, target)\n }\n\n async exportMd(id: string) {\n await mkdir(this.md, { recursive: true })\n try {\n let recordMap = this.pageMap && this.pageMap[id]\n if (!recordMap) {\n console.warn(`Missing from pageMap ${id}`)\n recordMap = await this.notion.getPage(id)\n }\n if (!this.recursive) this.recordMap = recordMap\n try {\n if (!recordMap) recordMap = await this.notion.getPage(id)\n } catch {\n return\n }\n if (!['page', 'collection_view_page'].includes(recordMap.block[id].value.type)) throw new Error('Not a page')\n const target = await this.pageToMarkdown(id, recordMap)\n if (!this.pageMap[id]) this.pageMap[id] = recordMap\n const path = join(this.md, `${getCanonicalPageId(id, recordMap)}`)\n this.promises.push(this.writeFile(`${path}.md`, target))\n } catch (e) {\n console.error(id, e)\n }\n }\n\n async pageToMarkdown(id: string, recordMap: ExtendedRecordMap) {\n const markdown = await this.pageToMarkdownObj(id, recordMap)\n let md = `---\\nTitle: ${markdown.title}\\n`\n md += `Parent: ${markdown.parent}\\n`\n const attrs = Object.keys(markdown).filter(key => !['title', 'parent', 'body'].includes(key))\n for (const attr of attrs) md += `${attr}: ${markdown[attr]}\\n`\n md += '---\\n'\n md += markdown.body\n return md\n }\n\n async pageToMarkdownObj(id: string, recordMap: ExtendedRecordMap) {\n const page = recordMap.block[id].value as PageBlock\n const markdown: Markdown = {}\n\n // Title\n const title = await this.decorationsToMarkdown(\n page.properties?.title ? page.properties.title : [['Untitled']],\n recordMap\n )\n markdown.title = title\n\n // Parent\n const parentBlock = getBlockParent(page, recordMap)\n let parent: string\n if (isSpace(parentBlock)) parent = parentBlock.name\n else if (isCollection(parentBlock)) parent = getTextContent(parentBlock.name)\n else if (parentBlock) parent = getBlockTitle(parentBlock, recordMap)\n\n // Collection Attributes\n if (isCollection(parent)) {\n const properties = parent?.schema ? Object.keys(parent.schema) : []\n properties.splice(properties.indexOf('title'), 1)\n for (const property of properties) {\n const propName = parent.schema[property].name\n const propType = parent.schema[property].type\n let value = String()\n switch (propType) {\n case 'text':\n value = page?.properties?.[property]\n ? await this.decorationsToMarkdown(page.properties[property], recordMap)\n : ''\n break\n case 'created_by': {\n const user = await this.getUser(page.created_by_id, recordMap)\n value = user ? user.name : 'Unknown'\n break\n }\n case 'last_edited_by': {\n const user = await this.getUser(page.last_edited_by_id, recordMap)\n value = user ? user.name : 'Unknown'\n break\n }\n case 'created_time':\n value = formatDate(page.created_time)\n break\n case 'last_edited_time':\n value = formatDate(page.last_edited_time)\n break\n default:\n value = ''\n }\n markdown[propName] = value\n }\n }\n const body = await this.childrenToMd(page, recordMap, '', page)\n markdown.body = body\n return markdown\n }\n\n async childrenToMd(parentBlock: Block, recordMap: ExtendedRecordMap, prefix: string, page: Block) {\n let md = String()\n let numbering = 1\n for (const child of parentBlock.content ? parentBlock.content : []) {\n const childBlock = await this.getBlock(child, recordMap, `${child} from ${getBlockTitle(page, recordMap)}`)\n if (!childBlock) continue\n\n const title = childBlock?.properties?.title\n switch (childBlock.type) {\n case 'header':\n md += `${prefix}# ${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'sub_header':\n md += `${prefix}## ${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'sub_sub_header':\n md += `${prefix}### ${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'text':\n md += `${prefix}${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'bulleted_list':\n md += `${prefix}- ${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'numbered_list':\n md += `${prefix}${numbering++}. ${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'to_do':\n md += `${prefix}- [ ] ${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'toggle':\n md += `${prefix}<details><summary>${prefix}${prefix}${await this.decorationsToMarkdown(\n title,\n recordMap\n )}</summary>\\n`\n break\n case 'quote':\n md += (await this.decorationsToMarkdown(title, recordMap, `\\n${prefix.trim()}> `)) + '\\n'\n break\n case 'code':\n md += `${prefix}\\`\\`\\`type${await this.decorationsToMarkdown(title, recordMap)}\\`\\`\\``\n break\n case 'equation':\n md += `${prefix}$$${await this.decorationsToMarkdown(title, recordMap)}$$`\n break\n case 'callout': {\n md += (await this.decorationsToMarkdown(title, recordMap, `\\n${prefix.trim()}> `)) + '\\n'\n break\n }\n case 'bookmark': {\n const nesting = `\\n${prefix.trim()}> `\n md += `${nesting}[${getTextContent(\n childBlock.properties?.title ? childBlock.properties.title : [['Untitled']]\n )}](${getTextContent(childBlock.properties.link)})\\n`\n break\n }\n case 'external_object_instance': {\n try {\n const url = childBlock.format.original_url\n const title = childBlock.format.attributes\n ? childBlock.format.attributes.filter(attr => attr.id === 'title')[0]?.values?.[0]\n : url\n if (!url) break\n md += `${prefix}${prefix}[${title}](${url})${prefix}`\n break\n } catch (e) {\n console.error(e, childBlock.id)\n break\n }\n }\n\n // Collection\n case 'collection_view_page':\n case 'collection_view': {\n const collection = await this.getCollection(\n childBlock as CollectionViewBlock,\n recordMap,\n `${childBlock.id} from ${getPageTitle(recordMap)}`\n )\n if (!collection) continue\n\n // Generate Table\n md += `${prefix}### ${await this.decorationsToMarkdown(collection.name, recordMap)}`\n md += `${prefix}|Title|\\n|:-:|`\n const views = childBlock.view_ids\n .map(id => {\n if (!recordMap.collection_view[id]) if (this.debug) console.warn(`Missing view ${id} from ${collection.name}`)\n return recordMap.collection_view[id]?.value\n })\n .filter(Boolean)\n const children = []\n for (const view of views) {\n const results = await this.getCollectionView(\n collection.id,\n view.id,\n recordMap,\n `${collection.name} ${view.name}`\n )\n if (results) for (const result of results.blockIds) children.push(result)\n else break\n }\n for (const childPage of children) {\n const childBlock = recordMap.block[childPage]?.value\n if (!childBlock) if (this.debug) console.warn(`no ${childPage} in ${collection.name[0]}`)\n md += `${prefix}|[${getBlockTitle(childBlock, recordMap)}](${getBlockLink(childPage, recordMap)})|`\n }\n\n // Make children page\n if (this.recursive && children.length)\n for (const childPage of children) this.promises.push(this.exportMd(childPage))\n\n break\n }\n case 'page': {\n md += `${prefix}${prefix}[${getBlockTitle(childBlock, recordMap)}](${getBlockLink(\n childBlock.id,\n recordMap\n )})${prefix}`\n if (this.recursive) this.promises.push(this.exportMd(childBlock.id))\n\n break\n }\n case 'alias': {\n const aliasBlock = recordMap.block[childBlock.format?.alias_pointer?.id]?.value\n if (!aliasBlock) {\n if (this.debug)\n console.warn(\n `Missing alias ${childBlock.format?.alias_pointer?.id} from ${getBlockTitle(page, recordMap)} ${page.id}`\n )\n continue\n }\n md += `${prefix}${prefix}[${getBlockTitle(aliasBlock, recordMap)}](${getBlockLink(\n aliasBlock.id,\n recordMap\n )})${prefix}`\n break\n }\n\n // Media\n case 'image': {\n const caption = childBlock.properties.caption ? getTextContent(childBlock.properties.caption) : ''\n md += `${prefix}![${caption}](${defaultMapImageUrl(childBlock.format?.display_source, childBlock)})`\n break\n }\n\n case 'video':\n md += `${prefix}<video src=\"${childBlock.format.display_source} />`\n break\n\n // Embed\n case 'file':\n md += `${prefix}[File](${childBlock.format?.display_source})`\n break\n case 'pdf':\n md += `${prefix}<iframe src=\"${childBlock.format?.display_source}\"/>`\n break\n\n // Else\n case 'divider':\n md += `${prefix}---`\n break\n case 'column_list':\n break\n case 'column':\n break\n default:\n md += `${prefix}`\n }\n\n // Finalize\n if (childBlock.content && childBlock.type !== 'page' && childBlock.type !== 'collection_view_page') {\n const nestedPrefix = ['toggle', `transclusion_container`, `transclusion_reference`, 'column_list'].includes(\n childBlock.type\n )\n ? prefix\n : `\\n${prefix.trim()}> `\n md += await this.childrenToMd(childBlock, recordMap, nestedPrefix, page)\n if (childBlock.type === 'column') md += '\\n'\n }\n if (childBlock.type === 'toggle') md += `${prefix}</details>${prefix}`\n }\n return md\n }\n\n async decorationsToMarkdown(decos: Decoration[], recordMap: ExtendedRecordMap, prefix = '') {\n if (!decos) return String()\n let md = String()\n for (const deco of decos) {\n let wrapper = String()\n const [text, subdecos] = deco\n if (!subdecos) {\n md += text\n } else {\n let textonly: string = text\n for (const subdeco of subdecos)\n switch (subdeco[0]) {\n case 'p': {\n const blockId = subdeco[1]\n const linkedBlock = await this.getBlock(blockId, recordMap, `\"p\" ${getPageTitle(recordMap)}`)\n if (!linkedBlock) break\n\n const title = getBlockTitle(linkedBlock, recordMap)\n const url = getBlockLink(blockId, recordMap)\n textonly = `[${title}](${url})`\n break\n }\n case 'a': {\n const url = subdeco[1]\n textonly = `[${text}](${url})`\n break\n }\n case 'i':\n wrapper += '*'\n break\n case 'b':\n wrapper += '**'\n break\n case 'h':\n // Disable for now == syntax does not supported well\n wrapper += ''\n break\n case 'c':\n wrapper += '`'\n break\n case 's':\n wrapper += '~~'\n break\n case 'e':\n wrapper += '$'\n textonly = subdeco[1]\n break\n case 'eoi': {\n try {\n const objectid = subdeco[1]\n const object = await this.getBlock(objectid, recordMap, `\"eoi\" ${getPageTitle(recordMap)}`)\n if (!object) break\n const url = object.format.uri\n const title = object.format.attributes\n ? object.format.attributes?.filter(attr => attr.id === 'title')[0]?.values?.[0]\n : url\n if (!url) break\n textonly = `[${title}](${url})`\n break\n } catch (e) {\n console.error(e, deco)\n break\n }\n }\n case 'u': {\n const user = await this.getUser(subdeco[1], recordMap)\n if (!user) break\n textonly = `[@${user.name}](mailto:${user.email})`\n break\n }\n }\n let decorated: string = textonly\n if (subdecos.find(subdeco => subdeco[0] === '_')) decorated = `<u>${textonly}</u>`\n decorated = wrapper + decorated + wrapper.split('').reverse().join('')\n md += decorated\n }\n }\n const lines = md.split('\\n')\n const prefixed = lines.map(line => prefix + line)\n return prefixed.join('')\n }\n\n async getBlock(id: string, recordMap: ExtendedRecordMap, message = '') {\n let block = recordMap.block[id]?.value\n if (!block && this.recordMap) block = this.recordMap.block[id]?.value\n try {\n if (!block && this.token) {\n const notion = new NotionAPI({ authToken: this.token })\n const response = await notion.getBlocks([id])\n block = response.recordMap?.block?.[id]?.value\n }\n } catch {\n if (!block) if (this.debug) console.warn(`${message} Missing block ${id}`)\n }\n if (block) {\n recordMap.block[id] = { value: block, role: 'reader' }\n if (this.recordMap) this.recordMap.block[id] = { value: block, role: 'reader' }\n }\n return block\n }\n\n async getUser(id: string, recordMap: ExtendedRecordMap) {\n let user = recordMap.notion_user[id]?.value\n if (!user && this.recordMap) user = this.recordMap.notion_user[id]?.value\n try {\n if (!user && this.token) {\n const notion = new NotionAPI({ authToken: this.token })\n const response = await notion.getUsers([id])\n user = response.recordMapWithRoles?.notion_user?.[id]?.value\n }\n } catch {\n if (!user) if (this.debug) console.warn(`Missing user ${id}`)\n }\n if (user) {\n recordMap.notion_user[id] = { value: user, role: 'reader' }\n if (this.recordMap) this.recordMap.notion_user[id] = { value: user, role: 'reader' }\n }\n return user\n }\n\n async getCollection(collectionViewBlock: CollectionViewBlock, recordMap: ExtendedRecordMap, message = '') {\n const collectionId = collectionViewBlock.collection_id\n let collection = recordMap.collection[collectionViewBlock.collection_id]?.value\n if (!collection && this.recordMap) {\n collection = this.recordMap.collection[collectionId]?.value\n if (collection) {\n recordMap.collection[collectionId] = this.recordMap.collection?.[collectionId]\n for (const viewId of collectionViewBlock.view_ids)\n recordMap.collection_view[viewId] = this.recordMap.collection_view?.[viewId]\n }\n }\n try {\n if (!collection && this.token) {\n const notion = new NotionAPI({ authToken: this.token })\n const response = await notion.getPageRaw(collectionViewBlock.id)\n // @wait for rate limit\n sleepSync(1000 * this.wait)\n if (!response.recordMap) console.error(response)\n collection = response.recordMap.collection[collectionId]?.value\n if (collection) {\n recordMap.collection_view = { ...recordMap.collection_view, ...response.recordMap.collection_view }\n recordMap.collection = { ...recordMap.collection, ...response.recordMap.collection }\n recordMap.block = { ...recordMap.block, ...response.recordMap.block }\n this.recordMap.collection_view = { ...this.recordMap.collection_view, ...response.recordMap.collection_view }\n this.recordMap.collection = { ...this.recordMap.collection, ...response.recordMap.collection }\n this.recordMap.block = { ...this.recordMap.block, ...response.recordMap.block }\n }\n }\n } catch {\n if (!collection) if (this.debug) console.warn(`${message} Missing collection block ${collectionViewBlock.id}`)\n }\n await this.getCollectionView(collectionId, collectionViewBlock.view_ids[0], recordMap, message)\n return collection\n }\n\n async getCollectionView(collectionId: string, viewId: string, recordMap: ExtendedRecordMap, message = '') {\n let results = recordMap.collection_query?.[collectionId]?.[viewId]?.collection_group_results\n if (!results && this.recordMap) {\n results = this.recordMap.collection_query?.[collectionId]?.[viewId]?.collection_group_results\n if (results) {\n recordMap.collection_query![collectionId] = {\n ...recordMap.collection_query![collectionId],\n [viewId]: this.recordMap.collection_query?.[collectionId]?.[viewId]\n }\n this.recordMap.collection_query![collectionId] = {\n ...this.recordMap.collection_query![collectionId],\n [viewId]: this.recordMap.collection_query?.[collectionId]?.[viewId]\n }\n recordMap.collection![collectionId] = {\n ...recordMap.collection![collectionId],\n [viewId]: this.recordMap.collection?.[collectionId]?.[viewId]\n }\n this.recordMap.collection![collectionId] = {\n ...this.recordMap.collection![collectionId],\n [viewId]: this.recordMap.collection?.[collectionId]?.[viewId]\n }\n }\n }\n try {\n if (!results && this.token) {\n const notion = new NotionAPI({ authToken: this.token })\n const response = await notion.getCollectionData(collectionId, viewId, recordMap.collection_view[viewId]?.value)\n results = response.result?.reducerResults?.collection_group_results\n if (results) {\n recordMap.collection_query![collectionId] = {\n ...recordMap.collection_query![collectionId],\n [viewId]: response.result?.reducerResults\n }\n if (this.recordMap)\n this.recordMap.collection_query![collectionId] = {\n ...this.recordMap.collection_query![collectionId],\n [viewId]: response.result?.reducerResults\n }\n for (const blockId in response.recordMap.block) {\n const block = response.recordMap.block[blockId].value\n if (block) {\n recordMap.block[blockId] = { value: block, role: 'reader' }\n if (this.recordMap) this.recordMap.block[blockId] = { value: block, role: 'reader' }\n }\n }\n for (const collection in response.recordMap.collection) {\n const collectionValue = response.recordMap.collection[collection].value\n if (collectionValue) {\n recordMap.collection[collection] = { value: collectionValue, role: 'reader' }\n if (this.recordMap) this.recordMap.collection[collection] = { value: collectionValue, role: 'reader' }\n }\n }\n for (const collectionView in response.recordMap.collection_view) {\n const collectionViewValue = response.recordMap.collection_view[collectionView].value\n if (collectionViewValue) {\n recordMap.collection_view[collectionView] = { value: collectionViewValue, role: 'reader' }\n if (this.recordMap)\n this.recordMap.collection_view[collectionView] = { value: collectionViewValue, role: 'reader' }\n }\n }\n }\n }\n } catch {\n if (!results) if (this.debug) console.warn(`${message} Missing collection view ${viewId}`)\n }\n return results\n }\n\n async getSpace(id: string, recordMap: ExtendedRecordMap) {\n let space = recordMap.space[id]?.value\n if (!space && this.recordMap) space = this.recordMap.space[id]?.value\n try {\n if (!space && this.token) {\n const notion = new NotionAPI({ authToken: this.token })\n const response = await notion.getSpaces([id])\n space = response.recordMapWithRoles?.space?.[id]?.value\n if (space) {\n recordMap.space[id] = { value: space, role: 'reader' }\n if (this.recordMap) this.recordMap.space[id] = { value: space, role: 'reader' }\n }\n }\n } catch {\n if (!space) if (this.debug) console.warn(`Missing space ${id}`)\n }\n return space\n }\n}\n\nexport async function loadRaw(\n folder: string\n): Promise<{ recordMap: ExtendedRecordMap; pageTree: PageTree; pageMap: PageMap }> {\n const promises = []\n promises.push(readFile(join(folder, 'recordMap', 'block.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'recordMap', 'collection.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'recordMap', 'notion_user.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'recordMap', 'space.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'recordMap', 'collection_view.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'recordMap', 'collection_query.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'recordMap', 'signed_urls.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'pageTree.json'), 'utf8').then(JSON.parse))\n\n const [block, collection, notion_user, space, collection_view, collection_query, signed_urls, pageTree] =\n await Promise.all(promises)\n\n const pageMap = {}\n const inputStream = fs.createReadStream(join(folder, 'pageMap.json'))\n const parseStream = JSONStream.parse('*')\n inputStream.pipe(parseStream)\n parseStream.on('data', (recordMap: ExtendedRecordMap) => {\n const key = Object.keys(recordMap.block)[0]\n pageMap[key] = recordMap\n })\n await new Promise(res => stream.finished(parseStream, err => res(err)))\n const recordMap: ExtendedRecordMap = {\n block,\n collection,\n notion_user,\n space,\n collection_query,\n collection_view,\n signed_urls\n }\n return { recordMap, pageTree, pageMap }\n}\n\nexport async function loadJson<C>(folder: string, filename: string): Promise<C> {\n const object = {} as C\n const inputStream = fs.createReadStream(join(folder, `${filename}.json`))\n const parseStream = JSONStream.parse('*')\n inputStream.pipe(parseStream)\n parseStream.on('*', ([key, value]) => {\n object[key] = value\n })\n return new Promise(res =>\n stream.finished(parseStream, err => {\n console.error(err)\n res(object)\n })\n )\n}\n\nconst sleepSync = (ms: number) => {\n const sharedBuffer = new Int32Array(new SharedArrayBuffer(4))\n Atomics.wait(sharedBuffer, 0, 0, ms)\n}\n","import fs from 'fs'\nimport { promisify } from 'util'\n\nexport interface PageNode {\n id: string\n blocks: number\n pages: number\n title: string\n children?: PageNode[]\n}\n\nconst writeFile = promisify(fs.writeFile)\n\nexport async function generateTreemaps(folder: string, pageTree: PageNode) {\n const treemapDataPages = computeMetrics(pageTree, 'pages')\n const titlePages = 'Texonom PageTree'\n const outputPathPages = `${folder}/pagetree.html`\n await generateTreemapHTML(treemapDataPages, titlePages, outputPathPages)\n\n const treemapDataBlocks = computeMetrics(pageTree, 'blocks')\n const titleBlocks = 'Texonom BlockMap'\n const outputPathBlocks = `${folder}/blocktree.html`\n await generateTreemapHTML(treemapDataBlocks, titleBlocks, outputPathBlocks)\n}\n\ninterface TreemapNode {\n id: string\n name: string\n value: number\n children?: TreemapNode[]\n}\n\nfunction computeMetrics(pageTree: PageNode, metric: 'blocks' | 'pages'): TreemapNode | null {\n function recurse(node: PageNode): TreemapNode | null {\n const children = node.children ? node.children.map(recurse).filter((child): child is TreemapNode => child !== null) : []\n let nodeValue = node[metric] || 0\n\n // Sum the values of the children\n if (children.length > 0) {\n const childrenValue = children.reduce((sum, child) => sum + child.value, 0)\n if (nodeValue === 0) nodeValue = childrenValue\n }\n\n // Exclude nodes with zero value\n if (nodeValue <= 0) return null\n\n return {\n id: node.id,\n name: node.title,\n value: nodeValue,\n children: children.length > 0 ? children : undefined\n }\n }\n return recurse(pageTree)\n}\n\nasync function generateTreemapHTML(data: TreemapNode, title: string, outputPath: string) {\n const htmlContent = `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<title>${title}</title>\n<style>\n body {\n margin: 0;\n font-family: sans-serif;\n background-color: #202229;\n }\n .header {\n text-align: center;\n margin: 20px;\n font-size: 24px;\n color: white;\n }\n .breadcrumb {\n text-align: center;\n margin: 10px;\n font-size: 16px;\n color: white;\n }\n .current-title {\n text-align: center;\n margin: 10px;\n font-size: 18px;\n color: white;\n }\n .chart {\n width: 100%;\n height: 70vh;\n margin: auto;\n position: relative;\n }\n .node rect {\n cursor: pointer;\n stroke: #fff;\n stroke-width: 1px;\n rx: 8;\n ry: 8;\n }\n .label {\n text-anchor: middle;\n fill: white;\n text-decoration: underline;\n cursor: pointer;\n }\n .count {\n text-anchor: middle;\n fill: lightgray;\n }\n</style>\n</head>\n<body>\n<div class=\"header\">${title}</div>\n<div class=\"breadcrumb\" id=\"breadcrumb\"></div>\n<div class=\"current-title\" id=\"current-title\"></div>\n<div class=\"chart\" id=\"chart\"></div>\n<script src=\"https://d3js.org/d3.v6.min.js\"></script>\n<script>\n var data = ${JSON.stringify(data)};\n\n var margin = {top: 20, right: 0, bottom: 0, left: 0},\n width = document.getElementById('chart').clientWidth,\n height = document.getElementById('chart').clientHeight;\n\n var color = d3.scaleOrdinal()\n .domain([0, 1, 2, 3, 4, 5])\n .range([\"#465881\", \"#5f6d96\", \"#7882ab\", \"#9197c0\"]);\n\n var x = d3.scaleLinear()\n .domain([0, width])\n .range([0, width]);\n\n var y = d3.scaleLinear()\n .domain([0, height])\n .range([0, height]);\n\n var treemapLayout = d3.treemap()\n .size([width, height])\n .paddingInner(2)\n .round(false);\n\n var root = d3.hierarchy(data)\n .sum(function(d) { return d.value; })\n .sort(function(a, b) { return b.value - a.value; });\n\n treemapLayout(root);\n\n var svg = d3.select(\"#chart\").append(\"svg\")\n .attr(\"width\", width)\n .attr(\"height\", height)\n .style(\"font\", \"10px sans-serif\")\n .style(\"position\", \"relative\");\n\n display(root);\n\n function display(d) {\n var currentDepth = d.depth;\n\n // Update breadcrumb\n var breadcrumb = d.ancestors().reverse().map(function(d) {\n return '<span class=\"breadcrumb-item\" data-id=\"' + d.data.id + '\">' + d.data.name + '</span>';\n }).join(' / ');\n document.getElementById('breadcrumb').innerHTML = breadcrumb;\n\n // Add click events to breadcrumb\n var breadcrumbItems = document.querySelectorAll('.breadcrumb-item');\n breadcrumbItems.forEach(function(item) {\n item.addEventListener('click', function(event) {\n var id = event.target.getAttribute('data-id');\n var node = findNodeById(root, id);\n if (node) {\n zoom(node);\n }\n });\n });\n\n // Update current title\n document.getElementById('current-title').innerText = d.data.name;\n\n x.domain([d.x0, d.x1]);\n y.domain([d.y0, d.y1]);\n\n var nodes = d.descendants().filter(function(node) {\n return node.depth - currentDepth <= 1 && node.depth >= currentDepth;\n });\n\n svg.selectAll(\".node\").remove();\n\n var cell = svg.selectAll(\".node\")\n .data(nodes)\n .enter().append(\"g\")\n .attr(\"class\", \"node\")\n .attr(\"transform\", function(d) { return \"translate(\" + x(d.x0) + \",\" + y(d.y0) + \")\"; })\n .on(\"click\", function(event, d) {\n if (d.children) {\n zoom(d);\n } else {\n window.open('https://texonom.com/' + d.data.id, '_blank');\n }\n event.stopPropagation();\n });\n\n cell.append(\"rect\")\n .attr(\"id\", function(d) { return d.data.id; })\n .attr(\"width\", function(d) { return x(d.x1) - x(d.x0); })\n .attr(\"height\", function(d) { return y(d.y1) - y(d.y0); })\n .attr(\"fill\", function(d) { return color(d.depth); })\n .attr(\"rx\", 8)\n .attr(\"ry\", 8);\n\n cell.append(\"text\")\n .attr(\"class\", \"label\")\n .attr(\"x\", function(d) { return (x(d.x1) - x(d.x0)) / 2; })\n .attr(\"y\", function(d) { return (y(d.y1) - y(d.y0)) / 2; })\n .text(function(d) { return d.data.name; })\n .style(\"font-size\", function(d) {\n var boxArea = (x(d.x1) - x(d.x0)) * (y(d.y1) - y(d.y0));\n var size = Math.max(10, Math.min(30, Math.sqrt(boxArea) / 5));\n return size + \"px\";\n })\n .on(\"click\", function(event, d) {\n window.open('https://texonom.com/' + d.data.id, '_blank');\n event.stopPropagation();\n });\n\n cell.append(\"text\")\n .attr(\"class\", \"count\")\n .attr(\"x\", function(d) { return (x(d.x1) - x(d.x0)) / 2; })\n .attr(\"y\", function(d) { return (y(d.y1) - y(d.y0)) / 2 + 20; })\n .text(function(d) { return d.data.value; })\n .style(\"fill\", \"lightgray\")\n .style(\"font-size\", \"0.8rem\");\n }\n\n function zoom(d) {\n var currentDepth = d.depth;\n\n // Update breadcrumb\n var breadcrumb = d.ancestors().reverse().map(function(d) {\n return '<span class=\"breadcrumb-item\" data-id=\"' + d.data.id + '\">' + d.data.name + '</span>';\n }).join(' / ');\n document.getElementById('breadcrumb').innerHTML = breadcrumb;\n\n // Add click events to breadcrumb\n var breadcrumbItems = document.querySelectorAll('.breadcrumb-item');\n breadcrumbItems.forEach(function(item) {\n item.addEventListener('click', function(event) {\n var id = event.target.getAttribute('data-id');\n var node = findNodeById(root, id);\n if (node) {\n zoom(node);\n }\n });\n });\n\n // Update current title\n document.getElementById('current-title').innerText = d.data.name;\n\n var t = svg.transition()\n .duration(750);\n\n x.domain([d.x0, d.x1]);\n y.domain([d.y0, d.y1]);\n\n var nodes = d.descendants().filter(function(node) {\n return node.depth - currentDepth <= 1 && node.depth >= currentDepth;\n });\n\n var cell = svg.selectAll(\".node\")\n .data(nodes, function(d) { return d.data.id; });\n\n cell.exit().remove();\n\n var cellEnter = cell.enter().append(\"g\")\n .attr(\"class\", \"node\")\n .on(\"click\", function(event, d) {\n if (d.children) {\n zoom(d);\n } else {\n window.open('https://texonom.com/' + d.data.id, '_blank');\n }\n event.stopPropagation();\n });\n\n cellEnter.append(\"rect\")\n .attr(\"id\", function(d) { return d.data.id; })\n .attr(\"fill\", function(d) { return color(d.depth); })\n .attr(\"rx\", 8)\n .attr(\"ry\", 8);\n\n cellEnter.append(\"text\")\n .attr(\"class\", \"label\")\n .style(\"fill\", \"white\")\n .on(\"click\", function(event, d) {\n window.open('https://texonom.com/' + d.data.id, '_blank');\n event.stopPropagation();\n });\n\n cellEnter.append(\"text\")\n .attr(\"class\", \"count\")\n .style(\"fill\", \"lightgray\")\n .style(\"font-size\", \"0.8rem\");\n\n cell = cellEnter.merge(cell);\n\n cell.transition(t)\n .attr(\"transform\", function(d) { return \"translate(\" + x(d.x0) + \",\" + y(d.y0) + \")\"; });\n\n cell.select(\"rect\").transition(t)\n .attr(\"width\", function(d) { return x(d.x1) - x(d.x0); })\n .attr(\"height\", function(d) { return y(d.y1) - y(d.y0); });\n\n cell.select(\".label\").transition(t)\n .attr(\"x\", function(d) { return (x(d.x1) - x(d.x0)) / 2; })\n .attr(\"y\", function(d) { return (y(d.y1) - y(d.y0)) / 2; })\n .text(function(d) { return d.data.name; })\n .style(\"font-size\", function(d) {\n var boxArea = (x(d.x1) - x(d.x0)) * (y(d.y1) - y(d.y0));\n var size = Math.max(10, Math.min(30, Math.sqrt(boxArea) / 5));\n return size + \"px\";\n });\n\n cell.select(\".count\").transition(t)\n .attr(\"x\", function(d) { return (x(d.x1) - x(d.x0)) / 2; })\n .attr(\"y\", function(d) { return (y(d.y1) - y(d.y0)) / 2 + 20; })\n .text(function(d) { return d.data.value; });\n }\n\n function findNodeById(node, id) {\n if (node.data.id === id) {\n return node;\n }\n if (node.children) {\n for (var child of node.children) {\n var result = findNodeById(child, id);\n if (result) return result;\n }\n }\n return null;\n }\n</script>\n</body>\n</html>\n `\n\n await writeFile(outputPath, htmlContent, 'utf8')\n}\n","import type { PageNode } from './treemap'\n\nexport interface ExportStats {\n totalPages: number\n totalBlocks: number\n maxDepth: number\n}\n\nexport function computeStats(pageTree: PageNode): ExportStats {\n let totalPages = 0\n let totalBlocks = 0\n let maxDepth = 0\n\n function traverse(node: PageNode, depth: number) {\n totalPages += node.pages || 0\n totalBlocks += node.blocks || 0\n if (depth > maxDepth) maxDepth = depth\n if (node.children) for (const child of node.children) traverse(child, depth + 1)\n }\n\n traverse(pageTree, 1)\n return { totalPages, totalBlocks, maxDepth }\n}\n\nexport async function writeStats(file: string, stats: ExportStats) {\n const fs = await import('fs/promises')\n await fs.writeFile(file, JSON.stringify(stats, null, 2), 'utf8')\n}\n"],"mappings":"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","names":["Cli","Builtins","displayName","version","Option","Command","NotionAPI","getBlockTitle","getCanonicalPageId","parsePageId","formatDate","getTextContent","getBlockParent","defaultMapImageUrl","getAllInSpace","getPageTitle","recursivePageTree","join","mkdir","readFile","JSONStream","fs","promisify","stream","format","isCollection","isSpace","writeFile","getBlockLink","blockId","recordMap","domain","NotionExporter","options","id","pageTree","pageMap","loadRaw","startPage","promises","table","filename","object","outputStream","transformStream","key","target","ext","path","markdown","md","attrs","attr","_a","_b","page","title","parentBlock","parent","properties","property","propName","propType","value","user","body","prefix","_c","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","numbering","child","childBlock","nesting","url","e","collection","views","children","view","results","result","childPage","aliasBlock","caption","nestedPrefix","decos","deco","wrapper","text","subdecos","textonly","subdeco","linkedBlock","objectid","decorated","line","message","block","collectionViewBlock","collectionId","viewId","response","sleepSync","_n","_o","_p","_q","_r","_s","collectionValue","collectionView","collectionViewValue","space","folder","notion_user","collection_view","collection_query","signed_urls","inputStream","parseStream","res","err","loadJson","ms","sharedBuffer","fs","promisify","writeFile","generateTreemaps","folder","pageTree","treemapDataPages","computeMetrics","titlePages","outputPathPages","generateTreemapHTML","treemapDataBlocks","titleBlocks","outputPathBlocks","metric","recurse","node","children","child","nodeValue","childrenValue","sum","data","title","outputPath","htmlContent","computeStats","pageTree","totalPages","totalBlocks","maxDepth","traverse","node","depth","child","writeStats","file","stats","NotionExportCommand","Command","Option","exporter","NotionExporter","tree","generateTreemaps","stats","computeStats","writeStats","cli","Cli","displayName","version","NotionExportCommand","Builtins"]}
1
+ {"version":3,"file":"main.js","sources":["../../src/notion/index.ts","../../src/treemap.ts","../../src/stats.ts","../../src/notion/export.ts","../../src/main.ts"],"sourcesContent":["import { NotionAPI } from '@texonom/nclient'\nimport {\n getBlockTitle,\n getCanonicalPageId,\n parsePageId,\n formatDate,\n getTextContent,\n getBlockParent,\n defaultMapImageUrl,\n getAllInSpace,\n getPageTitle,\n recursivePageTree\n} from '@texonom/nutils'\nimport { join } from 'path'\nimport { mkdir, readFile } from 'fs/promises'\nimport JSONStream from 'JSONStream'\nimport fs from 'graceful-fs'\nimport { promisify } from 'util'\nimport { execSync } from 'child_process'\nimport stream from 'stream'\nimport { format } from 'prettier'\nimport { isCollection, isSpace } from '@texonom/ntypes'\n\nimport type { PageTree } from '@texonom/nutils'\nimport type { ExtendedRecordMap, PageMap, PageBlock, Block, Decoration, CollectionViewBlock } from '@texonom/ntypes'\n\nlet writeFile = promisify(fs.writeFile)\n\nexport const getBlockLink = (blockId: string, recordMap: ExtendedRecordMap, domain = 'https://texonom.com') =>\n `${domain}/${getCanonicalPageId(blockId, recordMap)}`\n\nexport type Markdown = {\n [attre in string]: string\n}\n\nexport class NotionExporter {\n notion: NotionAPI\n recordMap: ExtendedRecordMap\n pageTree: PageTree\n pageMap: PageMap\n promises: Promise<unknown>[] = []\n\n // Options\n folder: string = 'texonom-raw'\n md: string = 'texonom-md'\n domain: string = 'https://texonom.com'\n validation: boolean = true\n update: boolean = false\n page: string\n recursive: boolean = false\n prefetch: boolean = false\n load: boolean = false\n raw: boolean = false\n dataset: boolean = false\n push: boolean = false\n debug: boolean = false\n wait: number = 5\n token: string | undefined\n\n constructor(options: {\n folder?: string\n validation?: boolean\n update?: boolean\n page: string\n recursive?: boolean\n prefetch?: boolean\n md?: string\n domain?: string\n load?: boolean\n raw?: boolean\n dataset?: boolean\n token?: string\n push?: boolean\n }) {\n this.page = parsePageId(options.page)\n this.folder = options.folder ?? this.folder\n this.domain = options.domain ?? this.domain\n this.md = options.md ?? this.md\n this.validation = options.validation ?? this.validation\n this.update = options.update ?? this.update\n this.recursive = options.recursive ?? this.recursive\n this.prefetch = options.prefetch ?? this.prefetch\n this.load = options.load ?? this.load\n this.raw = options.raw ?? this.raw\n this.dataset = options.dataset ?? this.dataset\n this.token = options.token\n this.push = options.push ?? this.push\n\n this.notion = new NotionAPI({ authToken: this.token })\n if (this.validation) writeFile = async () => {}\n }\n\n async execute() {\n const id = parsePageId(this.page)\n\n // Load\n if (this.load) {\n console.time('Load raw data')\n await this.loadRaw()\n console.timeEnd('Load raw data')\n }\n if (this.prefetch) {\n console.time('Fetch raw data')\n await this.fetchRawSpace(id)\n console.timeEnd('Fetch raw data')\n }\n\n // Save\n if (this.raw) {\n console.time('Export raw files')\n if (this.recursive) await this.saveRawSpace()\n else await this.saveRawPage(id)\n console.timeEnd('Export raw files')\n }\n // Export\n else {\n console.time('Extract markdown')\n await this.exportMd(id)\n console.timeEnd('Extract markdown')\n const pageTree = {\n id: this.page,\n title: getBlockTitle(this.recordMap.block[this.page].value, this.recordMap),\n blocks: 1,\n pages: 1,\n children: [],\n type: 'page'\n }\n recursivePageTree(this.recordMap, pageTree)\n this.pageTree = pageTree\n }\n await Promise.all(this.promises)\n // Update\n if (this.update)\n if (this.recursive) await this.saveRawSpace()\n else await this.saveRawPage(id)\n }\n\n async loadRaw() {\n const { recordMap, pageTree, pageMap } = await loadRaw(this.folder)\n this.recordMap = recordMap\n this.pageTree = pageTree\n this.pageMap = pageMap\n }\n\n async fetchRawSpace(startPage: string) {\n const { recordMap, pageTree, pageMap } = await getAllInSpace(\n startPage,\n this.notion.getPage.bind(this.notion),\n this.notion.getBlocks.bind(this.notion),\n this.notion.fetchCollections.bind(this.notion),\n {\n startRecordMap: this.recordMap,\n collectionConcurrency: 100,\n concurrency: 100,\n fetchOption: { timeout: 10000 },\n debug: this.debug\n }\n )\n this.pageMap = pageMap\n this.recordMap = recordMap\n this.pageTree = pageTree\n }\n\n async saveRawSpace() {\n if (this.validation) return\n await mkdir(this.folder, { recursive: true })\n const promises = []\n await mkdir(join(this.folder, 'recordMap'), { recursive: true })\n for (const table in this.recordMap) this.saveJson(join('recordMap', table), this.recordMap[table])\n this.saveJson('pageMap', this.pageMap)\n this.saveJson('pageTree', this.pageTree)\n await Promise.all(promises)\n }\n\n saveJson(filename: string, object: Record<string, unknown>) {\n if (this.validation) return\n const outputStream = fs.createWriteStream(`${join(this.folder, filename)}.json`)\n const transformStream = JSONStream.stringifyObject()\n transformStream.pipe(outputStream)\n // @ts-ignore\n for (const key in object) transformStream.write([key, object[key]])\n transformStream.end()\n }\n\n async saveRawPage(id: string) {\n if (this.validation) return\n await mkdir(this.folder, { recursive: true })\n const recordMap = await this.notion.getPage(id)\n const filename = `${getCanonicalPageId(id, recordMap)}`\n let target = JSON.stringify(recordMap)\n const ext = 'json'\n target = await format(target, { parser: 'json' })\n await this.writeFile(`${join(this.folder, filename)}.${ext}`, target)\n }\n\n async writeFile(path: string, target: string) {\n if (!this.folder) return\n else await writeFile(path, target)\n }\n\n async exportMd(id: string) {\n await mkdir(this.md, { recursive: true })\n try {\n let recordMap = this.pageMap && this.pageMap[id]\n if (!recordMap) {\n console.warn(`Missing from pageMap ${id}`)\n recordMap = await this.notion.getPage(id)\n }\n if (!this.recursive) this.recordMap = recordMap\n try {\n if (!recordMap) recordMap = await this.notion.getPage(id)\n } catch {\n return\n }\n if (!['page', 'collection_view_page'].includes(recordMap.block[id].value.type)) throw new Error('Not a page')\n const target = await this.pageToMarkdown(id, recordMap)\n if (!this.pageMap[id]) this.pageMap[id] = recordMap\n const path = join(this.md, `${getCanonicalPageId(id, recordMap)}`)\n this.promises.push(this.writeFile(`${path}.md`, target))\n } catch (e) {\n console.error(id, e)\n }\n }\n\n async pageToMarkdown(id: string, recordMap: ExtendedRecordMap) {\n const markdown = await this.pageToMarkdownObj(id, recordMap)\n let md = `---\\nTitle: ${markdown.title}\\n`\n md += `Parent: ${markdown.parent}\\n`\n const attrs = Object.keys(markdown).filter(key => !['title', 'parent', 'body'].includes(key))\n for (const attr of attrs) md += `${attr}: ${markdown[attr]}\\n`\n md += '---\\n'\n md += markdown.body\n return md\n }\n\n async pageToMarkdownObj(id: string, recordMap: ExtendedRecordMap) {\n const page = recordMap.block[id].value as PageBlock\n const markdown: Markdown = {}\n\n // Title\n const title = await this.decorationsToMarkdown(\n page.properties?.title ? page.properties.title : [['Untitled']],\n recordMap\n )\n markdown.title = title\n\n // Parent\n const parentBlock = getBlockParent(page, recordMap)\n let parent: string\n if (isSpace(parentBlock)) parent = parentBlock.name\n else if (isCollection(parentBlock)) parent = getTextContent(parentBlock.name)\n else if (parentBlock) parent = getBlockTitle(parentBlock, recordMap)\n\n // Collection Attributes\n if (isCollection(parent)) {\n const properties = parent?.schema ? Object.keys(parent.schema) : []\n properties.splice(properties.indexOf('title'), 1)\n for (const property of properties) {\n const propName = parent.schema[property].name\n const propType = parent.schema[property].type\n let value = String()\n switch (propType) {\n case 'text':\n value = page?.properties?.[property]\n ? await this.decorationsToMarkdown(page.properties[property], recordMap)\n : ''\n break\n case 'created_by': {\n const user = await this.getUser(page.created_by_id, recordMap)\n value = user ? user.name : 'Unknown'\n break\n }\n case 'last_edited_by': {\n const user = await this.getUser(page.last_edited_by_id, recordMap)\n value = user ? user.name : 'Unknown'\n break\n }\n case 'created_time':\n value = formatDate(page.created_time)\n break\n case 'last_edited_time':\n value = formatDate(page.last_edited_time)\n break\n default:\n value = ''\n }\n markdown[propName] = value\n }\n }\n const body = await this.childrenToMd(page, recordMap, '', page)\n markdown.body = body\n return markdown\n }\n\n async childrenToMd(parentBlock: Block, recordMap: ExtendedRecordMap, prefix: string, page: Block) {\n let md = String()\n let numbering = 1\n for (const child of parentBlock.content ? parentBlock.content : []) {\n const childBlock = await this.getBlock(child, recordMap, `${child} from ${getBlockTitle(page, recordMap)}`)\n if (!childBlock) continue\n\n const title = childBlock?.properties?.title\n switch (childBlock.type) {\n case 'header':\n md += `${prefix}# ${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'sub_header':\n md += `${prefix}## ${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'sub_sub_header':\n md += `${prefix}### ${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'text':\n md += `${prefix}${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'bulleted_list':\n md += `${prefix}- ${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'numbered_list':\n md += `${prefix}${numbering++}. ${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'to_do':\n md += `${prefix}- [ ] ${await this.decorationsToMarkdown(title, recordMap)}`\n break\n case 'toggle':\n md += `${prefix}<details><summary>${prefix}${prefix}${await this.decorationsToMarkdown(\n title,\n recordMap\n )}</summary>\\n`\n break\n case 'quote':\n md += (await this.decorationsToMarkdown(title, recordMap, `\\n${prefix.trim()}> `)) + '\\n'\n break\n case 'code':\n md += `${prefix}\\`\\`\\`type${await this.decorationsToMarkdown(title, recordMap)}\\`\\`\\``\n break\n case 'equation':\n md += `${prefix}$$${await this.decorationsToMarkdown(title, recordMap)}$$`\n break\n case 'callout': {\n md += (await this.decorationsToMarkdown(title, recordMap, `\\n${prefix.trim()}> `)) + '\\n'\n break\n }\n case 'bookmark': {\n const nesting = `\\n${prefix.trim()}> `\n md += `${nesting}[${getTextContent(\n childBlock.properties?.title ? childBlock.properties.title : [['Untitled']]\n )}](${getTextContent(childBlock.properties.link)})\\n`\n break\n }\n case 'external_object_instance': {\n try {\n const url = childBlock.format.original_url\n const title = childBlock.format.attributes\n ? childBlock.format.attributes.filter(attr => attr.id === 'title')[0]?.values?.[0]\n : url\n if (!url) break\n md += `${prefix}${prefix}[${title}](${url})${prefix}`\n break\n } catch (e) {\n console.error(e, childBlock.id)\n break\n }\n }\n\n // Collection\n case 'collection_view_page':\n case 'collection_view': {\n const collection = await this.getCollection(\n childBlock as CollectionViewBlock,\n recordMap,\n `${childBlock.id} from ${getPageTitle(recordMap)}`\n )\n if (!collection) continue\n\n // Generate Table\n md += `${prefix}### ${await this.decorationsToMarkdown(collection.name, recordMap)}`\n md += `${prefix}|Title|\\n|:-:|`\n const views = childBlock.view_ids\n .map(id => {\n if (!recordMap.collection_view[id]) if (this.debug) console.warn(`Missing view ${id} from ${collection.name}`)\n return recordMap.collection_view[id]?.value\n })\n .filter(Boolean)\n const children = []\n for (const view of views) {\n const results = await this.getCollectionView(\n collection.id,\n view.id,\n recordMap,\n `${collection.name} ${view.name}`\n )\n if (results) for (const result of results.blockIds) children.push(result)\n else break\n }\n for (const childPage of children) {\n const childBlock = recordMap.block[childPage]?.value\n if (!childBlock) if (this.debug) console.warn(`no ${childPage} in ${collection.name[0]}`)\n md += `${prefix}|[${getBlockTitle(childBlock, recordMap)}](${getBlockLink(childPage, recordMap)})|`\n }\n\n // Make children page\n if (this.recursive && children.length)\n for (const childPage of children) this.promises.push(this.exportMd(childPage))\n\n break\n }\n case 'page': {\n md += `${prefix}${prefix}[${getBlockTitle(childBlock, recordMap)}](${getBlockLink(\n childBlock.id,\n recordMap\n )})${prefix}`\n if (this.recursive) this.promises.push(this.exportMd(childBlock.id))\n\n break\n }\n case 'alias': {\n const aliasBlock = recordMap.block[childBlock.format?.alias_pointer?.id]?.value\n if (!aliasBlock) {\n if (this.debug)\n console.warn(\n `Missing alias ${childBlock.format?.alias_pointer?.id} from ${getBlockTitle(page, recordMap)} ${page.id}`\n )\n continue\n }\n md += `${prefix}${prefix}[${getBlockTitle(aliasBlock, recordMap)}](${getBlockLink(\n aliasBlock.id,\n recordMap\n )})${prefix}`\n break\n }\n\n // Media\n case 'image': {\n const caption = childBlock.properties.caption ? getTextContent(childBlock.properties.caption) : ''\n md += `${prefix}![${caption}](${defaultMapImageUrl(childBlock.format?.display_source, childBlock)})`\n break\n }\n\n case 'video':\n md += `${prefix}<video src=\"${childBlock.format.display_source} />`\n break\n\n // Embed\n case 'file':\n md += `${prefix}[File](${childBlock.format?.display_source})`\n break\n case 'pdf':\n md += `${prefix}<iframe src=\"${childBlock.format?.display_source}\"/>`\n break\n\n // Else\n case 'divider':\n md += `${prefix}---`\n break\n case 'column_list':\n break\n case 'column':\n break\n default:\n md += `${prefix}`\n }\n\n // Finalize\n if (childBlock.content && childBlock.type !== 'page' && childBlock.type !== 'collection_view_page') {\n const nestedPrefix = ['toggle', `transclusion_container`, `transclusion_reference`, 'column_list'].includes(\n childBlock.type\n )\n ? prefix\n : `\\n${prefix.trim()}> `\n md += await this.childrenToMd(childBlock, recordMap, nestedPrefix, page)\n if (childBlock.type === 'column') md += '\\n'\n }\n if (childBlock.type === 'toggle') md += `${prefix}</details>${prefix}`\n }\n return md\n }\n\n async decorationsToMarkdown(decos: Decoration[], recordMap: ExtendedRecordMap, prefix = '') {\n if (!decos) return String()\n let md = String()\n for (const deco of decos) {\n let wrapper = String()\n const [text, subdecos] = deco\n if (!subdecos) {\n md += text\n } else {\n let textonly: string = text\n for (const subdeco of subdecos)\n switch (subdeco[0]) {\n case 'p': {\n const blockId = subdeco[1]\n const linkedBlock = await this.getBlock(blockId, recordMap, `\"p\" ${getPageTitle(recordMap)}`)\n if (!linkedBlock) break\n\n const title = getBlockTitle(linkedBlock, recordMap)\n const url = getBlockLink(blockId, recordMap)\n textonly = `[${title}](${url})`\n break\n }\n case 'a': {\n const url = subdeco[1]\n textonly = `[${text}](${url})`\n break\n }\n case 'i':\n wrapper += '*'\n break\n case 'b':\n wrapper += '**'\n break\n case 'h':\n // Disable for now == syntax does not supported well\n wrapper += ''\n break\n case 'c':\n wrapper += '`'\n break\n case 's':\n wrapper += '~~'\n break\n case 'e':\n wrapper += '$'\n textonly = subdeco[1]\n break\n case 'eoi': {\n try {\n const objectid = subdeco[1]\n const object = await this.getBlock(objectid, recordMap, `\"eoi\" ${getPageTitle(recordMap)}`)\n if (!object) break\n const url = object.format.uri\n const title = object.format.attributes\n ? object.format.attributes?.filter(attr => attr.id === 'title')[0]?.values?.[0]\n : url\n if (!url) break\n textonly = `[${title}](${url})`\n break\n } catch (e) {\n console.error(e, deco)\n break\n }\n }\n case 'u': {\n const user = await this.getUser(subdeco[1], recordMap)\n if (!user) break\n textonly = `[@${user.name}](mailto:${user.email})`\n break\n }\n }\n let decorated: string = textonly\n if (subdecos.find(subdeco => subdeco[0] === '_')) decorated = `<u>${textonly}</u>`\n decorated = wrapper + decorated + wrapper.split('').reverse().join('')\n md += decorated\n }\n }\n const lines = md.split('\\n')\n const prefixed = lines.map(line => prefix + line)\n return prefixed.join('')\n }\n\n async getBlock(id: string, recordMap: ExtendedRecordMap, message = '') {\n let block = recordMap.block[id]?.value\n if (!block && this.recordMap) block = this.recordMap.block[id]?.value\n try {\n if (!block && this.token) {\n const notion = new NotionAPI({ authToken: this.token })\n const response = await notion.getBlocks([id])\n block = response.recordMap?.block?.[id]?.value\n }\n } catch {\n if (!block) if (this.debug) console.warn(`${message} Missing block ${id}`)\n }\n if (block) {\n recordMap.block[id] = { value: block, role: 'reader' }\n if (this.recordMap) this.recordMap.block[id] = { value: block, role: 'reader' }\n }\n return block\n }\n\n async getUser(id: string, recordMap: ExtendedRecordMap) {\n let user = recordMap.notion_user[id]?.value\n if (!user && this.recordMap) user = this.recordMap.notion_user[id]?.value\n try {\n if (!user && this.token) {\n const notion = new NotionAPI({ authToken: this.token })\n const response = await notion.getUsers([id])\n user = response.recordMapWithRoles?.notion_user?.[id]?.value\n }\n } catch {\n if (!user) if (this.debug) console.warn(`Missing user ${id}`)\n }\n if (user) {\n recordMap.notion_user[id] = { value: user, role: 'reader' }\n if (this.recordMap) this.recordMap.notion_user[id] = { value: user, role: 'reader' }\n }\n return user\n }\n\n async getCollection(collectionViewBlock: CollectionViewBlock, recordMap: ExtendedRecordMap, message = '') {\n const collectionId = collectionViewBlock.collection_id\n let collection = recordMap.collection[collectionViewBlock.collection_id]?.value\n if (!collection && this.recordMap) {\n collection = this.recordMap.collection[collectionId]?.value\n if (collection) {\n recordMap.collection[collectionId] = this.recordMap.collection?.[collectionId]\n for (const viewId of collectionViewBlock.view_ids)\n recordMap.collection_view[viewId] = this.recordMap.collection_view?.[viewId]\n }\n }\n try {\n if (!collection && this.token) {\n const notion = new NotionAPI({ authToken: this.token })\n const response = await notion.getPageRaw(collectionViewBlock.id)\n // @wait for rate limit\n sleepSync(1000 * this.wait)\n if (!response.recordMap) console.error(response)\n collection = response.recordMap.collection[collectionId]?.value\n if (collection) {\n recordMap.collection_view = { ...recordMap.collection_view, ...response.recordMap.collection_view }\n recordMap.collection = { ...recordMap.collection, ...response.recordMap.collection }\n recordMap.block = { ...recordMap.block, ...response.recordMap.block }\n this.recordMap.collection_view = { ...this.recordMap.collection_view, ...response.recordMap.collection_view }\n this.recordMap.collection = { ...this.recordMap.collection, ...response.recordMap.collection }\n this.recordMap.block = { ...this.recordMap.block, ...response.recordMap.block }\n }\n }\n } catch {\n if (!collection) if (this.debug) console.warn(`${message} Missing collection block ${collectionViewBlock.id}`)\n }\n await this.getCollectionView(collectionId, collectionViewBlock.view_ids[0], recordMap, message)\n return collection\n }\n\n async getCollectionView(collectionId: string, viewId: string, recordMap: ExtendedRecordMap, message = '') {\n let results = recordMap.collection_query?.[collectionId]?.[viewId]?.collection_group_results\n if (!results && this.recordMap) {\n results = this.recordMap.collection_query?.[collectionId]?.[viewId]?.collection_group_results\n if (results) {\n recordMap.collection_query![collectionId] = {\n ...recordMap.collection_query![collectionId],\n [viewId]: this.recordMap.collection_query?.[collectionId]?.[viewId]\n }\n this.recordMap.collection_query![collectionId] = {\n ...this.recordMap.collection_query![collectionId],\n [viewId]: this.recordMap.collection_query?.[collectionId]?.[viewId]\n }\n recordMap.collection![collectionId] = {\n ...recordMap.collection![collectionId],\n [viewId]: this.recordMap.collection?.[collectionId]?.[viewId]\n }\n this.recordMap.collection![collectionId] = {\n ...this.recordMap.collection![collectionId],\n [viewId]: this.recordMap.collection?.[collectionId]?.[viewId]\n }\n }\n }\n try {\n if (!results && this.token) {\n const notion = new NotionAPI({ authToken: this.token })\n const response = await notion.getCollectionData(collectionId, viewId, recordMap.collection_view[viewId]?.value)\n results = response.result?.reducerResults?.collection_group_results\n if (results) {\n recordMap.collection_query![collectionId] = {\n ...recordMap.collection_query![collectionId],\n [viewId]: response.result?.reducerResults\n }\n if (this.recordMap)\n this.recordMap.collection_query![collectionId] = {\n ...this.recordMap.collection_query![collectionId],\n [viewId]: response.result?.reducerResults\n }\n for (const blockId in response.recordMap.block) {\n const block = response.recordMap.block[blockId].value\n if (block) {\n recordMap.block[blockId] = { value: block, role: 'reader' }\n if (this.recordMap) this.recordMap.block[blockId] = { value: block, role: 'reader' }\n }\n }\n for (const collection in response.recordMap.collection) {\n const collectionValue = response.recordMap.collection[collection].value\n if (collectionValue) {\n recordMap.collection[collection] = { value: collectionValue, role: 'reader' }\n if (this.recordMap) this.recordMap.collection[collection] = { value: collectionValue, role: 'reader' }\n }\n }\n for (const collectionView in response.recordMap.collection_view) {\n const collectionViewValue = response.recordMap.collection_view[collectionView].value\n if (collectionViewValue) {\n recordMap.collection_view[collectionView] = { value: collectionViewValue, role: 'reader' }\n if (this.recordMap)\n this.recordMap.collection_view[collectionView] = { value: collectionViewValue, role: 'reader' }\n }\n }\n }\n }\n } catch {\n if (!results) if (this.debug) console.warn(`${message} Missing collection view ${viewId}`)\n }\n return results\n }\n\n async getSpace(id: string, recordMap: ExtendedRecordMap) {\n let space = recordMap.space[id]?.value\n if (!space && this.recordMap) space = this.recordMap.space[id]?.value\n try {\n if (!space && this.token) {\n const notion = new NotionAPI({ authToken: this.token })\n const response = await notion.getSpaces([id])\n space = response.recordMapWithRoles?.space?.[id]?.value\n if (space) {\n recordMap.space[id] = { value: space, role: 'reader' }\n if (this.recordMap) this.recordMap.space[id] = { value: space, role: 'reader' }\n }\n }\n } catch {\n if (!space) if (this.debug) console.warn(`Missing space ${id}`)\n }\n return space\n }\n\n pushRepos() {\n const run = (cmd: string, cwd: string) => {\n try {\n execSync(cmd, { cwd, stdio: 'ignore' })\n } catch {\n // Ignore errors - some commands may fail (e.g., remote already exists)\n }\n }\n const message = new Date().toString()\n\n // push raw\n run('git init', this.folder)\n run('git add .', this.folder)\n run(`git commit -m \"${message}\"`, this.folder)\n run('git branch -M main', this.folder)\n run('git remote add origin https://github.com/texonom/texonom-raw.git', this.folder)\n run('git push -u origin main --force', this.folder)\n\n // push md\n run('git init', this.md)\n run('git add .', this.md)\n run(`git commit -m \"${message}\"`, this.md)\n run('git branch -M main', this.md)\n run('git remote add origin https://github.com/texonom/texonom-md.git', this.md)\n run('git push -u origin main --force', this.md)\n }\n}\n\nexport async function loadRaw(\n folder: string\n): Promise<{ recordMap: ExtendedRecordMap; pageTree: PageTree; pageMap: PageMap }> {\n const promises = []\n promises.push(readFile(join(folder, 'recordMap', 'block.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'recordMap', 'collection.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'recordMap', 'notion_user.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'recordMap', 'space.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'recordMap', 'collection_view.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'recordMap', 'collection_query.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'recordMap', 'signed_urls.json'), 'utf8').then(JSON.parse))\n promises.push(readFile(join(folder, 'pageTree.json'), 'utf8').then(JSON.parse))\n\n const [block, collection, notion_user, space, collection_view, collection_query, signed_urls, pageTree] =\n await Promise.all(promises)\n\n const pageMap = {}\n const inputStream = fs.createReadStream(join(folder, 'pageMap.json'))\n const parseStream = JSONStream.parse('*')\n inputStream.pipe(parseStream)\n parseStream.on('data', (recordMap: ExtendedRecordMap) => {\n const key = Object.keys(recordMap.block)[0]\n pageMap[key] = recordMap\n })\n await new Promise(res => stream.finished(parseStream, err => res(err)))\n const recordMap: ExtendedRecordMap = {\n block,\n collection,\n notion_user,\n space,\n collection_query,\n collection_view,\n signed_urls\n }\n return { recordMap, pageTree, pageMap }\n}\n\nexport async function loadJson<C>(folder: string, filename: string): Promise<C> {\n const object = {} as C\n const inputStream = fs.createReadStream(join(folder, `${filename}.json`))\n const parseStream = JSONStream.parse('*')\n inputStream.pipe(parseStream)\n parseStream.on('*', ([key, value]) => {\n object[key] = value\n })\n return new Promise(res =>\n stream.finished(parseStream, err => {\n console.error(err)\n res(object)\n })\n )\n}\n\nconst sleepSync = (ms: number) => {\n const sharedBuffer = new Int32Array(new SharedArrayBuffer(4))\n Atomics.wait(sharedBuffer, 0, 0, ms)\n}\n","import fs from 'fs'\nimport { promisify } from 'util'\n\nexport interface PageNode {\n id: string\n blocks: number\n pages: number\n title: string\n children?: PageNode[]\n}\n\nconst writeFile = promisify(fs.writeFile)\n\nexport async function generateTreemaps(folder: string, pageTree: PageNode) {\n const treemapDataPages = computeMetrics(pageTree, 'pages')\n const titlePages = 'Texonom PageTree'\n const outputPathPages = `${folder}/pagetree.html`\n await generateTreemapHTML(treemapDataPages, titlePages, outputPathPages)\n\n const treemapDataBlocks = computeMetrics(pageTree, 'blocks')\n const titleBlocks = 'Texonom BlockMap'\n const outputPathBlocks = `${folder}/blocktree.html`\n await generateTreemapHTML(treemapDataBlocks, titleBlocks, outputPathBlocks)\n}\n\ninterface TreemapNode {\n id: string\n name: string\n value: number\n children?: TreemapNode[]\n}\n\nfunction computeMetrics(pageTree: PageNode, metric: 'blocks' | 'pages'): TreemapNode | null {\n function recurse(node: PageNode): TreemapNode | null {\n const children = node.children ? node.children.map(recurse).filter((child): child is TreemapNode => child !== null) : []\n let nodeValue = node[metric] || 0\n\n // Sum the values of the children\n if (children.length > 0) {\n const childrenValue = children.reduce((sum, child) => sum + child.value, 0)\n if (nodeValue === 0) nodeValue = childrenValue\n }\n\n // Exclude nodes with zero value\n if (nodeValue <= 0) return null\n\n return {\n id: node.id,\n name: node.title,\n value: nodeValue,\n children: children.length > 0 ? children : undefined\n }\n }\n return recurse(pageTree)\n}\n\nasync function generateTreemapHTML(data: TreemapNode, title: string, outputPath: string) {\n const htmlContent = `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<title>${title}</title>\n<style>\n body {\n margin: 0;\n font-family: sans-serif;\n background-color: #202229;\n }\n .header {\n text-align: center;\n margin: 20px;\n font-size: 24px;\n color: white;\n }\n .breadcrumb {\n text-align: center;\n margin: 10px;\n font-size: 16px;\n color: white;\n }\n .current-title {\n text-align: center;\n margin: 10px;\n font-size: 18px;\n color: white;\n }\n .chart {\n width: 100%;\n height: 70vh;\n margin: auto;\n position: relative;\n }\n .node rect {\n cursor: pointer;\n stroke: #fff;\n stroke-width: 1px;\n rx: 8;\n ry: 8;\n }\n .label {\n text-anchor: middle;\n fill: white;\n text-decoration: underline;\n cursor: pointer;\n }\n .count {\n text-anchor: middle;\n fill: lightgray;\n }\n</style>\n</head>\n<body>\n<div class=\"header\">${title}</div>\n<div class=\"breadcrumb\" id=\"breadcrumb\"></div>\n<div class=\"current-title\" id=\"current-title\"></div>\n<div class=\"chart\" id=\"chart\"></div>\n<script src=\"https://d3js.org/d3.v6.min.js\"></script>\n<script>\n var data = ${JSON.stringify(data)};\n\n var margin = {top: 20, right: 0, bottom: 0, left: 0},\n width = document.getElementById('chart').clientWidth,\n height = document.getElementById('chart').clientHeight;\n\n var color = d3.scaleOrdinal()\n .domain([0, 1, 2, 3, 4, 5])\n .range([\"#465881\", \"#5f6d96\", \"#7882ab\", \"#9197c0\"]);\n\n var x = d3.scaleLinear()\n .domain([0, width])\n .range([0, width]);\n\n var y = d3.scaleLinear()\n .domain([0, height])\n .range([0, height]);\n\n var treemapLayout = d3.treemap()\n .size([width, height])\n .paddingInner(2)\n .round(false);\n\n var root = d3.hierarchy(data)\n .sum(function(d) { return d.value; })\n .sort(function(a, b) { return b.value - a.value; });\n\n treemapLayout(root);\n\n var svg = d3.select(\"#chart\").append(\"svg\")\n .attr(\"width\", width)\n .attr(\"height\", height)\n .style(\"font\", \"10px sans-serif\")\n .style(\"position\", \"relative\");\n\n display(root);\n\n function display(d) {\n var currentDepth = d.depth;\n\n // Update breadcrumb\n var breadcrumb = d.ancestors().reverse().map(function(d) {\n return '<span class=\"breadcrumb-item\" data-id=\"' + d.data.id + '\">' + d.data.name + '</span>';\n }).join(' / ');\n document.getElementById('breadcrumb').innerHTML = breadcrumb;\n\n // Add click events to breadcrumb\n var breadcrumbItems = document.querySelectorAll('.breadcrumb-item');\n breadcrumbItems.forEach(function(item) {\n item.addEventListener('click', function(event) {\n var id = event.target.getAttribute('data-id');\n var node = findNodeById(root, id);\n if (node) {\n zoom(node);\n }\n });\n });\n\n // Update current title\n document.getElementById('current-title').innerText = d.data.name;\n\n x.domain([d.x0, d.x1]);\n y.domain([d.y0, d.y1]);\n\n var nodes = d.descendants().filter(function(node) {\n return node.depth - currentDepth <= 1 && node.depth >= currentDepth;\n });\n\n svg.selectAll(\".node\").remove();\n\n var cell = svg.selectAll(\".node\")\n .data(nodes)\n .enter().append(\"g\")\n .attr(\"class\", \"node\")\n .attr(\"transform\", function(d) { return \"translate(\" + x(d.x0) + \",\" + y(d.y0) + \")\"; })\n .on(\"click\", function(event, d) {\n if (d.children) {\n zoom(d);\n } else {\n window.open('https://texonom.com/' + d.data.id, '_blank');\n }\n event.stopPropagation();\n });\n\n cell.append(\"rect\")\n .attr(\"id\", function(d) { return d.data.id; })\n .attr(\"width\", function(d) { return x(d.x1) - x(d.x0); })\n .attr(\"height\", function(d) { return y(d.y1) - y(d.y0); })\n .attr(\"fill\", function(d) { return color(d.depth); })\n .attr(\"rx\", 8)\n .attr(\"ry\", 8);\n\n cell.append(\"text\")\n .attr(\"class\", \"label\")\n .attr(\"x\", function(d) { return (x(d.x1) - x(d.x0)) / 2; })\n .attr(\"y\", function(d) { return (y(d.y1) - y(d.y0)) / 2; })\n .text(function(d) { return d.data.name; })\n .style(\"font-size\", function(d) {\n var boxArea = (x(d.x1) - x(d.x0)) * (y(d.y1) - y(d.y0));\n var size = Math.max(10, Math.min(30, Math.sqrt(boxArea) / 5));\n return size + \"px\";\n })\n .on(\"click\", function(event, d) {\n window.open('https://texonom.com/' + d.data.id, '_blank');\n event.stopPropagation();\n });\n\n cell.append(\"text\")\n .attr(\"class\", \"count\")\n .attr(\"x\", function(d) { return (x(d.x1) - x(d.x0)) / 2; })\n .attr(\"y\", function(d) { return (y(d.y1) - y(d.y0)) / 2 + 20; })\n .text(function(d) { return d.data.value; })\n .style(\"fill\", \"lightgray\")\n .style(\"font-size\", \"0.8rem\");\n }\n\n function zoom(d) {\n var currentDepth = d.depth;\n\n // Update breadcrumb\n var breadcrumb = d.ancestors().reverse().map(function(d) {\n return '<span class=\"breadcrumb-item\" data-id=\"' + d.data.id + '\">' + d.data.name + '</span>';\n }).join(' / ');\n document.getElementById('breadcrumb').innerHTML = breadcrumb;\n\n // Add click events to breadcrumb\n var breadcrumbItems = document.querySelectorAll('.breadcrumb-item');\n breadcrumbItems.forEach(function(item) {\n item.addEventListener('click', function(event) {\n var id = event.target.getAttribute('data-id');\n var node = findNodeById(root, id);\n if (node) {\n zoom(node);\n }\n });\n });\n\n // Update current title\n document.getElementById('current-title').innerText = d.data.name;\n\n var t = svg.transition()\n .duration(750);\n\n x.domain([d.x0, d.x1]);\n y.domain([d.y0, d.y1]);\n\n var nodes = d.descendants().filter(function(node) {\n return node.depth - currentDepth <= 1 && node.depth >= currentDepth;\n });\n\n var cell = svg.selectAll(\".node\")\n .data(nodes, function(d) { return d.data.id; });\n\n cell.exit().remove();\n\n var cellEnter = cell.enter().append(\"g\")\n .attr(\"class\", \"node\")\n .on(\"click\", function(event, d) {\n if (d.children) {\n zoom(d);\n } else {\n window.open('https://texonom.com/' + d.data.id, '_blank');\n }\n event.stopPropagation();\n });\n\n cellEnter.append(\"rect\")\n .attr(\"id\", function(d) { return d.data.id; })\n .attr(\"fill\", function(d) { return color(d.depth); })\n .attr(\"rx\", 8)\n .attr(\"ry\", 8);\n\n cellEnter.append(\"text\")\n .attr(\"class\", \"label\")\n .style(\"fill\", \"white\")\n .on(\"click\", function(event, d) {\n window.open('https://texonom.com/' + d.data.id, '_blank');\n event.stopPropagation();\n });\n\n cellEnter.append(\"text\")\n .attr(\"class\", \"count\")\n .style(\"fill\", \"lightgray\")\n .style(\"font-size\", \"0.8rem\");\n\n cell = cellEnter.merge(cell);\n\n cell.transition(t)\n .attr(\"transform\", function(d) { return \"translate(\" + x(d.x0) + \",\" + y(d.y0) + \")\"; });\n\n cell.select(\"rect\").transition(t)\n .attr(\"width\", function(d) { return x(d.x1) - x(d.x0); })\n .attr(\"height\", function(d) { return y(d.y1) - y(d.y0); });\n\n cell.select(\".label\").transition(t)\n .attr(\"x\", function(d) { return (x(d.x1) - x(d.x0)) / 2; })\n .attr(\"y\", function(d) { return (y(d.y1) - y(d.y0)) / 2; })\n .text(function(d) { return d.data.name; })\n .style(\"font-size\", function(d) {\n var boxArea = (x(d.x1) - x(d.x0)) * (y(d.y1) - y(d.y0));\n var size = Math.max(10, Math.min(30, Math.sqrt(boxArea) / 5));\n return size + \"px\";\n });\n\n cell.select(\".count\").transition(t)\n .attr(\"x\", function(d) { return (x(d.x1) - x(d.x0)) / 2; })\n .attr(\"y\", function(d) { return (y(d.y1) - y(d.y0)) / 2 + 20; })\n .text(function(d) { return d.data.value; });\n }\n\n function findNodeById(node, id) {\n if (node.data.id === id) {\n return node;\n }\n if (node.children) {\n for (var child of node.children) {\n var result = findNodeById(child, id);\n if (result) return result;\n }\n }\n return null;\n }\n</script>\n</body>\n</html>\n `\n\n await writeFile(outputPath, htmlContent, 'utf8')\n}\n","import type { PageNode } from './treemap'\n\nexport interface ExportStats {\n totalPages: number\n totalBlocks: number\n maxDepth: number\n}\n\nexport function computeStats(pageTree: PageNode): ExportStats {\n let totalPages = 0\n let totalBlocks = 0\n let maxDepth = 0\n\n function traverse(node: PageNode, depth: number) {\n totalPages += node.pages || 0\n totalBlocks += node.blocks || 0\n if (depth > maxDepth) maxDepth = depth\n if (node.children) for (const child of node.children) traverse(child, depth + 1)\n }\n\n traverse(pageTree, 1)\n return { totalPages, totalBlocks, maxDepth }\n}\n\nexport async function writeStats(file: string, stats: ExportStats) {\n const fs = await import('fs/promises')\n await fs.writeFile(file, JSON.stringify(stats, null, 2), 'utf8')\n}\n","import { Option, Command } from 'clipanion'\nimport { NotionExporter } from './index'\nimport { generateTreemaps, PageNode } from '../treemap'\nimport { computeStats, writeStats } from '../stats'\n\nexport class NotionExportCommand extends Command {\n static paths = [['export']]\n\n folder = Option.String('-o,--output', 'texonom-raw', {\n description: 'Target root folder to export folder'\n })\n md = Option.String('-m,--md', 'texonom-md', {\n description: 'Target folder to export markdown'\n })\n domain = Option.String('-d,--domain', 'https://texonom.com', {\n description: 'Domain to fill in the link'\n })\n validation = Option.Boolean('-v,--validation', {\n description: 'Validation exported data only'\n })\n update = Option.Boolean('-u,--update', {\n description: 'Update exported data and resave to the --root'\n })\n page = Option.String('-p,--page', {\n required: true,\n description: 'Target page to export'\n })\n recursive = Option.Boolean('-r,--recursive', {\n description: 'Recursively export children'\n })\n prefetch = Option.Boolean('-f, --prefetch', {\n description: 'Prefetch all space for faster export (recommended for exporting all pages in a space)'\n })\n load = Option.Boolean('-l, --load', {\n description: 'Load data from exported cache folder --root'\n })\n raw = Option.Boolean('--raw', {\n description: 'Export raw recordMap JSON data \\n Markdown format do not preserve all information'\n })\n dataset = Option.Boolean('-d, --dataset', {\n description: 'Export as dataset for LLM learning'\n })\n treemap = Option.Boolean('--treemap', {\n description: 'Generate HTML treemap after export'\n })\n stats = Option.Boolean('--stats', {\n description: 'Generate statistics JSON after export'\n })\n token = Option.String('-t,--token', {\n description: 'Notion Access Token'\n })\n wait = Option.Counter('-w,--wait', {\n description: 'Wait couter for missed collection view'\n })\n push = Option.Boolean('--push', {\n description: 'Push exported data to remote repositories'\n })\n\n async execute() {\n const exporter = new NotionExporter({\n folder: this.folder,\n validation: this.validation,\n update: this.update,\n page: this.page,\n recursive: this.recursive,\n prefetch: this.prefetch,\n load: this.load,\n raw: this.raw,\n dataset: this.dataset,\n token: this.token,\n push: this.push\n })\n await exporter.execute()\n if (this.push) await exporter.pushRepos()\n\n if (this.treemap || this.stats) if (!exporter.pageTree) await exporter.loadRaw()\n\n const tree = exporter.pageTree as unknown as PageNode\n if (this.treemap && tree) await generateTreemaps(this.folder, tree)\n\n if (this.stats && tree) {\n const stats = computeStats(tree)\n await writeStats(`${this.folder}/stats.json`, stats)\n }\n }\n}\n","import { Cli, Builtins } from 'clipanion'\n\nimport { version, displayName } from '../package.json'\nimport { NotionExportCommand } from './notion/export'\n\nconst cli = new Cli({\n binaryName: 'notion',\n binaryLabel: displayName,\n binaryVersion: version\n})\n\ncli.register(NotionExportCommand)\ncli.register(Builtins.HelpCommand)\ncli.register(Builtins.VersionCommand)\ncli.runExit(process.argv.slice(2), Cli.defaultContext)\n\nexport * from './notion/export'\nexport * from './notion/index'\nexport * from './treemap'\nexport * from './stats'\n"],"names":["writeFile","promisify","fs","getBlockLink","blockId","recordMap","domain","getCanonicalPageId","NotionExporter","options","parsePageId","NotionAPI","id","pageTree","getBlockTitle","recursivePageTree","pageMap","loadRaw","startPage","getAllInSpace","mkdir","promises","join","table","filename","object","outputStream","transformStream","JSONStream","key","target","ext","format","path","markdown","md","attrs","attr","page","title","_a","parentBlock","getBlockParent","parent","isSpace","isCollection","getTextContent","properties","property","propName","propType","value","_b","user","formatDate","body","prefix","numbering","child","childBlock","nesting","url","_d","_c","e","collection","getPageTitle","views","children","view","results","result","childPage","_e","aliasBlock","_h","_g","_f","_j","_i","caption","defaultMapImageUrl","_k","_l","_m","nestedPrefix","decos","deco","wrapper","text","subdecos","textonly","subdeco","linkedBlock","objectid","decorated","line","message","block","collectionViewBlock","collectionId","viewId","response","sleepSync","_n","_o","_q","_p","_r","_s","collectionValue","collectionView","collectionViewValue","space","run","cmd","cwd","execSync","folder","readFile","notion_user","collection_view","collection_query","signed_urls","inputStream","parseStream","res","stream","err","loadJson","ms","sharedBuffer","generateTreemaps","treemapDataPages","computeMetrics","titlePages","outputPathPages","generateTreemapHTML","treemapDataBlocks","titleBlocks","outputPathBlocks","metric","recurse","node","nodeValue","childrenValue","sum","data","outputPath","htmlContent","computeStats","totalPages","totalBlocks","maxDepth","traverse","depth","writeStats","file","stats","_NotionExportCommand","Command","Option","exporter","tree","NotionExportCommand","cli","Cli","displayName","version","Builtins"],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAmDQA,CAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAMZ,KAAK,UAAU4G,CAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmOjC,QAAMnJ,GAAUoJ,GAAYC,GAAa,MAAM;AACjD;ACnVO,SAASC,GAAazI,GAAiC;AAC5D,MAAI0I,IAAa,GACbC,IAAc,GACdC,IAAW;AAEf,WAASC,EAASX,GAAgBY,GAAe;AAI/C,QAHAJ,KAAcR,EAAK,SAAS,GAC5BS,KAAeT,EAAK,UAAU,GAC1BY,IAAQF,MAAUA,IAAWE,IAC7BZ,EAAK,SAAU,YAAWrF,KAASqF,EAAK,SAAU,CAAAW,EAAShG,GAAOiG,IAAQ,CAAC;AAAA,EACjF;AAEA,SAAAD,EAAS7I,GAAU,CAAC,GACb,EAAE,YAAA0I,GAAY,aAAAC,GAAa,UAAAC,EAAA;AACpC;AAEA,eAAsBG,GAAWC,GAAcC,GAAoB;AAEjE,SADW,MAAM,OAAO,aAAa,GAC5B,UAAUD,GAAM,KAAK,UAAUC,GAAO,MAAM,CAAC,GAAG,MAAM;AACjE;ACtBO,MAAMC,IAAN,MAAMA,UAA4BC,GAAQ;AAAA,EAA1C,cAAA;AAAA,UAAA,GAAA,SAAA,GAGL,KAAA,SAASC,EAAO,OAAO,eAAe,eAAe;AAAA,MACnD,aAAa;AAAA,IAAA,CACd,GACD,KAAA,KAAKA,EAAO,OAAO,WAAW,cAAc;AAAA,MAC1C,aAAa;AAAA,IAAA,CACd,GACD,KAAA,SAASA,EAAO,OAAO,eAAe,uBAAuB;AAAA,MAC3D,aAAa;AAAA,IAAA,CACd,GACD,KAAA,aAAaA,EAAO,QAAQ,mBAAmB;AAAA,MAC7C,aAAa;AAAA,IAAA,CACd,GACD,KAAA,SAASA,EAAO,QAAQ,eAAe;AAAA,MACrC,aAAa;AAAA,IAAA,CACd,GACD,KAAA,OAAOA,EAAO,OAAO,aAAa;AAAA,MAChC,UAAU;AAAA,MACV,aAAa;AAAA,IAAA,CACd,GACD,KAAA,YAAYA,EAAO,QAAQ,kBAAkB;AAAA,MAC3C,aAAa;AAAA,IAAA,CACd,GACD,KAAA,WAAWA,EAAO,QAAQ,kBAAkB;AAAA,MAC1C,aAAa;AAAA,IAAA,CACd,GACD,KAAA,OAAOA,EAAO,QAAQ,cAAc;AAAA,MAClC,aAAa;AAAA,IAAA,CACd,GACD,KAAA,MAAMA,EAAO,QAAQ,SAAS;AAAA,MAC5B,aAAa;AAAA;AAAA,IAAA,CACd,GACD,KAAA,UAAUA,EAAO,QAAQ,iBAAiB;AAAA,MACxC,aAAa;AAAA,IAAA,CACd,GACD,KAAA,UAAUA,EAAO,QAAQ,aAAa;AAAA,MACpC,aAAa;AAAA,IAAA,CACd,GACD,KAAA,QAAQA,EAAO,QAAQ,WAAW;AAAA,MAChC,aAAa;AAAA,IAAA,CACd,GACD,KAAA,QAAQA,EAAO,OAAO,cAAc;AAAA,MAClC,aAAa;AAAA,IAAA,CACd,GACD,KAAA,OAAOA,EAAO,QAAQ,aAAa;AAAA,MACjC,aAAa;AAAA,IAAA,CACd,GACD,KAAA,OAAOA,EAAO,QAAQ,UAAU;AAAA,MAC9B,aAAa;AAAA,IAAA,CACd;AAAA,EAAA;AAAA,EAED,MAAM,UAAU;AACd,UAAMC,IAAW,IAAI1J,GAAe;AAAA,MAClC,QAAQ,KAAK;AAAA,MACb,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,WAAW,KAAK;AAAA,MAChB,UAAU,KAAK;AAAA,MACf,MAAM,KAAK;AAAA,MACX,KAAK,KAAK;AAAA,MACV,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,MAAM,KAAK;AAAA,IAAA,CACZ;AACD,UAAM0J,EAAS,QAAA,GACX,KAAK,QAAM,MAAMA,EAAS,UAAA,IAE1B,KAAK,WAAW,KAAK,WAAYA,EAAS,YAAU,MAAMA,EAAS,QAAA;AAEvE,UAAMC,IAAOD,EAAS;AAGtB,QAFI,KAAK,WAAWC,WAAY/B,GAAiB,KAAK,QAAQ+B,CAAI,GAE9D,KAAK,SAASA,GAAM;AACtB,YAAML,IAAQR,GAAaa,CAAI;AAC/B,YAAMP,GAAW,GAAG,KAAK,MAAM,eAAeE,CAAK;AAAA,IACrD;AAAA,EACF;AACF;AA/EEC,EAAO,QAAQ,CAAC,CAAC,QAAQ,CAAC;AADrB,IAAMK,IAANL;ACAP,MAAMM,IAAM,IAAIC,EAAI;AAAA,EAClB,YAAY;AAAA,EACZ,aAAaC;AAAA,EACb,eAAeC;AACjB,CAAC;AAEDH,EAAI,SAASD,CAAmB;AAChCC,EAAI,SAASI,EAAS,WAAW;AACjCJ,EAAI,SAASI,EAAS,cAAc;AACpCJ,EAAI,QAAQ,QAAQ,KAAK,MAAM,CAAC,GAAGC,EAAI,cAAc;"}
@@ -0,0 +1,5 @@
1
+ export * from './notion/export';
2
+ export * from './notion/index';
3
+ export * from './treemap';
4
+ export * from './stats';
5
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/main.ts"],"names":[],"mappings":"AAgBA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,SAAS,CAAA"}
@@ -16,6 +16,7 @@ export declare class NotionExportCommand extends Command {
16
16
  stats: boolean;
17
17
  token: string;
18
18
  wait: number;
19
+ push: boolean;
19
20
  execute(): Promise<void>;
20
21
  }
21
22
  //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../../src/notion/export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,OAAO,EAAE,MAAM,WAAW,CAAA;AAK3C,qBAAa,mBAAoB,SAAQ,OAAO;IAC9C,MAAM,CAAC,KAAK,aAAe;IAE3B,MAAM,SAEJ;IACF,EAAE,SAEA;IACF,MAAM,SAEJ;IACF,UAAU,UAER;IACF,MAAM,UAEJ;IACF,IAAI,SAGF;IACF,SAAS,UAEP;IACF,QAAQ,UAEN;IACF,IAAI,UAEF;IACF,GAAG,UAED;IACF,OAAO,UAEL;IACF,OAAO,UAEL;IACF,KAAK,UAEH;IACF,KAAK,SAEH;IACF,IAAI,SAEF;IACF,IAAI,UAEF;IAEI,OAAO;CA2Bd"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.test.d.ts","sourceRoot":"","sources":["../../../../src/notion/export.test.ts"],"names":[],"mappings":""}
@@ -1,6 +1,6 @@
1
1
  import { NotionAPI } from '@texonom/nclient';
2
- import type { PageTree } from '@texonom/nutils';
3
- import type { ExtendedRecordMap, PageMap, Block, Decoration, CollectionViewBlock } from '@texonom/ntypes';
2
+ import { PageTree } from '@texonom/nutils';
3
+ import { ExtendedRecordMap, PageMap, Block, Decoration, CollectionViewBlock } from '@texonom/ntypes';
4
4
  export declare const getBlockLink: (blockId: string, recordMap: ExtendedRecordMap, domain?: string) => string;
5
5
  export type Markdown = {
6
6
  [attre in string]: string;
@@ -22,6 +22,7 @@ export declare class NotionExporter {
22
22
  load: boolean;
23
23
  raw: boolean;
24
24
  dataset: boolean;
25
+ push: boolean;
25
26
  debug: boolean;
26
27
  wait: number;
27
28
  token: string | undefined;
@@ -38,6 +39,7 @@ export declare class NotionExporter {
38
39
  raw?: boolean;
39
40
  dataset?: boolean;
40
41
  token?: string;
42
+ push?: boolean;
41
43
  });
42
44
  execute(): Promise<void>;
43
45
  loadRaw(): Promise<void>;
@@ -52,14 +54,15 @@ export declare class NotionExporter {
52
54
  childrenToMd(parentBlock: Block, recordMap: ExtendedRecordMap, prefix: string, page: Block): Promise<string>;
53
55
  decorationsToMarkdown(decos: Decoration[], recordMap: ExtendedRecordMap, prefix?: string): Promise<string>;
54
56
  getBlock(id: string, recordMap: ExtendedRecordMap, message?: string): Promise<Block>;
55
- getUser(id: string, recordMap: ExtendedRecordMap): Promise<import("@texonom/ntypes").User>;
56
- getCollection(collectionViewBlock: CollectionViewBlock, recordMap: ExtendedRecordMap, message?: string): Promise<import("@texonom/ntypes").Collection>;
57
+ getUser(id: string, recordMap: ExtendedRecordMap): Promise<import('@texonom/ntypes').User>;
58
+ getCollection(collectionViewBlock: CollectionViewBlock, recordMap: ExtendedRecordMap, message?: string): Promise<import('@texonom/ntypes').Collection>;
57
59
  getCollectionView(collectionId: string, viewId: string, recordMap: ExtendedRecordMap, message?: string): Promise<{
58
60
  type: string;
59
- blockIds: import("@texonom/ntypes").ID[];
61
+ blockIds: import('@texonom/ntypes').ID[];
60
62
  hasMore: boolean;
61
63
  }>;
62
- getSpace(id: string, recordMap: ExtendedRecordMap): Promise<import("@texonom/ntypes").Space>;
64
+ getSpace(id: string, recordMap: ExtendedRecordMap): Promise<import('@texonom/ntypes').Space>;
65
+ pushRepos(): void;
63
66
  }
64
67
  export declare function loadRaw(folder: string): Promise<{
65
68
  recordMap: ExtendedRecordMap;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/notion/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { PageNode } from './treemap';
1
+ import { PageNode } from './treemap';
2
2
  export interface ExportStats {
3
3
  totalPages: number;
4
4
  totalBlocks: number;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../../src/stats.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEzC,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,WAAW,CAc5D;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,iBAGhE"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"treemap.d.ts","sourceRoot":"","sources":["../../../src/treemap.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAA;CACtB;AAID,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,iBAUxE"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,MAAM,CAAA"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@texonom/cli",
3
3
  "displayName": "Notion CLI",
4
- "version": "1.4.7",
4
+ "version": "1.5.0",
5
5
  "type": "module",
6
6
  "description": "Texonom CLI which has ability to export data from Notion.so",
7
7
  "repository": "texonom/notion-node",
@@ -15,7 +15,7 @@
15
15
  "build"
16
16
  ],
17
17
  "engines": {
18
- "node": ">=22.16.0"
18
+ "node": ">=22.22.0"
19
19
  },
20
20
  "bin": {
21
21
  "notion": "./build/src/main.js"
@@ -24,10 +24,10 @@
24
24
  "JSONStream": "^1.3.5",
25
25
  "clipanion": "^3.2.1",
26
26
  "graceful-fs": "^4.2.11",
27
- "prettier": "^3.5.3",
28
- "@texonom/nclient": "^1.4.7",
29
- "@texonom/ntypes": "^1.4.7",
30
- "@texonom/nutils": "^1.4.7"
27
+ "prettier": "^3.8.1",
28
+ "@texonom/nclient": "^1.5.0",
29
+ "@texonom/ntypes": "^1.5.0",
30
+ "@texonom/nutils": "^1.5.0"
31
31
  },
32
32
  "standard-version": {
33
33
  "skip": {
@@ -40,8 +40,8 @@
40
40
  "@types/jsonstream": "^0.8.33"
41
41
  },
42
42
  "scripts": {
43
- "build": "tsc && tsup",
44
- "watch": "tsup --watch --silent --onSuccess 'echo build successful'",
43
+ "build": "tsc && vite build",
44
+ "watch": "vite build --watch --mode development",
45
45
  "test": "vitest --run",
46
46
  "prerelease": "standard-version --skip.changelog --prerelease",
47
47
  "release": "standard-version --release-as",
package/readme.md CHANGED
@@ -1,25 +1,31 @@
1
1
  # Texonom Notion CLI
2
2
 
3
- > Robust TypeScript client for the unofficial Notion API.
3
+ Command line interface for exporting Notion data. It wraps the `@texonom/nclient` library and converts pages or entire workspaces to Markdown.
4
4
 
5
5
  [![NPM](https://img.shields.io/npm/v/@texonom/cli.svg)](https://www.npmjs.com/package/@texonom/cli) [![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
6
 
7
+ ## Features
8
+
9
+ - Export a single page or an entire workspace
10
+ - Output raw Notion data or rendered Markdown
11
+ - Handles rate limits and supports auth tokens
12
+
7
13
  ## Install
8
14
 
9
15
  ```bash
10
16
  pnpm i @texonom/cli
11
17
  ```
12
18
 
13
- # Usages
19
+ ## Usage
14
20
 
15
- ## Export
21
+ ### Export
16
22
 
17
- ```zsh
18
- ## export block, collection, collection_view and notion_user for each folder
23
+ ```bash
24
+ # export block, collection, collection_view and notion_user for each folder
19
25
  pnpm tsx src/main.ts export --raw
20
26
  ```
21
27
 
22
- # Develop
28
+ ### Programmatic use
23
29
 
24
30
  ```ts
25
31
  import { NotionExporter } from '@texonom/cli'
@@ -29,31 +35,54 @@ const recordMap = await exporter.notion.getPage(pageId)
29
35
  const md = await exporter.pageToMarkdown(parsePageId(pageId), recordMap)
30
36
  ```
31
37
 
32
- ### Example
38
+ ```ts
39
+ // also works with page URLs thanks to nutils
40
+ import { parsePageId } from '@texonom/nutils'
41
+
42
+ const exporter = new NotionExporter({ page })
43
+ const recordMap = await exporter.notion.getPage(page)
44
+ const md = await exporter.pageToMarkdown(parsePageId(page), recordMap)
45
+ ```
33
46
 
34
- Export whole workspace
47
+ ### Example workflow
35
48
 
36
- ```sh
37
- # 1. First get all raw data from the Notion API
49
+ ```bash
50
+ # 1. Fetch raw data from Notion
38
51
  pnpm tsx src/main.ts export -p 04089c8ae3534bf79512fc495944b321 --raw -r -f
39
52
 
40
- # 2. After that transform all raw data to markdown
41
- # it requres Notion token if there are missed blocks & spaces & users & collections (No ~ query)
53
+ # 2. Transform raw data to markdown (requires token if data is private)
42
54
  export NOTION_TOKEN=
43
55
  pnpm tsx src/main.ts export -p 04089c8ae3534bf79512fc495944b321 -r -l -t $NOTION_TOKEN -u
44
- # 3. If there is a rate limit error try without token for anonymous request
56
+
57
+ # 3. Retry without token if you hit rate limits
45
58
  pnpm tsx src/main.ts export -p 04089c8ae3534bf79512fc495944b321 -r -l -u
46
- # Iterate the 2-3 commands until collection error is gone (due to the rate limit)
47
59
  ```
48
60
 
49
- if there is memory error
61
+ If you encounter memory errors:
50
62
 
51
- ```
63
+ ```bash
52
64
  NODE_OPTIONS="--max-old-space-size=16384" tsx ...
53
65
  ```
54
66
 
55
- Export a single page
67
+ ### Export a single page
56
68
 
57
- ```sh
69
+ ```bash
58
70
  pnpm tsx src/main.ts export -p 04089c8ae3534bf79512fc495944b321
59
71
  ```
72
+
73
+ ## API
74
+
75
+ Exports:
76
+
77
+ - `NotionExportCommand` CLI entry
78
+ - `NotionExporter` class
79
+ - `getBlockLink(blockId, recordMap)`
80
+ - `loadRaw(folder)`
81
+ - `loadJson(folder, file)`
82
+ - `generateTreemaps(folder, pageTree)`
83
+ - `computeStats(pageTree)`
84
+ - `writeStats(file, stats)`
85
+
86
+ ## Difference from React Notion X
87
+
88
+ The original project focuses on rendering. This CLI adds a straightforward way to download and convert Notion content from the terminal.