-
Notifications
You must be signed in to change notification settings - Fork 6
[ENG-1848] Add Roam full markdown content variant for shared nodes #1134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b4f758c
f29b4b9
430f0e2
6ff9e81
223d023
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,233 @@ | ||
| import type { TreeNode } from "roamjs-components/types"; | ||
| import type { CrossAppNode } from "@repo/database/crossAppNodeContract"; | ||
| import { buildFullMarkdown } from "./convertRoamNodeToFullContent"; | ||
|
|
||
| /** | ||
| * Typed example for ENG-1848 ("tests or fixtures cover representative Roam | ||
| * block content becoming `full` markdown"). This is not a concrete test; it | ||
| * documents the `tree.children` shape returned by `getFullTreeByParentUid` for | ||
| * a real Roam claim page and type-checks the generated markdown against the | ||
| * contract. | ||
| * | ||
| * Derived from: | ||
| * https://roamresearch.com/#/app/plugin-testing-akamatsulab2/page/dnHNmYwe5 | ||
| * | ||
| * Observed markdown output: | ||
| * | ||
| * # [[CLM]] - Actin assembly peaks 8 seconds before endocytic scission | ||
| * | ||
| * - ## Source of Claim [ℹ](link to [[@source]], name, URL, etc) | ||
| * - [[[[EVD]] - Membrane invagination occurred ~6 seconds after scission protein (spHob1-GFP) was detected in budding yeast cells - [[@sun2019direct]]]] | ||
| * - [[[[EVD]] - At fission yeast endocytic sites, scission protein (spHob1) first detected ~2 seconds before initiation of membrane invagination - [[@sun2019direct]]]] | ||
| * - [[[[EVD]] - Actin appearance occurred 9 (+/-2) seconds prior to patch formation and disappears 10 (+/-2) seconds following patch development. [[@sirotkin2010quantitative]]]] | ||
| * - [[[[EVD]] - At zero seconds, 7000 actin proteins associated with endocytic invagination - [[@sirotkin2010quantitative]]]] | ||
| * - actin assembly peaks (x) seconds before/after endocytic scission | ||
| * - [[[[CLM]] - Actin assembly peaks 8 seconds before endocytic scission]] | ||
| * - ## Notes | ||
| * -  | ||
| */ | ||
|
|
||
| type SerializedTreeNode = Omit<TreeNode, "children" | "editTime"> & { | ||
| children: SerializedTreeNode[]; | ||
| editTime: string; | ||
| }; | ||
|
|
||
| const deserializeTreeNode = (node: SerializedTreeNode): TreeNode => ({ | ||
| ...node, | ||
| editTime: new Date(node.editTime), | ||
| children: node.children.map(deserializeTreeNode), | ||
| }); | ||
|
|
||
| const title = | ||
| "[[CLM]] - Actin assembly peaks 8 seconds before endocytic scission"; | ||
|
|
||
| const serializedBlocks: SerializedTreeNode[] = [ | ||
| { | ||
| text: "Source of Claim [ℹ](((JtVWq1Cwl)))", | ||
| open: true, | ||
| order: 0, | ||
| uid: "yxM5yI07g", | ||
| heading: 2, | ||
| viewType: "bullet", | ||
| blockViewType: "outline", | ||
| editTime: "2024-02-29T21:28:17.505Z", | ||
| props: { | ||
| imageResize: {}, | ||
| iframe: {}, | ||
| }, | ||
| textAlign: "left", | ||
| children: [ | ||
| { | ||
| text: "[[[[EVD]] - Membrane invagination occurred ~6 seconds after scission protein (spHob1-GFP) was detected in budding yeast cells - [[@sun2019direct]]]]", | ||
| open: true, | ||
| order: 0, | ||
| uid: "tZnNCIgsk", | ||
| heading: 0, | ||
| viewType: "bullet", | ||
| blockViewType: "outline", | ||
| editTime: "2024-03-25T05:40:43.601Z", | ||
| props: { | ||
| imageResize: {}, | ||
| iframe: {}, | ||
| }, | ||
| textAlign: "left", | ||
| children: [], | ||
| parents: [0], | ||
| }, | ||
| { | ||
| text: "[[[[EVD]] - At fission yeast endocytic sites, scission protein (spHob1) first detected ~2 seconds before initiation of membrane invagination - [[@sun2019direct]]]]", | ||
| open: true, | ||
| order: 1, | ||
| uid: "i-rS06THC", | ||
| heading: 0, | ||
| viewType: "bullet", | ||
| blockViewType: "outline", | ||
| editTime: "2024-02-29T21:38:44.920Z", | ||
| props: { | ||
| imageResize: {}, | ||
| iframe: {}, | ||
| }, | ||
| textAlign: "left", | ||
| children: [], | ||
| parents: [0], | ||
| }, | ||
| { | ||
| text: "[[[[EVD]] - Actin appearance occurred 9 (+/-2) seconds prior to patch formation and disappears 10 (+/-2) seconds following patch development. [[@sirotkin2010quantitative]]]]", | ||
| open: true, | ||
| order: 2, | ||
| uid: "fiWpNvVM8", | ||
| heading: 0, | ||
| viewType: "bullet", | ||
| blockViewType: "outline", | ||
| editTime: "2024-02-29T21:38:54.473Z", | ||
| props: { | ||
| imageResize: {}, | ||
| iframe: {}, | ||
| }, | ||
| textAlign: "left", | ||
| children: [], | ||
| parents: [0], | ||
| }, | ||
| { | ||
| text: "[[[[EVD]] - At zero seconds, 7000 actin proteins associated with endocytic invagination - [[@sirotkin2010quantitative]]]]", | ||
| open: true, | ||
| order: 3, | ||
| uid: "nz8-Sd5a5", | ||
| heading: 0, | ||
| viewType: "bullet", | ||
| blockViewType: "outline", | ||
| editTime: "2024-02-29T21:39:03.540Z", | ||
| props: { | ||
| imageResize: {}, | ||
| iframe: {}, | ||
| }, | ||
| textAlign: "left", | ||
| children: [], | ||
| parents: [0], | ||
| }, | ||
| { | ||
| text: "", | ||
| open: true, | ||
| order: 4, | ||
| uid: "fEcOIBDD7", | ||
| heading: 0, | ||
| viewType: "bullet", | ||
| blockViewType: "outline", | ||
| editTime: "2024-02-29T21:39:31.790Z", | ||
| props: { | ||
| imageResize: {}, | ||
| iframe: {}, | ||
| }, | ||
| textAlign: "left", | ||
| children: [], | ||
| parents: [0], | ||
| }, | ||
| { | ||
| text: "actin assembly peaks (x) seconds before/after endocytic scission", | ||
| open: true, | ||
| order: 5, | ||
| uid: "xgfRsZ-Xb", | ||
| heading: 0, | ||
| viewType: "bullet", | ||
| blockViewType: "outline", | ||
| editTime: "2024-02-29T21:38:25.591Z", | ||
| props: { | ||
| imageResize: {}, | ||
| iframe: {}, | ||
| }, | ||
| textAlign: "left", | ||
| children: [ | ||
| { | ||
| text: "[[[[CLM]] - Actin assembly peaks 8 seconds before endocytic scission]]", | ||
| open: true, | ||
| order: 0, | ||
| uid: "URYHjVOwB", | ||
| heading: 0, | ||
| viewType: "bullet", | ||
| blockViewType: "outline", | ||
| editTime: "2024-02-29T21:48:24.324Z", | ||
| props: { | ||
| imageResize: {}, | ||
| iframe: {}, | ||
| }, | ||
| textAlign: "left", | ||
| children: [], | ||
| parents: [0], | ||
| }, | ||
| ], | ||
| parents: [0], | ||
| }, | ||
| ], | ||
| parents: [], | ||
| }, | ||
| { | ||
| text: "Notes", | ||
| open: true, | ||
| order: 1, | ||
| uid: "LVRwULrGC", | ||
| heading: 2, | ||
| viewType: "bullet", | ||
| blockViewType: "outline", | ||
| editTime: "2024-02-29T21:28:17.509Z", | ||
| props: { | ||
| imageResize: {}, | ||
| iframe: {}, | ||
| }, | ||
| textAlign: "left", | ||
| children: [ | ||
| { | ||
| text: "", | ||
| open: true, | ||
| order: 0, | ||
| uid: "aMAPTRui2", | ||
| heading: 0, | ||
| viewType: "bullet", | ||
| blockViewType: "outline", | ||
| editTime: "2024-03-07T22:57:13.411Z", | ||
| props: { | ||
| imageResize: {}, | ||
| iframe: {}, | ||
| }, | ||
| textAlign: "left", | ||
| children: [], | ||
| parents: [0], | ||
| }, | ||
| ], | ||
| parents: [], | ||
| }, | ||
| ]; | ||
|
|
||
| const blocks = serializedBlocks.map(deserializeTreeNode); | ||
|
|
||
| export const roamClaimFullMarkdownExample: { | ||
| title: string; | ||
| blocks: TreeNode[]; | ||
| full: CrossAppNode["content"]["full"]; | ||
| } = { | ||
| title, | ||
| blocks, | ||
| full: { | ||
| format: "text/markdown", | ||
| value: buildFullMarkdown({ title, blocks }), | ||
| }, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| 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 type { LocalContentDataInput } from "@repo/database/inputTypes"; | ||
|
|
||
| const FULL_MARKDOWN_OPTS = { | ||
| refs: true, | ||
| embeds: true, | ||
| simplifiedFilename: false, | ||
| removeSpecialCharacters: false, | ||
| maxFilenameLength: 64, | ||
| linkType: "alias", | ||
| allNodes: [] as DiscourseNode[], | ||
| }; | ||
|
|
||
| export const buildFullMarkdown = ({ | ||
| title, | ||
| blocks, | ||
| viewType = "bullet", | ||
| }: { | ||
| title: string; | ||
| blocks: TreeNode[]; | ||
| viewType?: ViewType; | ||
| }): string => { | ||
| const body = blocks | ||
| .filter((block) => !!block.text || !!block.children?.length) | ||
| .map((block) => | ||
| toMarkdown({ c: block, v: viewType, i: 0, opts: FULL_MARKDOWN_OPTS }), | ||
| ) | ||
| .join("\n") | ||
| .trim(); | ||
| return body ? `# ${title}\n\n${body}\n` : `# ${title}\n`; | ||
| }; | ||
|
|
||
| export const convertRoamNodeToFullContent = ({ | ||
| nodes, | ||
| }: { | ||
| nodes: RoamDiscourseNodeData[]; | ||
| }): 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", | ||
| }, | ||
| ]; | ||
| } catch (error) { | ||
| console.error( | ||
| `convertRoamNodeToFullContent: failed to build full markdown for ${node.source_local_id}:`, | ||
| error, | ||
| ); | ||
| return []; | ||
|
Comment on lines
+61
to
+66
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚩 Full content silently skipped on error doesn't propagate to caller When Was this helpful? React with 👍 or 👎 to provide feedback. |
||
| } | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For node types backed by an Embedding Block Ref,
getDiscourseNodeTypeWithSettingsBlockNodessetssource_local_idto the child block UID and stores that block's text innode.text; reading only.childrenhere serializes descendants but drops the source block itself. A block-backed discourse node with no children now uploads# <page title>as itsfullcontent, and one with children still omits the actual claim/evidence text, so imported materializations are incomplete.Useful? React with 👍 / 👎.