Skip to content
Open
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
71 changes: 46 additions & 25 deletions apps/roam/src/utils/jsonld.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const jsonLdContext = (baseUrl: string): Record<string, string> => ({
prov: "http://www.w3.org/ns/prov#",
sioc: "http://rdfs.org/sioc/ns#",
dgb: "https://discoursegraphs.com/schema/dg_base",
dg: "https://discoursegraphs.com/schema/dg_core",
subClassOf: "rdfs:subClassOf",
title: "dc:title",
label: "rdfs:label",
Expand All @@ -32,6 +33,7 @@ export const jsonLdContext = (baseUrl: string): Record<string, string> => ({
relationDef: "dgb:RelationDef",
relationInstance: "dgb:RelationInstance",
inverseOf: "owl:inverseOf",
backlink: "dg:backlink",
pages: `${baseUrl}/page/`,
});

Expand Down Expand Up @@ -105,7 +107,10 @@ export const getJsonLdData = async ({
nodeLabelByType: Record<string, string>;
updateExportProgress: (progress: number) => Promise<void>;
}): Promise<
Record<string, string | Record<string, string> | Record<string, string>[]>
Record<
string,
string | Record<string, string> | Record<string, string | string[]>[]
>
> => {
const roamUrl = canonicalRoamUrl();
const getRelationData = () =>
Expand All @@ -131,40 +136,56 @@ export const getJsonLdData = async ({
.filter((s) => s.content !== undefined)
.map((node) => [node.label, node["@id"]]),
);
const nodeSet = new Set(pageData.map((n) => n.uid));

await Promise.all(
const nodes = await Promise.all(
pageData.map(async (page: Result) => {
const r = await pageToMarkdown(page, {
const md = await pageToMarkdown(page, {
...settings,
allNodes,
linkType: "roam url",
});
page.content = r.content;
const { content } = md;
page.content = content;
const { text, uid, type } = page;
const { date, displayName, modified } = getPageMetadata(text);
const nodeType = nodeSchemaUriByName[type as string];
if (!nodeType) {
internalError({
error: `Unknown node type "${type as string}" for page "${text}"`,
});
}
const backlinks = (
await (window.roamAlphaAPI.data.backend.q(
`[:find ?uid
:where
[?page :block/uid "${uid}"]
[?block :block/page ?page]
[or [?refBlock :block/refs ?block] [?refBlock :block/refs ?page]]
[?refBlock :block/page ?refPage]
[?refPage :block/uid ?uid]
]`,
) as Promise<Array<[string]>>)
)
.map((x) => x[0])
.filter((x) => nodeSet.has(x));
const r: Record<string, string | string[]> = {
"@id": `pages:${uid}`, // eslint-disable-line @typescript-eslint/naming-convention
"@type": nodeType, // eslint-disable-line @typescript-eslint/naming-convention
title: text,
content,
modified: modified?.toJSON(),
created: date.toJSON(),
creator: displayName,
};
if (backlinks.length > 0) {
r["backlinks"] = backlinks.map((x) => `pages:${x}`);
}
numTreatedPages += 1;
await updateExportProgress(0.1 + (numTreatedPages / numPages) * 0.75);
return r;
}),
);

const nodes = pageData.map(({ text, uid, content, type }) => {
const { date, displayName, modified } = getPageMetadata(text);
const nodeType = nodeSchemaUriByName[type];
if (!nodeType) {
internalError({
error: `Unknown node type "${type}" for page "${text}"`,
});
}
const r = {
"@id": `pages:${uid}`, // eslint-disable-line @typescript-eslint/naming-convention
"@type": nodeType ?? "nodeSchema", // eslint-disable-line @typescript-eslint/naming-convention
title: text,
content: content as string,
modified: modified?.toJSON(),
created: date.toJSON(),
creator: displayName,
};
return r;
});
const nodeSet = new Set(pageData.map((n) => n.uid));
const rels = await getRelationData();
await updateExportProgress(1);
const relations = uniqJsonArray(
Expand Down
5 changes: 0 additions & 5 deletions apps/website/public/schema/dg_base.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,6 @@ dgb:destination a dgb:Role ;
rdfs:range dgb:NodeSchema ;
rdfs:comment "The destination of a binary relation"@en .

dgb:textRefersToNode a owl:ObjectProperty;
rdfs:domain dgb:NodeSchema;
rdfs:range dgb:NodeSchema;
rdfs:comment "The text of a node refers to another node"@en .


# examples

Expand Down
23 changes: 21 additions & 2 deletions apps/website/public/schema/dg_core.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@
@prefix : <http://www.w3.org/2000/01/rdf-schema#> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix vs: <http://www.w3.org/2003/06/sw-vocab-status/ns#> .
@prefix sioc: <http://rdfs.org/sioc/ns#> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix dgb: <https://discoursegraphs.com/schema/dg_base#> .
@prefix dg: <https://discoursegraphs.com/schema/dg_core#> .
# http://purl.org/spar/po
@prefix po: <http://www.essepuntato.it/2008/12/pattern#> .

<https://discoursegraphs.com/schema/dg_core#>
dc:date "2025-12-31" ;
rdfs:comment "DiscourseGraph core vocabulary"@en ;
rdfs:label "DiscourseGraph core vocabulary"@en ;
owl:versionInfo "0 (tentative)" ;
a owl:Ontology.

dg:Question a dgb:NodeSchema;
rdfs:label "Question"@en;
Expand Down Expand Up @@ -90,3 +97,15 @@ dg:curatedFrom a dgb:RelationDef;
rdfs:label "Curated from"@en;
rdfs:range dg:Evidence;
rdfs:domain dg:Source.

dg:containsRec a owl:TransitiveProperty.
po:contains rdfs:subPropertyOf dg:containsRec.
dc:hasPart rdfs:subPropertyOf dg:containsRec.

dg:containsRef a owl:ObjectProperty;
owl:propertyChainAxiom (dg:containsRec dc:references);
rdfs:label "Contains a reference to"@en.

dg:backlink a owl:ObjectProperty;
owl:inverseOf dg:containsRef;
rdfs:label "is referred by"@en.