Skip to content

Exports and mappings ​

All exports run in the browser, in the backend's services/transformers/ folder. TransformationApplicationService is the facade; DocumentRecord exposes it per document as exportMarkdown(), exportHtml(), exportPdfBlob() and exportJsonLd(). In the standalone editor, src/standalone/utils/documentExport.ts turns the selected format into a file download.

FormatFunctionHow
JSONnoneThe stored document data as is (with its $schema).
MarkdowndocumentToMarkdownWalks the document data and writes headings, lists and tables. Labels come from the profile (labelSingularEn, labelPluralEn). Ends with a SideDoc attribution footer.
HTMLdocumentToHtmlConverts the Markdown with marked, wraps it in a standalone HTML page with DEFAULT_DOCUMENT_EXPORT_CSS (or your own CSS). Links pass through safeHref.
PDFhtmlToPdfBlobLays the HTML out as text (headings, paragraphs, bullets) with pdf-lib and the standard Helvetica fonts. URLs get link annotations. Characters outside WinAnsi are transliterated or replaced.
JSON-LDdocumentToJsonLd on the serviceApplies a declarative RDF mapping. Today the only target is DCAT-AP 3.0.

The toolbar offers JSON-LD only for profiles whose id starts with ds: (datasheet) or dcatap: (DCAT-AP dataset), the two sources that have a mapping. It is labelled experimental.

RDF mappings ​

The JSON-LD export is data driven. A mapping file says, per source field, where the value goes in the RDF output and how to convert it. The engine (transformers/rdf/rdf-mapping-engine.ts) is a generic interpreter that does not name any vocabulary itself; every RDF term comes from the mapping.

Where the files live ​

Mapping files are authored in the schemas repository, next to the profiles they map:

text
schemas/rdf-targets/dcat-ap/
├── datasheet-v2.dcat-ap.mapping.json         datasheet (ds:) -> DCAT-AP
├── dcat-ap-dataset.dcat-ap.mapping.json      dcat-ap-dataset (dcatap:) -> DCAT-AP
├── *.target-extension.json                   extension terms used by the mappings
└── *.md                                      mapping notes, open SHACL issues

The backend cannot read files at run time, so scripts/sync-dcat-mappings.mjs copies every *.dcat-ap.mapping.json to app/sidedoc-backend/src/lib/application/services/transformers/dcat/<name>.dcat-ap.mapping.generated.json. It checks that each file parses and fails the build if one does not. It runs as part of prebuild (npm run build:dcat-mappings runs it on its own) and needs SIDEDOC_SCHEMAS_DIR. The generated files are committed, so builds without a schemas checkout still have them. Do not edit the generated copies: change the file in the schemas repository and sync.

scripts/dcat-map.mjs runs the same engine from the command line, against the built dist/:

sh
npm run build -w @sidedoc/backend
node app/sidedoc-backend/scripts/dcat-map.mjs <mapping.json> <document.json> <out.jsonld>

The registry ​

transformers/rdf/rdf-mapping-registry.ts lists which (source profile, target model) pairs exist, in RDF_MAPPING_MATRIX. Each entry has the profile id prefixes it accepts (ds:, dcatap:), a target id (dcat-ap), a label and the imported mapping. findRdfMapping(profileId, target) returns the entry or null, and TransformationApplicationService.documentToJsonLd throws a clear error when there is none. availableRdfTargets(profileId) lists the targets for a profile.

To add a conversion: write the mapping file in the schemas repository, sync it, import the generated JSON in the registry and add one entry.

Mapping format ​

json
{
  "targetModelId": "dcat-ap-v3-ddchd",
  "sourceProfileId": "datasheet-v2",
  "rootType": "dcat:Dataset",
  "recordType": "dcat:CatalogRecord",
  "recordTopicProp": "foaf:primaryTopic",
  "vocab": { "label": "rdfs:label", "periodType": "dct:PeriodOfTime" },
  "rules": [
    {
      "id": "ds:f00100",
      "source": "#/title",
      "target": "dataset.dcterms:title",
      "cardinality": "1..*",
      "onMissing": "error",
      "extract": { "flatten": "unwrap", "as": "langLit" }
    }
  ]
}
  • rootType, recordType, recordTopicProp: types of the root node and of an optional record node (for statements about the datasheet itself), and the property that links them.
  • context: optional JSON-LD @context. Without it the engine uses a default with the common DCAT-family prefixes (dcat, dct, foaf, prov, skos, adms, spdx, vcard, ...).
  • vocab: logical names for RDF terms that the computed transforms use, so they contain no hard-coded vocabulary.
  • rules: one per field, usually with the profile's x-sidedoc id as id.
    • source: JSON pointer into the document (#/description/publisher).
    • target: dataset.<property> or record.<property>. dataset.<container>[*].<property> with a #/<container>/*/<leaf> source is a sub-rule for each item of an array container (for example distributions); the container itself is a rule with a container block.
    • extract: the declarative conversion. flatten (unwrap, flatItems, toArr, first, ...) selects the items; as (langLit, text, plain, markdownLit, iri, termNode, termOrLiteral, periodObject, typedDate, urlNode, ...) converts each item.
    • transform: one named computed transform for cases the DSL cannot express: checksumToSpdx, identifierToStructured, datesOrTermToTemporal, qualifiedRelationToDcat, agentOrRichTextToPublisher, agentToQualifiedAttribution, agentToVcardNode, sourceDataArrayToSourceStatements (KNOWN_TRANSFORM_NAMES).
    • fallback: where values go that cannot be mapped to the main target (for example a free-text value next to a structured one).
    • markdownTo: extra target for the Markdown version of a RichText value.
    • action: "drop": an explicit "not exported" entry.
    • cardinality, onMissing, note: documentation and checks.

validateMapping(mapping) checks that every rule has an id, source and target, that ids are unique and that named transforms exist. __tests__/unit/services/dcat-mapping-validation.test.ts runs it on the bundled mappings, and rdf-mapping-engine-coverage.test.ts and dcat-export.test.ts check the output against example datasheets from the schemas repository. SHACL validation of the output against DCAT-AP is done in the schemas repository (scripts/validate_dcatap.py).

The current state of the DCAT-AP alignment, and which mapping gaps are still open, is tracked in the mapping notes in rdf-targets/dcat-ap/.