Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions apps/roam/src/utils/convertRoamNodeToFullContent.simple.example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { TreeNode } from "roamjs-components/types";
import type { CrossAppNode } from "@repo/database/crossAppContracts";
import { buildFullMarkdown } from "./convertRoamNodeToFullContent";
import { contentTypes } from "@repo/content-model";

const block = (text: string, children: TreeNode[] = []): TreeNode => ({
text,
children,
order: 0,
parents: [],
uid: "",
heading: 0,
open: true,
viewType: "bullet",
blockViewType: "outline",
editTime: new Date(0),
textAlign: "left",
props: { imageResize: {}, iframe: {} },
});

const title = "Sleep improves memory consolidation";

const blocks: TreeNode[] = [
block(
"Multiple studies show that sleep after learning strengthens memory traces.",
),
block("Supporting evidence:", [block("[[EVD]] - Rasch & Born 2013")]),
];

export const roamClaimFullMarkdownSimpleExample: {
title: string;
blocks: TreeNode[];
full: CrossAppNode["content"]["full"];
} = {
title,
blocks,
full: {
contentType: contentTypes.roamMarkdown,
value: buildFullMarkdown({ title, blocks }),
},
};
48 changes: 34 additions & 14 deletions apps/roam/src/utils/convertRoamNodeToFullContent.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import { toMarkdown } from "./pageToMarkdown";
import { type RoamDiscourseNodeData } from "./getAllDiscourseNodesSince";
import { type DiscourseNode } from "./getDiscourseNodes";
import getFullTreeByParentUid from "roamjs-components/queries/getFullTreeByParentUid";
import getPageViewType from "roamjs-components/queries/getPageViewType";
import type { TreeNode, ViewType } from "roamjs-components/types";
import { contentTypes } from "@repo/content-model";
import type { CrossAppNode } from "@repo/database/crossAppContracts";
import { crossAppNodeToDbContent } from "@repo/database/lib/crossAppConverters";
import type { LocalContentDataInput } from "@repo/database/inputTypes";

export type RoamFullContentNode = {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the intent to replace this with CrossAppContent eventually?

author_local_id: string;
source_local_id: string;
created: string | number;
last_modified: string | number;
text: string;
node_type_id: string;
node_title?: string;
};

const FULL_MARKDOWN_OPTS = {
refs: true,
embeds: true,
Expand Down Expand Up @@ -38,26 +50,34 @@ export const buildFullMarkdown = ({
export const convertRoamNodeToFullContent = ({
nodes,
}: {
nodes: RoamDiscourseNodeData[];
nodes: RoamFullContentNode[];
}): LocalContentDataInput[] =>
nodes.flatMap((node) => {
try {
const title = node.node_title ?? node.text;
const blocks = getFullTreeByParentUid(node.source_local_id).children;
const viewType = getPageViewType(title) || "bullet";
return [
{
author_local_id: node.author_local_id,
source_local_id: node.source_local_id,
created: new Date(node.created || Date.now()).toISOString(),
last_modified: new Date(
node.last_modified || Date.now(),
).toISOString(),
text: buildFullMarkdown({ title, blocks, viewType }),
variant: "full",
scale: "document",
const crossAppNode: CrossAppNode = {
author: { localId: node.author_local_id },
localId: node.source_local_id,
createdAt: new Date(node.created || Date.now()),
modifiedAt: new Date(node.last_modified || Date.now()),
nodeType: { localId: node.node_type_id },
content: {
direct: {
localId: node.source_local_id,
value: title,
},

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maparent @mdroidian crossAppNode requires direct to be present but crossAppNodeToDbContent converter explicitly requires us to pass the variant type, so should we update the crossAppNode.content an or case?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It requires to pass the variant type to choose which of the two contents you're getting from the node. Will probably be updated with format when we have multiple format. I don't think we need to be an or case, or at least I don't see how it follows.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could have a variant that returns all contents as an array, would that be more useful to you?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was saying that here I am passing content.direct and content.full but direct will not be used anywhere it is here because the crossAppNode type requires both direct and full.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah! Yes, full should be optional.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a conference now, I'll make a task soon.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not see a case where the title is optional; do you?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case direct should be optional because it is not needed by the function that will consume this data

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... Are you sure that sharing does not include the title at all?
Possible underlying assumption: Do you expect the title to also be part of the full content?
In Obsidian we found it easier to separate the title from the content, so we assume that they are disjoint.

full: {
localId: node.source_local_id,
value: buildFullMarkdown({ title, blocks, viewType }),
contentType: contentTypes.roamMarkdown,
scale: "document",
},
},
];
};
const fullContent = crossAppNodeToDbContent(crossAppNode, "full");
return fullContent === undefined ? [] : [fullContent];
} catch (error) {
console.error(
`convertRoamNodeToFullContent: failed to build full markdown for ${node.source_local_id}:`,
Expand Down
Loading