Skip to content
Open
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
84 changes: 62 additions & 22 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ export function getSchemaUrl(schemaName, version) {
// check for query param override
const schemas_url = getSearchParam("schemas");
// Use raw github URL since the link will also display in the browser
let baseUrl = `https://raw.githubusercontent.com/ome/ngff-spec/${version}/schemas`;
// let baseUrl = `https://raw.githubusercontent.com/ome/ngff-spec/${version}/schemas`;
let baseUrl = `https://ngff--581.org.readthedocs.build/${version}/schemas`;
if (schemas_url) {
baseUrl = schemas_url;
} else if (version.startsWith("0.6")) {
baseUrl = "https://raw.githubusercontent.com/ome/ngff-spec/refs/heads/main/schemas";
}
if (baseUrl.endsWith("/")) {
baseUrl = baseUrl.slice(0, -1);
Expand Down Expand Up @@ -248,6 +247,23 @@ export function validateData(schema, jsonData, extraSchemas) {
return errors;
}

function getRefs(jsonSchema) {
// Return an array of $ref values found in the JSON schema.
let refs = [];
function findRefs(obj) {
if (typeof obj !== "object" || obj === null) return;
for (const key in obj) {
if (key === "$ref" && !refs.includes(obj[key])) {
refs.push(obj[key]);
} else {
findRefs(obj[key]);
}
}
}
findRefs(jsonSchema);
return refs;
}

export async function validate(jsonData) {
// get version, lookup schema, do validation...
// v0.5+ unwrap the attrs under "attributes.ome"
Expand Down Expand Up @@ -278,29 +294,53 @@ export async function validate(jsonData) {
}

let refSchemas = [];
// TODO: need to know whether to load other schemas...
// For now, we can use version check...
if (version === "0.5") {
const versionSchema = await getSchema(getSchemaUrl("_version", version));
// const schemaSchema = await getSchema(getSchemaUrl("_schema_url", version));
refSchemas = [versionSchema];
// For version 0.5+, we validate the "attributes" content.
// If no "attributes" exist, then it will be assumed this is v0.4 data (see above)

if (jsonData.attributes) {
jsonData = jsonData.attributes;
}

if (version.startsWith("0.6")) {
refSchemas = [];
// Since the image.schema has $id: https://ngff.openmicroscopy.org/0.6rc0/schemas/image.schema
// and contains "$ref": "coordinate_systems.schema" etc
// We need to use the same URL prefix for all those $ref schemas
const names = ["coordinate_transformations", "coordinate_systems", "axes", "_version"];
for(const name of names) {
const schema = await getSchema(getSchemaUrl(name, version));
schema["$id"] = `https://ngff.openmicroscopy.org/0.6rc0/schemas/${name}.schema`;
refSchemas.push(schema);
// Before we validate, need to load any additional schemas
// found under $refs...
let refs = [];
for (let s=0; s<schemaUrls.length; s++) {
let schema = await getSchema(schemaUrls[s]);
for (let ref of getRefs(schema)) {
// ignore local references within the same schema
if (!ref.startsWith("#") && !refs.includes(ref)) {
refs.push(ref.split("#")[0]);
}
}
}

let loadedNames = [];
let refIndex = 0;
// We process the refs list, while also adding to it...
while (refIndex < refs.length) {
let ref = refs[refIndex];
refIndex++;
const match = ref.match(/schemas\/([a-z_]+)\.schema/);
if (match) {
const name = match[1];
if (!loadedNames.includes(name)) {
// load the schema and populate refSchemas
const refSchemaUrl = getSchemaUrl(name, version);
const refSchema = await getSchema(refSchemaUrl);
refSchema["$id"] = ref;
refSchemas.push(refSchema);
loadedNames.push(name);

// keep adding any new refs to the list
for (let newRef of getRefs(refSchema)) {
if (!newRef.startsWith("#") && !refs.includes(newRef.split("#")[0])) {
// handle e.g. $ref: "axes.schema"
if (!newRef.startsWith("http")) {
newRef = ref.split("schemas")[0] + "schemas/" + newRef;
}
refs.push(newRef.split("#")[0]);
}
}
}
}
jsonData = jsonData.attributes;
}

let errors = [];
Expand Down
Loading