Skip to content

Commit e74c838

Browse files
fix: correctly handle configured outDirs, indexPath
1 parent 1f406cc commit e74c838

10 files changed

+152
-32
lines changed

jest.config.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = {
2+
transform: {
3+
"^.+\\.ts?$": "ts-jest",
4+
},
5+
testEnvironment: "node",
6+
testRegex: "./src/.*\\.(test|spec)?\\.(ts|ts)$",
7+
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
8+
roots: ["<rootDir>/src"],
9+
};

package.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@
1313
],
1414
"scripts": {
1515
"build": "tsc",
16-
"prepare": "tsc"
16+
"prepare": "tsc",
17+
"test": "jest"
1718
},
1819
"devDependencies": {
19-
"ts-node": "^10.2.1",
20-
"typescript": "^4.4.3",
20+
"@types/jest": "^27.0.2",
2121
"@types/js-yaml": "^4.0.3",
22-
"@types/mime-types": "^2.1.1"
22+
"@types/mime-types": "^2.1.1",
23+
"jest": "^27.3.1",
24+
"ts-jest": "^27.0.7",
25+
"ts-node": "^10.2.1",
26+
"typescript": "^4.4.3"
2327
},
2428
"dependencies": {
2529
"@notionhq/client": "^0.3.2",

src/DatabasePageRenderer.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,27 @@ import { Client } from "@notionhq/client";
22
import { DatabaseConfig } from "./SyncConfig";
33
import { Database } from "./Database";
44
import { DeferredRenderer } from "./DeferredRenderer";
5+
import { SyncConfig } from ".";
56

67
export class DatabasePageRenderer {
78
constructor(
89
readonly publicApi: Client,
910
readonly deferredRenderer: DeferredRenderer,
10-
readonly config: Record<string, DatabaseConfig>
11+
readonly config: SyncConfig
1112
) {}
1213

1314
async renderDatabase(databaseId: string): Promise<Database> {
14-
const dbConfig: DatabaseConfig = this.config[databaseId] || {
15-
outSubDir: "",
16-
pageCategoryValuePrefix: "",
15+
const fallbackDbConfig: DatabaseConfig = {
16+
outDir:
17+
databaseId === this.config.cmsDatabaseId
18+
? this.config.outDir
19+
: this.config.outDir + "/" + databaseId,
1720
properties: {
18-
category: "category",
21+
category: "Category",
1922
},
2023
};
24+
const dbConfig: DatabaseConfig =
25+
this.config.databases[databaseId] || fallbackDbConfig;
2126

2227
const db = await this.publicApi.databases.retrieve({
2328
database_id: databaseId,

src/PageRenderer.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,18 @@ export class PageRenderer {
3131
this.throwMissingRequiredProperty("name", page);
3232
}
3333

34-
const category = props.values[props.keys.get(config.properties.category)!!];
35-
if (category) {
36-
this.throwMissingRequiredProperty(config.properties.category, page);
34+
const category = props.values["category"];
35+
if (!category) {
36+
this.throwMissingRequiredProperty("category", page);
3737
}
3838

39+
debug(props);
40+
3941
const nameSlug = slugify(name);
40-
const categorySlug = config.pageCategoryValuePrefix + slugify(category);
42+
const categorySlug = slugify(category);
4143

42-
const file = `${config.outDir}/${nameSlug}.md`;
44+
const destDir = `${config.outDir}/${categorySlug}`;
45+
const file = `${destDir}/${nameSlug}.md`;
4346

4447
// Design: all the rendering performance could be greatly enhanced writing directly to output streams instead
4548
// of concatenating all in memory. OTOH naively concatenatic strings is straightforward, easier to debug and rendering
@@ -51,7 +54,7 @@ export class PageRenderer {
5154
file,
5255
properties: props,
5356
render: async () => {
54-
const assetWriter = new AssetWriter(config.outDir);
57+
const assetWriter = new AssetWriter(destDir);
5558

5659
const frontmatter = this.frontmatterRenderer.renderFrontmatter(
5760
props.values
@@ -62,7 +65,7 @@ export class PageRenderer {
6265
assetWriter
6366
);
6467

65-
await fs.mkdir(config.outDir, { recursive: true });
68+
await fs.mkdir(destDir, { recursive: true });
6669
await fs.writeFile(file, frontmatter + body);
6770

6871
logger.info("wrote: " + file);

src/PropertiesParser.spec.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { PropertiesParser } from "./PropertiesParser";
2+
import { DatabaseConfig } from "./SyncConfig";
3+
4+
describe("PropertiesParser", () => {
5+
describe("filter", () => {
6+
test("preserves all properties and adds conventional with no include filter", async () => {
7+
const sut = new PropertiesParser({} as any);
8+
9+
const props = {
10+
values: { order: 30, category: "Tools", name: "Terraform" },
11+
keys: new Map([
12+
["order", "order"],
13+
["Category", "category"],
14+
["Name", "name"],
15+
]),
16+
};
17+
18+
const config: DatabaseConfig = {
19+
outDir: "db/",
20+
properties: {
21+
category: "Category",
22+
},
23+
};
24+
25+
const result = sut.filter(config, props);
26+
const expected = {
27+
keys: props.keys,
28+
values: {
29+
order: 30,
30+
category: "Tools",
31+
name: "Terraform",
32+
title: "Terraform",
33+
},
34+
};
35+
36+
expect(result).toEqual(expected);
37+
});
38+
39+
test("filters according to include filter", async () => {
40+
const sut = new PropertiesParser({} as any);
41+
42+
const props = {
43+
values: { order: 30, category: "Tools", name: "Terraform" },
44+
keys: new Map([
45+
["order", "order"],
46+
["Category", "category"],
47+
["Name", "name"],
48+
]),
49+
};
50+
51+
const config: DatabaseConfig = {
52+
outDir: "db/",
53+
properties: {
54+
category: "Category",
55+
include: ["Name", "Category"],
56+
},
57+
};
58+
59+
const result = sut.filter(config, props);
60+
const expected = {
61+
keys: new Map([
62+
["Name", "name"],
63+
["Category", "category"],
64+
]),
65+
values: {
66+
category: "Tools",
67+
name: "Terraform",
68+
title: "Terraform",
69+
},
70+
};
71+
72+
expect(result).toEqual(expected);
73+
});
74+
});
75+
});

src/PropertiesParser.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ export class PropertiesParser {
7575
// patch properties by convention
7676
// vuepress expects a title and category property
7777
properties["title"] = input.values["name"]; // notion API always calls it name
78-
properties["category"] = input.values[config.properties.category];
78+
properties["category"] =
79+
input.values[input.keys.get(config.properties.category)!!];
7980

8081
// vuepress relies on files being called README.md to make "category home" pages
8182
// however the name "README" does not read nice in a sidebar menu, so we label these pages "Introduction"

src/SyncConfig.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ export interface SyncConfig {
44
/**
55
* Id of the Notion database containing the CMS content.
66
* Traversing the block graph starts here.
7+
*
8+
* By convention this database must have the following properties
9+
*
10+
* - Name: page name
11+
* - Category: page category
12+
* - sort: number to control sorting of pages in sidebar
713
*/
814
cmsDatabaseId: string;
915

@@ -31,18 +37,10 @@ export interface DatabaseConfig {
3137
/**
3238
* The output directory where the sync will place pages of this database.
3339
*
34-
* Example: "docs/mydb/"
40+
* Example: docs/mydb"
3541
*/
3642
outDir: string;
3743

38-
/**
39-
* The prefix to apply to the category value of all pages.
40-
* This is useful to create a unique category name for all pages of this database.
41-
*
42-
* Example: "mydb/"
43-
*/
44-
pageCategoryValuePrefix: string;
45-
4644
/**
4745
* Notion API https://developers.notion.com/reference/post-database-query#post-database-query-sort
4846
*/

src/slugify.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { slugify } from "./slugify";
2+
3+
describe("slugify", () => {
4+
test("does not preserve forward slashes", () => {
5+
expect(slugify("CFMM / core")).toEqual("cfmm-core");
6+
});
7+
8+
test("does not emojis", () => {
9+
expect(slugify("cfmm/🏢 Core")).toEqual("cfmm-core");
10+
});
11+
});

src/sync.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ export async function sync(notionApiToken: string, config: SyncConfig) {
2626
frontmatterRenderer,
2727
bodyRenderer
2828
);
29+
2930
const dbRenderer = new DatabasePageRenderer(
3031
publicApi,
3132
deferredRenderer,
32-
config.databases
33+
config
3334
);
3435

3536
deferredRenderer.initialize(dbRenderer, pageRenderer);
@@ -39,7 +40,7 @@ export async function sync(notionApiToken: string, config: SyncConfig) {
3940
await deferredRenderer.process();
4041

4142
await fs.writeFile(
42-
"docs/.vuepress/index.ts",
43+
config.indexPath,
4344
`export const index = ${JSON.stringify(
4445
deferredRenderer.getRenderedPages(),
4546
null,

tsconfig.json

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"compilerOptions": {
3-
"lib": ["ES2020"],
3+
"lib": [
4+
"ES2020"
5+
],
46
"target": "ES2020",
57
"module": "CommonJS",
68
"allowJs": true,
@@ -19,7 +21,18 @@
1921
"noUnusedParameters": false,
2022
"noUnusedLocals": true,
2123
"outDir": "./dist",
22-
"typeRoots": ["node_modules/@types"]
24+
"typeRoots": [
25+
"node_modules/@types"
26+
],
27+
"types": [
28+
"node",
29+
"@types/jest"
30+
]
2331
},
24-
"include": ["src/**.ts"]
25-
}
32+
"include": [
33+
"src/**.ts"
34+
],
35+
"exclude": [
36+
"src/**/*.spec.ts"
37+
]
38+
}

0 commit comments

Comments
 (0)