diff --git a/js/validation/index.js b/js/validation/index.js index 563a2e4..5d08495 100644 --- a/js/validation/index.js +++ b/js/validation/index.js @@ -1,106 +1,105 @@ /** * Copyright (C) 2020 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ /* * Reads a Codemeta file and shows human-friendly errors on it. * * This validator intentionaly does not use a schema, in order to show errors * that are easy to understand for users with no understanding of JSON-LD. */ function validateDocument(doc) { if (!Array.isArray(doc) && typeof doc != 'object') { setError("Document must be an object (starting and ending with { and }), not ${typeof doc}.") return false; } // TODO: validate id/@id context = doc["@context"]; if (context == "https://doi.org/10.5063/schema/codemeta-2.0") { // Correct } else if (Array.isArray(context) && context.includes("https://doi.org/10.5063/schema/codemeta-2.0")) { if (context.length !== 1) { setError(`Multiple values in @context are not supported (@context should be "https://doi.org/10.5063/schema/codemeta-2.0", not ${JSON.stringify(context)})`); return false; } } else { setError(`@context must be "https://doi.org/10.5063/schema/codemeta-2.0", not ${JSON.stringify(context)}`); return false; } // TODO: check there is either type or @type but not both var type = getDocumentType(doc); if (type === undefined) { setError("Missing type (must be SoftwareSourceCode or SoftwareApplication).") return false; } else if (!isCompactTypeEqual(type, "SoftwareSourceCode") && !isCompactTypeEqual(type, "SoftwareApplication")) { // Check this before other fields, as a wrong type error is more // understandable than "invalid field". setError(`Wrong document type: must be "SoftwareSourceCode"/"SoftwareApplication", not ${JSON.stringify(type)}`) return false; } else { return Object.entries(doc).every((entry) => { var fieldName = entry[0]; var subdoc = entry[1]; if (fieldName == "@context") { // Was checked before return true; } else if (fieldName == "type" || fieldName == "@type") { // Was checked before return true; } else { var validator = softwareFieldValidators[fieldName]; if (validator === undefined) { // TODO: find if it's a field that belongs to another type, // and suggest that to the user setError(`Unknown field "${fieldName}".`) return false; } else { return validator(fieldName, subdoc); } } }); } } async function parseAndValidateCodemeta(showPopup) { var codemetaText = document.querySelector('#codemetaText').innerText; let parsed, doc; try { parsed = 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.`); return; } setError(""); var isValid = validateDocument(parsed); if (showPopup) { if (isValid) { alert('Document is valid!') } else { alert('Document is invalid.'); } } - const expanded = await jsonld.expand(parsed); - doc = await jsonld.compact(expanded, CODEMETA_CONTEXT_URL); + doc = await jsonld.compact(parsed, CODEMETA_CONTEXT_URL); return doc; }