Skip to content

Commit

Permalink
Add referenced node to exported discourse context (#246)
Browse files Browse the repository at this point in the history
* append source node to discourse context

* add export setting

* sp
  • Loading branch information
mdroidian authored Apr 8, 2024
1 parent a9c5c30 commit 2d7eb25
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 8 deletions.
7 changes: 7 additions & 0 deletions src/discourseGraphsMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,13 @@ const initializeDiscourseGraphsMode = async (args: OnloadArgs) => {
items: ["alias", "wikilinks"],
},
} as Field<SelectField>,
{
title: "append referenced node",
// @ts-ignore
Panel: FlagPanel,
description:
"If a referenced node is defined in a node's format, it will be appended to the discourse context",
},
],
},
],
Expand Down
55 changes: 53 additions & 2 deletions src/utils/formatUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import discourseNodeFormatToDatalog from "./discourseNodeFormatToDatalog";
import createOverlayRender from "roamjs-components/util/createOverlayRender";
import { render as renderToast } from "roamjs-components/components/Toast";
import FormDialog from "roamjs-components/components/FormDialog";
import { QBClause, Result } from "./types";
import findDiscourseNode from "./findDiscourseNode";
import extractTag from "roamjs-components/util/extractTag";
import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle";

type FormDialogProps = Parameters<typeof FormDialog>[0];
const renderFormDialog = createOverlayRender<FormDialogProps>(
Expand Down Expand Up @@ -87,12 +91,21 @@ export const getNewDiscourseNodeText = async ({
};

export const getReferencedNodeInFormat = ({
format,
uid,
format: providedFormat,
discourseNodes = getDiscourseNodes(),
}: {
format: string;
uid?: string;
format?: string;
discourseNodes?: DiscourseNode[];
}) => {
let format = providedFormat;
if (!format) {
const discourseNode = findDiscourseNode(uid);
if (discourseNode) format = discourseNode.format;
}
if (!format) return null;

const regex = /{([\w\d-]*)}/g;
const matches = [...format.matchAll(regex)];

Expand All @@ -109,3 +122,41 @@ export const getReferencedNodeInFormat = ({

return null;
};

export const findReferencedNodeInText = ({
text,
discourseNode,
}: {
text: string;
discourseNode: DiscourseNode;
}) => {
// assumes that the referenced node in format has a specification
// which includes:
// has title relation
// a (.*?) pattern in it's target
// eg: Source: /^@(.*?)$/

const specification = discourseNode.specification;
const titleCondition = specification.find(
(s): s is QBClause => s.type === "clause" && s.relation === "has title"
);
if (!titleCondition) return null;

// Remove leading and trailing slashes and start/end modifiers
const patternStr = titleCondition.target.slice(1, -1).replace(/^\^|\$$/g, "");

// Since we assume there's always a (.*?), we replace it with a specific pattern to capture text within [[ ]]
// This assumes (.*?) is meant to capture the relevant content
const modifiedPatternStr = patternStr.replace(/\(\.\*\?\)/, "(.*?)");
const dynamicPattern = new RegExp(`\\[\\[${modifiedPatternStr}\\]\\]`, "g");
const match = text.match(dynamicPattern)?.[0] || "";
if (!match) return null;

const pageTitle = extractTag(match);
const uid = getPageUidByPageTitle(pageTitle);

return {
uid,
text: pageTitle,
} as Result;
};
63 changes: 57 additions & 6 deletions src/utils/getExportTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import getPageMetadata from "./getPageMetadata";
import getDiscourseContextResults from "./getDiscourseContextResults";
import fireQuery from "./fireQuery";
import { ExportTypes } from "./types";
import {
findReferencedNodeInText,
getReferencedNodeInFormat,
} from "./formatUtils";

export const updateExportProgress = (detail: {
progress: number;
Expand Down Expand Up @@ -219,6 +223,44 @@ const toMarkdown = ({
return `${indentation}${viewTypePrefix}${headingPrefix}${finalProcessedText}${lineBreak}${childrenMarkdown}`;
};

const handleDiscourseContext = async ({
includeDiscourseContext,
uid,
pageTitle,
isSamePageEnabled,
appendRefNodeContext,
}: {
includeDiscourseContext: boolean;
uid: string;
pageTitle: string;
isSamePageEnabled: boolean;
appendRefNodeContext: boolean;
}) => {
if (!includeDiscourseContext) return [];

const discourseResults = await getDiscourseContextResults({
uid,
isSamePageEnabled,
});
if (!appendRefNodeContext) return discourseResults;

const referencedDiscourseNode = getReferencedNodeInFormat({ uid });
if (referencedDiscourseNode) {
const referencedResult = findReferencedNodeInText({
text: pageTitle,
discourseNode: referencedDiscourseNode,
});
if (!referencedResult) return discourseResults;
const appendedContext = {
label: referencedDiscourseNode.text,
results: { [referencedResult.uid]: referencedResult },
};
return [...discourseResults, appendedContext];
}

return discourseResults;
};

type getExportTypesProps = {
results?: ExportDialogProps["results"];
exportId: string;
Expand Down Expand Up @@ -390,6 +432,10 @@ const getExportTypes = ({
tree: exportTree.children,
key: "resolve block embeds",
}).uid;
const appendRefNodeContext = !!getSubTree({
tree: exportTree.children,
key: "append referenced node",
}).uid;
const yaml = frontmatter.length
? frontmatter
: [
Expand All @@ -406,6 +452,7 @@ const getExportTypes = ({
maxFilenameLength,
removeSpecialCharacters,
linkType,
appendRefNodeContext,
};
};

Expand All @@ -424,6 +471,7 @@ const getExportTypes = ({
maxFilenameLength,
removeSpecialCharacters,
linkType,
appendRefNodeContext,
} = getExportSettings();
const allPages = await getPageData(
isSamePageEnabled,
Expand Down Expand Up @@ -452,12 +500,15 @@ const getExportTypes = ({
type,
};
const treeNode = getFullTreeByParentUid(uid);
const discourseResults = includeDiscourseContext
? await getDiscourseContextResults({
uid,
isSamePageEnabled,
})
: [];

const discourseResults = await handleDiscourseContext({
includeDiscourseContext,
pageTitle: text,
uid,
isSamePageEnabled,
appendRefNodeContext,
});

const referenceResults = isFlagEnabled("render references")
? (
window.roamAlphaAPI.data.fast.q(
Expand Down

0 comments on commit 2d7eb25

Please sign in to comment.