From ae70f9a311d85fb040be7700b168023024dc73ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9l=C3=A8ne=20MJ?= <20780121+hjonin@users.noreply.github.com> Date: Wed, 8 May 2024 17:20:57 +0200 Subject: [PATCH] Replace codemeta-local.jsonld with concatenated contexts (#47) --- data/contexts/codemeta-local.jsonld | 92 ----------------------------- js/codemeta_generation.js | 34 ++++++++--- js/validation/index.js | 11 ++-- 3 files changed, 29 insertions(+), 108 deletions(-) delete mode 100644 data/contexts/codemeta-local.jsonld diff --git a/data/contexts/codemeta-local.jsonld b/data/contexts/codemeta-local.jsonld deleted file mode 100644 index e6a30f8..0000000 --- a/data/contexts/codemeta-local.jsonld +++ /dev/null @@ -1,92 +0,0 @@ -{ - "@context": { - "type": "@type", - "id": "@id", - "schema":"http://schema.org/", - "codemeta": "https://codemeta.github.io/terms/", - "Organization": {"@id": "schema:Organization"}, - "Person": {"@id": "schema:Person"}, - "Review": {"@id": "schema:Review"}, - "Role": {"@id": "schema:Role"}, - "SoftwareSourceCode": {"@id": "schema:SoftwareSourceCode"}, - "SoftwareApplication": {"@id": "schema:SoftwareApplication"}, - "Text": {"@id": "schema:Text"}, - "URL": {"@id": "schema:URL"}, - "address": { "@id": "schema:address"}, - "affiliation": { "@id": "schema:affiliation"}, - "applicationCategory": { "@id": "schema:applicationCategory", "@type": "@id"}, - "applicationSubCategory": { "@id": "schema:applicationSubCategory", "@type": "@id"}, - "citation": { "@id": "schema:citation"}, - "codeRepository": { "@id": "schema:codeRepository", "@type": "@id"}, - "contributor": { "@id": "schema:contributor"}, - "copyrightHolder": { "@id": "schema:copyrightHolder"}, - "copyrightYear": { "@id": "schema:copyrightYear"}, - "creator": { "@id": "schema:creator"}, - "dateCreated": {"@id": "schema:dateCreated", "@type": "schema:Date" }, - "dateModified": {"@id": "schema:dateModified", "@type": "schema:Date" }, - "datePublished": {"@id": "schema:datePublished", "@type": "schema:Date" }, - "description": { "@id": "schema:description"}, - "downloadUrl": { "@id": "schema:downloadUrl", "@type": "@id"}, - "email": { "@id": "schema:email"}, - "editor": { "@id": "schema:editor"}, - "encoding": { "@id": "schema:encoding"}, - "endDate": { "@id": "schema:endDate"}, - "familyName": { "@id": "schema:familyName"}, - "fileFormat": { "@id": "schema:fileFormat", "@type": "@id"}, - "fileSize": { "@id": "schema:fileSize"}, - "funder": { "@id": "schema:funder"}, - "givenName": { "@id": "schema:givenName"}, - "hasPart": { "@id": "schema:hasPart" }, - "identifier": { "@id": "schema:identifier", "@type": "@id"}, - "installUrl": { "@id": "schema:installUrl", "@type": "@id"}, - "isAccessibleForFree": { "@id": "schema:isAccessibleForFree"}, - "isPartOf": { "@id": "schema:isPartOf"}, - "keywords": { "@id": "schema:keywords"}, - "license": { "@id": "schema:license", "@type": "@id"}, - "memoryRequirements": { "@id": "schema:memoryRequirements", "@type": "@id"}, - "name": { "@id": "schema:name"}, - "operatingSystem": { "@id": "schema:operatingSystem"}, - "permissions": { "@id": "schema:permissions"}, - "position": { "@id": "schema:position"}, - "processorRequirements": { "@id": "schema:processorRequirements"}, - "producer": { "@id": "schema:producer"}, - "programmingLanguage": { "@id": "schema:programmingLanguage"}, - "provider": { "@id": "schema:provider"}, - "publisher": { "@id": "schema:publisher"}, - "relatedLink": { "@id": "schema:relatedLink", "@type": "@id"}, - "review": { "@id": "schema:review", "@type": "@id" }, - "reviewAspect": { "@id": "schema:reviewAspect" }, - "reviewBody": { "@id": "schema:reviewBody" }, - "releaseNotes": { "@id": "schema:releaseNotes"}, - "roleName": { "@id": "schema:roleName"}, - "runtimePlatform": { "@id": "schema:runtimePlatform"}, - "sameAs": { "@id": "schema:sameAs", "@type": "@id"}, - "softwareHelp": { "@id": "schema:softwareHelp"}, - "softwareRequirements": { "@id": "schema:softwareRequirements", "@type": "@id"}, - "softwareVersion": { "@id": "schema:softwareVersion"}, - "sponsor": { "@id": "schema:sponsor"}, - "startDate": { "@id": "schema:startDate"}, - "storageRequirements": { "@id": "schema:storageRequirements", "@type": "@id"}, - "supportingData": { "@id": "schema:supportingData"}, - "targetProduct": { "@id": "schema:targetProduct"}, - "url": { "@id": "schema:url", "@type": "@id"}, - "version": { "@id": "schema:version"}, - - "author": { "@id": "schema:author", "@container": "@list" }, - - "softwareSuggestions": { "@id": "codemeta:softwareSuggestions", "@type": "@id"}, - "contIntegration": { "@id": "codemeta:contIntegration", "@type": "@id"}, - "continuousIntegration": { "@id": "codemeta:continuousIntegration", "@type": "@id"}, - "buildInstructions": { "@id": "codemeta:buildInstructions", "@type": "@id"}, - "developmentStatus": { "@id": "codemeta:developmentStatus", "@type": "@id"}, - "embargoDate": { "@id":"codemeta:embargoDate", "@type": "schema:Date" }, - "embargoEndDate": { "@id":"codemeta:embargoEndDate", "@type": "schema:Date" }, - "funding": { "@id": "codemeta:funding" }, - "readme": { "@id":"codemeta:readme", "@type": "@id" }, - "issueTracker": { "@id":"codemeta:issueTracker", "@type": "@id" }, - "referencePublication": { "@id": "codemeta:referencePublication", "@type": "@id"}, - "maintainer": { "@id": "codemeta:maintainer" }, - "hasSourceCode": { "@id": "codemeta:hasSourceCode", "@type": "@id"}, - "isSourceCodeOf": { "@id": "codemeta:isSourceCodeOf", "@type": "@id"} - } -} diff --git a/js/codemeta_generation.js b/js/codemeta_generation.js index 6366558..3048d83 100644 --- a/js/codemeta_generation.js +++ b/js/codemeta_generation.js @@ -7,8 +7,6 @@ "use strict"; -const LOCAL_CONTEXT_PATH = "./data/contexts/codemeta-local.jsonld"; -const LOCAL_CONTEXT_URL = "local"; const CODEMETA_CONTEXTS = { "2.0": { path: "./data/contexts/codemeta-2.0.jsonld", @@ -23,14 +21,12 @@ const CODEMETA_CONTEXTS = { const SPDX_PREFIX = 'https://spdx.org/licenses/'; const loadContextData = async () => { - const [contextLocal, contextV2, contextV3] = + const [contextV2, contextV3] = await Promise.all([ - fetch(LOCAL_CONTEXT_PATH).then(response => response.json()), fetch(CODEMETA_CONTEXTS["2.0"].path).then(response => response.json()), fetch(CODEMETA_CONTEXTS["3.0"].path).then(response => response.json()) ]); return { - [LOCAL_CONTEXT_URL]: contextLocal, [CODEMETA_CONTEXTS["2.0"].url]: contextV2, [CODEMETA_CONTEXTS["3.0"].url]: contextV3 } @@ -54,6 +50,10 @@ const initJsonldLoader = contexts => { jsonld.documentLoader = getJsonldCustomLoader(contexts); }; +const getAllCodemetaContextUrls= () => { + return Object.values(CODEMETA_CONTEXTS).map(context => context.url); +} + function emptyToUndefined(v) { if (v == null || v == "") return undefined; @@ -217,9 +217,9 @@ function generateReview() { return doc; } -async function buildExpandedJson() { +async function buildExpandedDocWithAllContexts() { var doc = { - "@context": LOCAL_CONTEXT_URL, + "@context": getAllCodemetaContextUrls(), "@type": "SoftwareSourceCode", }; @@ -274,7 +274,9 @@ async function generateCodemeta(codemetaVersion = "2.0") { var codemetaText, errorHTML; if (inputForm.checkValidity()) { - const expanded = await buildExpandedJson(); + // Expand document with all contexts before compacting + // to allow generating property from any context + const expanded = await buildExpandedDocWithAllContexts(); const compacted = await jsonld.compact(expanded, CODEMETA_CONTEXTS[codemetaVersion].url); codemetaText = JSON.stringify(compacted, null, 4); errorHTML = ""; @@ -380,9 +382,23 @@ function importPersons(prefix, legend, docs) { }); } +async function recompactDocWithAllContexts(doc) { + const allContexts = getAllCodemetaContextUrls(); + const newDoc = structuredClone(doc); + newDoc["@context"] = allContexts; + const expanded = await jsonld.expand(newDoc); + const compacted = await jsonld.compact(expanded, allContexts); + return compacted; +} + async function importCodemeta() { var inputForm = document.querySelector('#inputForm'); - var doc = await parseAndValidateCodemeta(false); + var doc = parseAndValidateCodemeta(false); + + // Re-compact document with all contexts + // to allow importing property from any context + doc = await recompactDocWithAllContexts(doc); + resetForm(); if (doc['license'] !== undefined) { diff --git a/js/validation/index.js b/js/validation/index.js index 4035f8c..60ed250 100644 --- a/js/validation/index.js +++ b/js/validation/index.js @@ -65,12 +65,12 @@ function validateDocument(doc) { } -async function parseAndValidateCodemeta(showPopup) { +function parseAndValidateCodemeta(showPopup) { var codemetaText = document.querySelector('#codemetaText').innerText; - let parsed, doc; + var doc; try { - parsed = JSON.parse(codemetaText); + doc = JSON.parse(codemetaText); } catch (e) { setError(`Could not read codemeta document because it is not valid JSON (${e}). Check for missing or extra quote, colon, or bracket characters.`); @@ -79,7 +79,7 @@ async function parseAndValidateCodemeta(showPopup) { setError(""); - var isValid = validateDocument(parsed); + var isValid = validateDocument(doc); if (showPopup) { if (isValid) { alert('Document is valid!') @@ -89,8 +89,5 @@ async function parseAndValidateCodemeta(showPopup) { } } - parsed["@context"] = LOCAL_CONTEXT_URL; - const expanded = await jsonld.expand(parsed); - doc = await jsonld.compact(expanded, LOCAL_CONTEXT_URL); return doc; }