Skip to content

Commit 8dee479

Browse files
feat: ensure that tables always put the title column first
1 parent 536d4d1 commit 8dee479

File tree

3 files changed

+36
-14
lines changed

3 files changed

+36
-14
lines changed

src/DatabaseViewRenderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ export class DatabaseViewRenderer {
4343
const props = pages[0].properties;
4444

4545
const keys = PropertiesParser.filterIncludedKeys(
46+
props.keys,
4647
view.properties.include,
47-
props.keys
4848
);
4949

5050
const table: any[][] = [];

src/PropertiesParser.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ describe("PropertiesParser", () => {
6363
name: "Terraform",
6464
},
6565
};
66+
6667
expect(result).toEqual(expected);
68+
// explicitly test key ordering
69+
expect(Array.from(result.keys.keys())).toEqual(["Name", "order", "Category"]);
6770
});
6871

6972
test("filters according to include filter", async () => {

src/PropertiesParser.ts

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,8 @@ import { DatabaseConfig, DatabaseConfigRenderPages } from './SyncConfig';
88

99
const debug = require("debug")("properties");
1010

11-
export interface ParsedProperties {
12-
title: string | null;
13-
category: string | null;
14-
order: number | undefined;
15-
properties: Record<string, any>;
16-
keys: Map<string, string>;
17-
}
18-
1911
export class PropertiesParser {
20-
constructor(private readonly richText: RichTextRenderer) {}
12+
constructor(private readonly richText: RichTextRenderer) { }
2113

2214
public async parsePageProperties(
2315
page: Page,
@@ -60,14 +52,30 @@ export class PropertiesParser {
6052

6153
public async parseProperties(page: Page, config: DatabaseConfig) {
6254
/**
63-
* Design: we always lookup the properties opn the page object itself.
55+
* Design: we always lookup the properties on the page object itself.
6456
* This way we only parse properties once and avoid any problems coming from
6557
* e.g. category properties being filtered via include filters.
6658
*/
59+
60+
/**
61+
* Terminology:
62+
*
63+
* property: Notion API property name
64+
* key: slugified Notion API property name, used to later build frontmatter
65+
* value: Notion API property value
66+
*/
67+
68+
/**
69+
* A record of key->value
70+
*/
6771
const properties: Record<string, any> = {};
72+
/**
73+
* A map of proprety -> key
74+
*/
6875
const keys = new Map<string, string>();
6976

7077
let title: string | null = null;
78+
let titleProperty: string | null = null;
7179
let category: string | null = null;
7280
let order: number | undefined = undefined;
7381

@@ -89,6 +97,7 @@ export class PropertiesParser {
8997

9098
if (value.type === "title") {
9199
title = parsedValue;
100+
titleProperty = name;
92101
}
93102

94103
if (categoryProperty && name === categoryProperty) {
@@ -99,14 +108,24 @@ export class PropertiesParser {
99108
order = parsedValue;
100109
}
101110
}
111+
112+
if (!titleProperty) {
113+
throw this.errorMissingRequiredProperty("of type 'title'", page);
114+
}
115+
116+
// no explicit ordering specified, so we make sure to put the title property first
117+
const includes = config.properties?.include
118+
|| [titleProperty, ...Array.from(keys.keys()).filter(x => x != titleProperty)];
119+
120+
102121
return {
103122
title,
104123
category,
105124
order,
106125
properties,
107126
keys: PropertiesParser.filterIncludedKeys(
108-
config.properties?.include,
109-
keys
127+
keys,
128+
includes
110129
),
111130
};
112131
}
@@ -155,8 +174,8 @@ export class PropertiesParser {
155174
}
156175

157176
public static filterIncludedKeys(
177+
keys: Map<string, string>,
158178
includes: string[] | undefined,
159-
keys: Map<string, string>
160179
): Map<string, string> {
161180
if (!includes) {
162181
return keys;

0 commit comments

Comments
 (0)