Skip to content
Closed
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
10 changes: 10 additions & 0 deletions apps/roam/src/utils/jsonld.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,12 @@ export const getJsonLdData = async ({
Record<string, string | Record<string, string> | Record<string, string>[]>
> => {
const roamUrl = canonicalRoamUrl();
const roamUrlRe = new RegExp(roamUrl + "/page/([\\w\\d-]{9,10})\\b", "g");
const getRelationData = () =>
getRelationDataUtil({ allRelations, nodeLabelByType });
await updateExportProgress(0);
const pageData = getPageData({ results, allNodes });
const nodeUids = new Set(pageData.map((p) => p.uid));
const numPages = pageData.length + allNodes.length;
let numTreatedPages = 0;
const settings = {
Expand All @@ -138,6 +140,8 @@ export const getJsonLdData = async ({
...settings,
allNodes,
linkType: "roam url",
blockAnchors: true,
blockRefsAsLinks: true,
});
page.content = r.content;
numTreatedPages += 1;
Expand All @@ -153,6 +157,11 @@ export const getJsonLdData = async ({
error: `Unknown node type "${type}" for page "${text}"`,
});
}
const textRefersToNode = [
...new Set([...(content as string).matchAll(roamUrlRe)].map((r) => r[1])),
]
.filter((r) => nodeUids.has(r))
.map((r) => `pages:${r}`);
const r = {
"@id": `pages:${uid}`, // eslint-disable-line @typescript-eslint/naming-convention
"@type": nodeType ?? "nodeSchema", // eslint-disable-line @typescript-eslint/naming-convention
Expand All @@ -162,6 +171,7 @@ export const getJsonLdData = async ({
created: date.toJSON(),
creator: displayName,
};
if (textRefersToNode.length > 0) return { ...r, textRefersToNode };
return r;
});
const nodeSet = new Set(pageData.map((n) => n.uid));
Expand Down
54 changes: 41 additions & 13 deletions apps/roam/src/utils/pageToMarkdown.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BLOCK_REF_REGEX } from "roamjs-components/dom/constants";
import normalizePageTitle from "roamjs-components/queries/normalizePageTitle";
import getPageUidByBlockUid from "roamjs-components/queries/getPageUidByBlockUid";
import getTextByBlockUid from "roamjs-components/queries/getTextByBlockUid";
import getPageMetadata from "./getPageMetadata";
import getPageViewType from "roamjs-components/queries/getPageViewType";
Expand All @@ -20,6 +21,7 @@ import {
pullBlockToTreeNode,
collectUids,
} from "./exportUtils";
import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle";

const MATCHES_NONE = /$.+^/;

Expand Down Expand Up @@ -127,6 +129,8 @@ export const toMarkdown = ({
removeSpecialCharacters: boolean;
linkType: string;
flatten?: boolean;
blockRefsAsLinks?: boolean;
blockAnchors?: boolean;
};
}): string => {
const {
Expand All @@ -138,35 +142,53 @@ export const toMarkdown = ({
removeSpecialCharacters,
linkType,
flatten = false,
blockRefsAsLinks = false,
blockAnchors = false,
} = opts;
const processedText = c.text
.replace(embeds ? EMBED_REGEX : MATCHES_NONE, (_, blockUid) => {
.replace(embeds ? EMBED_REGEX : MATCHES_NONE, (_, blockUid: string) => {
const reference = getFullTreeByParentUid(blockUid);
return toMarkdown({ c: reference, i, v, opts });
})
.replace(embeds ? EMBED_CHILDREN_REGEX : MATCHES_NONE, (_, blockUid) => {
const reference = getFullTreeByParentUid(blockUid);
return reference.children
.map((child) => toMarkdown({ c: child, i, v, opts }))
.join("\n");
})
.replace(refs ? BLOCK_REF_REGEX : MATCHES_NONE, (_, blockUid) => {
const reference = getTextByBlockUid(blockUid);
return reference || blockUid;
.replace(
embeds ? EMBED_CHILDREN_REGEX : MATCHES_NONE,
(_, blockUid: string) => {
const reference = getFullTreeByParentUid(blockUid);
return reference.children
.map((child) => toMarkdown({ c: child, i, v, opts }))
.join("\n");
},
)
.replace(refs ? BLOCK_REF_REGEX : MATCHES_NONE, (_, blockUid: string) => {
const reference = getTextByBlockUid(blockUid) || blockUid;

if (blockRefsAsLinks) {
const pageUid = blockAnchors
? getPageUidByBlockUid(blockUid)
: blockUid;
if (pageUid === blockUid || pageUid === "")
return toLink(reference, blockUid, linkType);
else
// Note that the roam anchor follows a more complex pattern
// Here using the block anchor as target for internal export consistency
return toLink(reference, `${pageUid}#block-${blockUid}`, linkType);
} else return reference;
})
.replace(/{{\[\[TODO\]\]}}/g, v === "bullet" ? "[ ]" : "- [ ]")
.replace(/{{\[\[DONE\]\]}}/g, v === "bullet" ? "[x]" : "- [x]")
.replace(/\_\_(.+?)\_\_/g, "_$1_") // convert Roam italics __ to markdown italics _
.replace(/(?<!\n)```/g, "\n```") // Add line break before last code blocks
.trim();
const finalProcessedText =
simplifiedFilename || removeSpecialCharacters
simplifiedFilename || removeSpecialCharacters || blockRefsAsLinks
? XRegExp.matchRecursive(processedText, "#?\\[\\[", "\\]\\]", "i", {
valueNames: ["between", "left", "match", "right"],
unbalanced: "skip",
})
.map((s) => {
if (s.name === "match") {
const pageUid = getPageUidByPageTitle(s.value);
if (pageUid.length > 0) return toLink(s.value, pageUid, linkType);
const name = getFilename({
title: s.value,
allNodes,
Expand Down Expand Up @@ -205,8 +227,8 @@ export const toMarkdown = ({
})
.join("");
const lineBreak = v === "document" ? "\n" : "";

return `${indentation}${viewTypePrefix}${headingPrefix}${finalProcessedText}${lineBreak}${childrenMarkdown}`;
const blockAnchor = blockAnchors ? `{#block-${c.uid}}` : "";
return `${indentation}${viewTypePrefix}${headingPrefix}${blockAnchor}${finalProcessedText}${lineBreak}${childrenMarkdown}`;
};

export const pageToMarkdown = async (
Expand All @@ -222,6 +244,8 @@ export const pageToMarkdown = async (
maxFilenameLength,
removeSpecialCharacters,
linkType,
blockRefsAsLinks = false,
blockAnchors = false,
}: {
includeDiscourseContext: boolean;
appendRefNodeContext: boolean;
Expand All @@ -233,6 +257,8 @@ export const pageToMarkdown = async (
maxFilenameLength: number;
removeSpecialCharacters: boolean;
linkType: string;
blockRefsAsLinks?: boolean;
blockAnchors?: boolean;
},
): Promise<{ title: string; content: string; uids: Set<string> }> => {
const v = getPageViewType(text) || "bullet";
Expand Down Expand Up @@ -287,6 +313,8 @@ export const pageToMarkdown = async (
maxFilenameLength,
removeSpecialCharacters,
linkType,
blockAnchors,
blockRefsAsLinks,
},
}),
)
Expand Down