diff --git a/apps/roam/src/utils/jsonld.ts b/apps/roam/src/utils/jsonld.ts index 9ce326880..ce0699a17 100644 --- a/apps/roam/src/utils/jsonld.ts +++ b/apps/roam/src/utils/jsonld.ts @@ -17,6 +17,7 @@ export const jsonLdContext = (baseUrl: string): Record => ({ 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", @@ -32,6 +33,7 @@ export const jsonLdContext = (baseUrl: string): Record => ({ relationDef: "dgb:RelationDef", relationInstance: "dgb:RelationInstance", inverseOf: "owl:inverseOf", + backlink: "dg:backlink", pages: `${baseUrl}/page/`, }); @@ -105,7 +107,10 @@ export const getJsonLdData = async ({ nodeLabelByType: Record; updateExportProgress: (progress: number) => Promise; }): Promise< - Record | Record[]> + Record< + string, + string | Record | Record[] + > > => { const roamUrl = canonicalRoamUrl(); const getRelationData = () => @@ -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>) + ) + .map((x) => x[0]) + .filter((x) => nodeSet.has(x)); + const r: Record = { + "@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( diff --git a/apps/website/public/schema/dg_base.ttl b/apps/website/public/schema/dg_base.ttl index cdbf659fa..b06b6d22a 100644 --- a/apps/website/public/schema/dg_base.ttl +++ b/apps/website/public/schema/dg_base.ttl @@ -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 diff --git a/apps/website/public/schema/dg_core.ttl b/apps/website/public/schema/dg_core.ttl index 0a12121a7..cbf70630f 100644 --- a/apps/website/public/schema/dg_core.ttl +++ b/apps/website/public/schema/dg_core.ttl @@ -3,11 +3,18 @@ @prefix : . @prefix dc: . @prefix owl: . -@prefix vs: . -@prefix sioc: . @prefix prov: . @prefix dgb: . @prefix dg: . +# http://purl.org/spar/po +@prefix po: . + + + 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; @@ -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.