Skip to content

Commit 290a9f5

Browse files
authored
ENG-1409 - Add Roam Import JSON support in getExportTypes.ts (#761)
* Add Roam Import JSON support in getExportTypes.ts - Introduced types for RoamImportUser, RoamImportBlock, and RoamImportPage to structure imported data. - Implemented functions to convert nodes to RoamImportBlock format and retrieve user information. - Added a new export type for Roam Import JSON, allowing for structured export of Roam data in JSON format. * Refactor getExportTypes to streamline heading and text alignment handling - Simplified the assignment of the heading property. - Updated text alignment logic to only set the property when it is not "left".
1 parent 290d095 commit 290a9f5

1 file changed

Lines changed: 102 additions & 0 deletions

File tree

apps/roam/src/utils/getExportTypes.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,31 @@ type getExportTypesProps = {
3838
isExportDiscourseGraph: boolean;
3939
};
4040

41+
/* eslint-disable @typescript-eslint/naming-convention */
42+
type RoamImportUser = {
43+
":user/uid": string;
44+
};
45+
46+
type RoamImportBlock = {
47+
string: string;
48+
uid?: string;
49+
children?: RoamImportBlock[];
50+
"create-time"?: number;
51+
"edit-time"?: number;
52+
"edit-user"?: RoamImportUser;
53+
heading?: 0 | 1 | 2 | 3;
54+
"text-align"?: "left" | "center" | "right" | "justify";
55+
};
56+
57+
type RoamImportPage = {
58+
title: string;
59+
children?: RoamImportBlock[];
60+
"create-time"?: number;
61+
"edit-time"?: number;
62+
"edit-user"?: RoamImportUser;
63+
};
64+
/* eslint-enable @typescript-eslint/naming-convention */
65+
4166
const getExportTypes = ({
4267
results,
4368
exportId,
@@ -53,6 +78,49 @@ const getExportTypes = ({
5378
const getRelationData = () =>
5479
getRelationDataUtil({ allRelations, nodeLabelByType, local: true });
5580

81+
const getRoamImportUser = (): RoamImportUser | undefined => {
82+
const userUid = window.roamAlphaAPI.user.uid();
83+
if (!userUid) return undefined;
84+
const user = {} as RoamImportUser;
85+
user[":user/uid"] = userUid;
86+
return user;
87+
};
88+
89+
const toEpochMilliseconds = (value: Date): number | undefined => {
90+
const time = value.getTime();
91+
return Number.isFinite(time) && time > 0 ? time : undefined;
92+
};
93+
94+
const toRoamHeading = (heading: number): 0 | 1 | 2 | 3 => {
95+
if (heading === 1 || heading === 2 || heading === 3) return heading;
96+
return 0;
97+
};
98+
99+
const toRoamImportBlock = (
100+
node: TreeNode,
101+
editUser: RoamImportUser | undefined,
102+
): RoamImportBlock => {
103+
const editTime = toEpochMilliseconds(node.editTime);
104+
const heading = toRoamHeading(node.heading);
105+
const children = node.children.map((child) =>
106+
toRoamImportBlock(child, editUser),
107+
);
108+
109+
const block: RoamImportBlock = {
110+
string: node.text,
111+
uid: node.uid || undefined,
112+
children: children.length ? children : undefined,
113+
heading,
114+
};
115+
block["create-time"] = editTime;
116+
block["edit-time"] = editTime;
117+
block["edit-user"] = editUser;
118+
if (node.textAlign && node.textAlign !== "left") {
119+
block["text-align"] = node.textAlign;
120+
}
121+
return block;
122+
};
123+
56124
const getJsonData = async (results: Result[]) => {
57125
const grammar = allRelations.map(({ label, destination, source }) => ({
58126
label,
@@ -79,6 +147,27 @@ const getExportTypes = ({
79147
});
80148
};
81149

150+
const getRoamImportData = (results: Result[]): RoamImportPage[] => {
151+
const editUser = getRoamImportUser();
152+
return getPageData({ results, allNodes, isExportDiscourseGraph }).map(
153+
({ text, uid }) => {
154+
const { children } = getFullTreeByParentUid(uid);
155+
const { date, modified } = getPageMetadata(text);
156+
const createTime = toEpochMilliseconds(date);
157+
const editTime = toEpochMilliseconds(modified);
158+
159+
const page: RoamImportPage = {
160+
title: text,
161+
children: children.map((node) => toRoamImportBlock(node, editUser)),
162+
};
163+
page["create-time"] = createTime;
164+
page["edit-time"] = editTime || createTime;
165+
page["edit-user"] = editUser;
166+
return page;
167+
},
168+
);
169+
};
170+
82171
return [
83172
{
84173
name: "Markdown",
@@ -145,6 +234,19 @@ const getExportTypes = ({
145234
];
146235
},
147236
},
237+
{
238+
name: "Roam Import JSON",
239+
callback: ({ filename }) => {
240+
if (!results) return Promise.resolve([]);
241+
const data = getRoamImportData(results);
242+
return Promise.resolve([
243+
{
244+
title: `${filename.replace(/\.json$/, "")}.json`,
245+
content: JSON.stringify(data, undefined, 2),
246+
},
247+
]);
248+
},
249+
},
148250
{
149251
name: "JSON-LD (Experimental)",
150252
callback: async ({ filename }) => {

0 commit comments

Comments
 (0)