Skip to content

Commit bc65b8f

Browse files
committed
feat: improved logging
1 parent 52ece8d commit bc65b8f

File tree

4 files changed

+58
-11
lines changed

4 files changed

+58
-11
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ One of the big attractions of Notion for large documentation projects is that yo
8181

8282
## Slugs
8383

84-
By default, pages will be given a slug based on the Notion id. For a human-readable URL, add a notion property named `Slug` and enter values in there.
84+
By default, pages will be given a slug based on the Notion id. For a human-readable URL, add a notion property named `Slug` to your database pages and enter a value in there that will work well in a URL. That is, no spaces, ?, #, /, etc.
8585

8686
## Known Limitations
8787

src/NotionPage.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,32 @@ export class NotionPage {
3434
private metadata: GetPageResponse;
3535
public readonly pageId: string;
3636
public context: string; // where we found it in the hierarchy of the outline
37+
public foundDirectlyInOutline: boolean; // the page was found as a descendent of /outline instead of being linked to
3738

3839
private constructor(
3940
context: string,
4041
pageId: string,
41-
metadata: GetPageResponse
42+
metadata: GetPageResponse,
43+
foundDirectlyInOutline: boolean
4244
) {
4345
this.context = context;
4446
this.pageId = pageId;
4547
this.metadata = metadata;
48+
this.foundDirectlyInOutline = foundDirectlyInOutline;
49+
4650
// review: this is expensive to learn as it takes another api call... I
4751
// think? We can tell if it's a database because it has a "Name" instead of a
4852
// "tile" and "parent": "type": "database_id". But do we need to differentiate
4953
//this.type = PageType.Unknown;
5054
}
5155
public static async fromPageId(
5256
context: string,
53-
pageId: string
57+
pageId: string,
58+
foundDirectlyInOutline: boolean
5459
): Promise<NotionPage> {
5560
const metadata = await getPageMetadata(pageId);
5661
//logDebug(JSON.stringify(metadata));
57-
return new NotionPage(context, pageId, metadata);
62+
return new NotionPage(context, pageId, metadata, foundDirectlyInOutline);
5863
}
5964

6065
public matchesLinkId(id: string): boolean {
@@ -142,7 +147,9 @@ export class NotionPage {
142147
public get slug(): string {
143148
return this.explicitSlug() ?? "/" + this.pageId;
144149
}
145-
150+
public get hasExplicitSlug(): boolean {
151+
return this.explicitSlug() !== undefined;
152+
}
146153
public get keywords(): string | undefined {
147154
return this.getPlainTextProperty("Keywords", "");
148155
}

src/log.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ export function warning(s: string): void {
1414
export function info(s: string): void {
1515
console.log(s);
1616
}
17+
export function heading(s: string): void {
18+
console.log(chalk.blue(s));
19+
}
1720
export function verbose(s: string): void {
1821
if (logLevel === "verbose" || logLevel === "debug")
1922
console.log(chalk.green(s));

src/pull.ts

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ import {
1313
import { tweakForDocusaurus } from "./DocusaurusTweaks";
1414
import { setupCustomTransformers } from "./CustomTranformers";
1515
import * as Path from "path";
16-
import { error, info, logDebug, verbose, warning } from "./log";
16+
import { error, heading, info, logDebug, verbose, warning } from "./log";
1717
import { convertInternalLinks } from "./links";
1818
import { ListBlockChildrenResponseResult } from "notion-to-md/build/types";
19+
import chalk from "chalk";
1920

2021
export type Options = {
2122
notionToken: string;
@@ -32,6 +33,12 @@ let currentSidebarPosition = 0;
3233
let layoutStrategy: LayoutStrategy;
3334
let notionToMarkdown: NotionToMarkdown;
3435
const pages = new Array<NotionPage>();
36+
const counts = {
37+
output_normally: 0,
38+
skipped_because_empty: 0,
39+
skipped_because_status: 0,
40+
skipped_because_level_cannot_have_content: 0,
41+
};
3542

3643
export async function notionPull(incomingOptions: Options): Promise<void> {
3744
options = incomingOptions;
@@ -67,9 +74,21 @@ export async function notionPull(incomingOptions: Options): Promise<void> {
6774
// introduce any hierarchy in the resulting page urls, we can't
6875
// do this link fixing until we've already seen all the pages and
6976
// figured out what their eventual relative url will be.
77+
heading(
78+
"Stage 1: walk children of the page named 'Outline', looking for pages..."
79+
);
7080
await getPagesRecursively("", options.rootPage, true);
7181
logDebug("getPagesRecursively", JSON.stringify(pages, null, 2));
82+
info(`Found ${pages.length} pages`);
83+
info(``);
84+
heading(
85+
`Stage 2: convert ${pages.length} Notion pages to markdown and save locally...`
86+
);
7287
await outputPages(pages);
88+
info(`Finished processing ${pages.length} pages`);
89+
info(JSON.stringify(counts));
90+
info(``);
91+
heading("Stage 3: clean up old files & images...");
7392
await layoutStrategy.cleanupOldFiles();
7493
await cleanupOldImages();
7594
}
@@ -91,10 +110,14 @@ async function getPagesRecursively(
91110
pageId: string,
92111
rootLevel: boolean
93112
) {
94-
const pageInTheOutline = await NotionPage.fromPageId(incomingContext, pageId);
113+
const pageInTheOutline = await NotionPage.fromPageId(
114+
incomingContext,
115+
pageId,
116+
true
117+
);
95118

96119
info(
97-
`Reading Outline Page ${incomingContext}/${pageInTheOutline.nameOrTitle}`
120+
`Looking for children and links from ${incomingContext}/${pageInTheOutline.nameOrTitle}`
98121
);
99122

100123
const pageInfo = await pageInTheOutline.getContentInfo();
@@ -103,7 +126,7 @@ async function getPagesRecursively(
103126
error(
104127
`Skipping "${pageInTheOutline.nameOrTitle}" and its children. docu-notion does not support pages that are both levels and have content at the same time.`
105128
);
106-
129+
++counts.skipped_because_level_cannot_have_content;
107130
return;
108131
}
109132
if (!rootLevel && pageInfo.hasParagraphs) {
@@ -135,14 +158,15 @@ async function getPagesRecursively(
135158
}
136159

137160
for (const id of pageInfo.linksPages) {
138-
pages.push(await NotionPage.fromPageId(context, id));
161+
pages.push(await NotionPage.fromPageId(context, id, false));
139162
}
140163
} else {
141164
console.info(
142165
warning(
143166
`Warning: The page "${pageInTheOutline.nameOrTitle}" is in the outline but appears to not have content, links to other pages, or child pages. It will be skipped.`
144167
)
145168
);
169+
++counts.skipped_because_empty;
146170
}
147171
}
148172

@@ -155,10 +179,21 @@ async function outputPage(page: NotionPage) {
155179
verbose(
156180
`Skipping page because status is not '${options.statusTag}': ${page.nameOrTitle}`
157181
);
182+
++counts.skipped_because_status;
158183
return;
159184
}
160185

161-
info(`Reading Page ${page.context}/${page.nameOrTitle}`);
186+
info(
187+
`Reading & converting page ${page.context}/${
188+
page.nameOrTitle
189+
} (${chalk.blue(
190+
page.hasExplicitSlug
191+
? page.slug
192+
: page.foundDirectlyInOutline
193+
? "Descendant of Outline, not Database"
194+
: "NO SLUG"
195+
)})`
196+
);
162197
layoutStrategy.pageWasSeen(page);
163198

164199
const mdPath = layoutStrategy.getPathForPage(page, ".md");
@@ -208,4 +243,6 @@ async function outputPage(page: NotionPage) {
208243
const output = `${frontmatter}\n${imports}\n${body}`;
209244

210245
fs.writeFileSync(mdPath, output, {});
246+
247+
++counts.output_normally;
211248
}

0 commit comments

Comments
 (0)