Skip to content

Commit 957ccd8

Browse files
committed
merge: resolve conflicts with main
1 parent 67fc000 commit 957ccd8

File tree

9 files changed

+266
-162
lines changed

9 files changed

+266
-162
lines changed

packages/cli/src/main.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ export * from './notion/export'
1818
export * from './notion/index'
1919
export * from './treemap'
2020
export * from './stats'
21+
export * from './treemap'
22+
export * from './stats'

packages/cli/src/notion/export.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
11
import { Option, Command } from 'clipanion'
22
import { NotionExporter } from './index'
33
import { generateTreemaps, PageNode } from '../treemap'
4+
import { computeStats, writeStats } from '../stats'
5+
treemap = Option.Boolean('--treemap', {
6+
description: 'Generate HTML treemap after export'
7+
})
8+
stats = Option.Boolean('--stats', {
9+
description: 'Generate statistics JSON after export'
10+
})
11+
12+
if (this.treemap || this.stats) if (!exporter.pageTree) await exporter.loadRaw()
13+
14+
const tree = exporter.pageTree as unknown as PageNode
15+
if (this.treemap && tree) await generateTreemaps(this.folder, tree)
16+
17+
if (this.stats && tree) {
18+
const stats = computeStats(tree)
19+
await writeStats(`${this.folder}/stats.json`, stats)
20+
}
21+
import { generateTreemaps, PageNode } from '../treemap'
422
import { computeStats, writeStats } from '../stats'
523

624
export class NotionExportCommand extends Command {

packages/cli/src/treemap.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,21 @@
11
import fs from 'fs'
22
import { promisify } from 'util'
3-
43
export interface PageNode {
5-
id: string
6-
blocks: number
74
pages: number
85
title: string
96
children?: PageNode[]
107
}
118

129
const writeFile = promisify(fs.writeFile)
13-
1410
export async function generateTreemaps(folder: string, pageTree: PageNode) {
1511
const treemapDataPages = computeMetrics(pageTree, 'pages')
1612
const titlePages = 'Texonom PageTree'
1713
const outputPathPages = `${folder}/pagetree.html`
1814
await generateTreemapHTML(treemapDataPages, titlePages, outputPathPages)
1915

20-
const treemapDataBlocks = computeMetrics(pageTree, 'blocks')
2116
const titleBlocks = 'Texonom BlockMap'
2217
const outputPathBlocks = `${folder}/blocktree.html`
2318
await generateTreemapHTML(treemapDataBlocks, titleBlocks, outputPathBlocks)
24-
}
25-
2619
interface TreemapNode {
2720
id: string
2821
name: string

packages/nclient/readme.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@ const backlinks = await api.getBacklinks({
4242
const pageBacklinks = await api.getPageBacklinks('page-id')
4343
```
4444

45+
### Fetch backlinks
46+
47+
Backlinks require an auth token.
48+
49+
```ts
50+
const backlinks = await api.getBacklinks({
51+
block: { id: 'page-id', spaceId: 'space-id' }
52+
})
53+
54+
// or simply pass the page id
55+
const pageBacklinks = await api.getPageBacklinks('page-id')
56+
```
57+
4558
### Fetch a database's content
4659

4760
You can pass a database ID to the `getPage` method. The response is an object which contains several important properties:

packages/nclient/src/notion-api.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ test(`Page Backlink`, { timeout: 10000, concurrent: true }, async () => {
6565
expect(backlinks.backlinks.length > 0)
6666
})
6767

68+
test(`Page Backlink`, { timeout: 10000, concurrent: true }, async () => {
69+
const api = new NotionAPI({ authToken: process.env.NOTION_TOKEN })
70+
const backlinks = await api.getPageBacklinks('441d5ce2-b781-46d0-9354-54042b4f06d9')
71+
expect(backlinks.backlinks.length > 0)
72+
})
73+
6874
test(`Get block`, { timeout: 10000, concurrent: true }, async () => {
6975
const id = '3f9e0d86-c643-4672-aa0c-78d63fa80598'
7076
const api = new NotionAPI()

packages/nclient/src/notion-api.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,23 @@ export class NotionAPI {
591591
return this.getBacklinks({ block: { id, spaceId } }, fetchOption)
592592
}
593593

594+
/**
595+
* Fetch backlinks for a page by automatically resolving its space id.
596+
* Requires an authToken since backlinks are a private API.
597+
*
598+
* @param pageId page id or url
599+
* @param fetchOption additional fetch options
600+
*/
601+
public async getPageBacklinks(pageId: string, fetchOption?: FetchOption) {
602+
const id = parsePageId(pageId)
603+
const res = await this.getBlocks([id], fetchOption)
604+
const block = res.recordMap.block[id]?.value
605+
if (!block) throw new Error(`Block not found "${uuidToId(id)}"`)
606+
const spaceId = block.space_id
607+
608+
return this.getBacklinks({ block: { id, spaceId } }, fetchOption)
609+
}
610+
594611
public async fetch<T>({
595612
endpoint,
596613
body,

packages/nreact/src/components/search-dialog.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import React from 'react'
2-
import { getBlockParentPage, getBlockTitle } from '@texonom/nutils'
3-
42
import { NotionContextConsumer, NotionContextProvider } from '../context'
53
import { ClearIcon } from '../icons/clear-icon'
64
import { LoadingIcon } from '../icons/loading-icon'
@@ -19,6 +17,16 @@ const debounce = (func: (...args: any[]) => void, wait: number) => {
1917
}
2018
}
2119

20+
// debounce search calls so the expensive query only runs after typing stops
21+
this._search = debounce(this._searchImpl.bind(this), 500)
22+
onInput={this._onChangeQuery}
23+
let timeout: ReturnType<typeof setTimeout> | undefined
24+
return (...args: any[]) => {
25+
if (timeout) clearTimeout(timeout)
26+
timeout = setTimeout(() => func(...args), wait)
27+
}
28+
}
29+
2230
export class SearchDialog extends React.Component<{
2331
isOpen: boolean
2432
rootBlockId: string

packages/nreact/src/context.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,15 @@ export const NotionContextProvider: React.FC<PartialNotionContext> = ({
185185
if (components.nextLink) {
186186
const nextLink = wrapNextLink(components.nextLink)
187187
components.nextLink = nextLink
188-
189188
if (!components.PageLink) components.PageLink = nextLink
190189
if (!components.Link) components.Link = nextLink
191190
}
191+
// ensure the user can't override default components with falsy values
192+
// since it would result in very difficult-to-debug react errors
193+
for (const key of Object.keys(components)) if (!components[key]) delete components[key]
194+
195+
return components
196+
}, [themeComponents])
192197

193198
// ensure the user can't override default components with falsy values
194199
// since it would result in very difficult-to-debug react errors

0 commit comments

Comments
 (0)