From c9ceb47da331c4ceed3aac773745678def7fe36b Mon Sep 17 00:00:00 2001 From: Howard Askew <19271569+howaskew@users.noreply.github.com> Date: Wed, 21 Oct 2026 10:54:45 +0100 Subject: [PATCH] Generate only schema.org and OpenActive terms from the schema.org vocabulary Recent schema.org releases (since data-models 3.0.10, which uses 30.1) also declare classes and properties from other vocabularies that schema.org terms are mapped to, such as snomed:, gs1:, dct:, og:, unece: and fibo-*. data-models 3.0.9's vocabulary had none. The generators turned them into library code, which broke every library: - classes named after SNOMED codes (e.g. "63653004") are invalid in TypeScript, PHP and Ruby - dct:description, gs1:description and og:description produce duplicate "Description" members in the property enumeration (45 duplicates in C#, 3 duplicate constants in PHP) Skip non-schema.org classes and properties when reading the schema.org vocabulary, drop links from schema.org classes to the skipped parent classes (otherwise resolving primary parents never completes), and keep only schema.org and OpenActive properties in the property enumeration. Against data-models 3.0.10 the generated libraries now differ from 3.0.9 only by new schema.org terms (and schema:Quantity, which schema.org 30.1 turned into a data type). Co-Authored-By: Claude Opus 5.5 (1M context) --- src/generator.js | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/generator.js b/src/generator.js index a387abf..6979fef 100644 --- a/src/generator.js +++ b/src/generator.js @@ -758,8 +758,12 @@ class Generator { createPropertiesEnumFile(enumType) { console.log("Generating enum ", enumType); - // Create enum values from property list - const values = [...getProperties()].map(value => ({ + // Create enum values from property list. Recent schema.org releases also map to properties from other + // vocabularies (e.g. http://purl.org/dc/terms/description), which would duplicate names such as + // "Description", so keep only schema.org and OpenActive properties. + const values = [...getProperties()] + .filter(value => value.startsWith("https://schema.org/") || value.startsWith("https://openactive.io/")) + .map(value => ({ memberVal: value, value: this.convertToClassName(this.getPropNameFromFQP(value)) })); @@ -870,6 +874,28 @@ class Generator { augmentWithExtension(extension) { let { graph: extModelGraph, prefix: extensionPrefix } = extension; + // Recent schema.org releases also declare terms from other vocabularies (e.g. snomed:, gs1:, dct:, + // fibo-*:) that schema.org terms are mapped to. They are not schema.org or OpenActive terms, and they + // produce invalid or duplicate names in the generated libraries (e.g. a class named "63653004", or + // dct:description and gs1:description alongside schema:description). Only generate schema.org's own + // terms, and drop links from schema.org classes to the skipped classes, so that inheritance is + // unchanged from earlier schema.org releases. + if (extensionPrefix === "schema") { + const isExternal = node => !String(node.id).startsWith("schema:"); + const skippedIds = new Set( + extModelGraph.filter(node => (node.type === "Class" || node.type === "Property") && isExternal(node)).map(node => node.id) + ); + extModelGraph = extModelGraph.filter(node => !skippedIds.has(node.id)); + // Also used afterwards by augmentEnumsWithExtension + extension.graph = extModelGraph; + extModelGraph.forEach(node => { + if (node.subClassOf) { + const parents = (Array.isArray(node.subClassOf) ? node.subClassOf : [node.subClassOf]).filter(id => !skippedIds.has(id)); + node.subClassOf = parents; + } + }); + } + // Add classes first extModelGraph.forEach(node => { if (!node.subClassOf) {