Skip to content

Commit 3e0c3e7

Browse files
committed
feat: add support for cover and icon
1 parent 979b057 commit 3e0c3e7

File tree

5 files changed

+129
-2
lines changed

5 files changed

+129
-2
lines changed

source/metadata.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* -------------------------------------------------------------------------
1414
*/
1515

16+
import { getPropertyContentFromFile } from '#property';
17+
1618
import type { Metadata, NotionAPIDatabase, NotionAPIPage } from '#types';
1719

1820
/**
@@ -28,6 +30,33 @@ export function getMetadata<E extends NotionAPIPage | NotionAPIDatabase>(
2830

2931
const variable = { url, lastEditedTime };
3032
const invariant = { createdTime };
33+
const visual = getCommonVisualMetadata(entity);
34+
35+
return { ...variable, ...invariant, ...visual };
36+
}
37+
38+
/**
39+
* get common visual properties such as cover and icon from a page or database
40+
* @param entity the page or database object returned from Notion API
41+
* @returns common properties
42+
*/
43+
export function getCommonVisualMetadata<
44+
E extends NotionAPIPage | NotionAPIDatabase,
45+
>(
46+
entity: E,
47+
): {
48+
coverImage: string | null;
49+
iconEmoji: string | null;
50+
iconImage: string | null;
51+
} {
52+
const { cover, icon } = entity;
3153

32-
return { ...variable, ...invariant };
54+
return {
55+
coverImage: cover ? getPropertyContentFromFile(cover) : null,
56+
iconEmoji: icon?.type === 'emoji' ? icon.emoji : null,
57+
iconImage:
58+
icon?.type === 'external' || icon?.type === 'file'
59+
? getPropertyContentFromFile(icon)
60+
: null,
61+
};
3362
}

source/types/index.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ export type Metadata = {
8585
url: string;
8686
createdTime: string;
8787
lastEditedTime: string;
88+
coverImage: string | null;
89+
iconEmoji: string | null;
90+
iconImage: string | null;
8891
};
8992

9093
export type Page = {

spec/client.spec.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@
1515

1616
import assert from 'assert';
1717

18-
import { Notion } from '#client';
18+
import { Notion, getCommonMetadata } from '#client';
1919
import { mockDatabase, mockPage } from './mock';
20+
import { NotionAPIPage } from '#types';
2021

2122
describe('cl:Notion', () => {
2223
const client = new Notion({ token: 'token' });
@@ -71,6 +72,9 @@ title: 'Text'
7172
url: 'https://www.notion.so/workspace/page'
7273
lastEditedTime: '2020-01-01T00:00:00Z'
7374
createdTime: '2020-01-01T00:00:00Z'
75+
coverImage: 'https://www.notion.so/cover.png'
76+
iconEmoji: '📚'
77+
iconImage: null
7478
---
7579
page-block0
7680

spec/metadata.spec.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,91 @@ describe('fn:getMetadata', () => {
2323
createdTime: '2020-01-01T00:00:00Z',
2424
lastEditedTime: '2020-01-01T00:00:00Z',
2525
url: 'https://www.notion.so/workspace/page',
26+
coverImage: 'https://www.notion.so/cover.png',
27+
iconEmoji: '📚',
28+
iconImage: null,
2629
});
2730
});
31+
32+
it('return null if no cover is set', () => {
33+
expect(getMetadata({ ...examples.page, cover: null })).toEqual(
34+
expect.objectContaining({ coverImage: null }),
35+
);
36+
});
37+
38+
it('return the file url if the cover is embedded', () => {
39+
expect(
40+
getMetadata({
41+
...examples.page,
42+
cover: {
43+
type: 'file',
44+
file: {
45+
url: 'url',
46+
expiry_time: '2020-01-01T00:00:00Z',
47+
},
48+
},
49+
}),
50+
).toEqual(expect.objectContaining({ coverImage: 'url' }));
51+
});
52+
53+
it('return the file url if the cover is external', () => {
54+
expect(
55+
getMetadata({
56+
...examples.page,
57+
cover: {
58+
type: 'external',
59+
external: {
60+
url: 'url',
61+
},
62+
},
63+
}),
64+
).toEqual(expect.objectContaining({ coverImage: 'url' }));
65+
});
66+
67+
it('return null if no icon is set', () => {
68+
expect(getMetadata({ ...examples.page, icon: null })).toEqual(
69+
expect.objectContaining({ iconEmoji: null, iconImage: null }),
70+
);
71+
});
72+
73+
it('return the emoji string if the icon is set as an emoji', () => {
74+
expect(
75+
getMetadata({
76+
...examples.page,
77+
icon: {
78+
type: 'emoji',
79+
emoji: '☀️',
80+
},
81+
}),
82+
).toEqual(expect.objectContaining({ iconEmoji: '☀️', iconImage: null }));
83+
});
84+
85+
it('return the file url if the icon is embedded', () => {
86+
expect(
87+
getMetadata({
88+
...examples.page,
89+
icon: {
90+
type: 'file',
91+
file: {
92+
url: 'url',
93+
expiry_time: '2020-01-01T00:00:00Z',
94+
},
95+
},
96+
}),
97+
).toEqual(expect.objectContaining({ iconEmoji: null, iconImage: 'url' }));
98+
});
99+
100+
it('return the file url if the icon is external', () => {
101+
expect(
102+
getMetadata({
103+
...examples.page,
104+
icon: {
105+
type: 'external',
106+
external: {
107+
url: 'url',
108+
},
109+
},
110+
}),
111+
).toEqual(expect.objectContaining({ iconEmoji: null, iconImage: 'url' }));
112+
});
28113
});

spec/node.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ function generateDatabase({
5252
url: `https://www.notion.so/${title.replace(' ', '-')}-${databaseID}`,
5353
createdTime,
5454
lastEditedTime,
55+
coverImage: null,
56+
iconEmoji: null,
57+
iconImage: null,
5558
},
5659
pages,
5760
};
@@ -80,6 +83,9 @@ function generatePage({
8083
url: `https://www.notion.so/${title.replace(' ', '-')}-${pageID}`,
8184
createdTime,
8285
lastEditedTime,
86+
coverImage: null,
87+
iconEmoji: null,
88+
iconImage: null,
8389
},
8490
markdown: '',
8591
blocks: [],

0 commit comments

Comments
 (0)