@unrdf/kgn 5.0.1 → 26.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +9207 -0
- package/package.json +33 -28
- package/src/base/filter-templates.js +7 -1
- package/src/base/index.js +15 -10
- package/src/base/injection-targets.js +6 -0
- package/src/base/macro-templates.js +6 -0
- package/src/base/shacl-templates.js +6 -0
- package/src/base/template-base.js +7 -1
- package/src/core/attestor.js +50 -1
- package/src/core/filters.js +134 -1
- package/src/core/index.js +8 -1
- package/src/core/kgen-engine.js +49 -1
- package/src/core/parser.js +52 -1
- package/src/core/post-processor.js +7 -1
- package/src/core/renderer.js +67 -1
- package/src/doc-generator/mdx-generator.mjs +1 -1
- package/src/doc-generator/nav-generator.mjs +1 -1
- package/src/doc-generator/rdf-builder.mjs +2 -2
- package/src/engine/index.js +9 -0
- package/src/engine/pipeline.js +7 -1
- package/src/engine/renderer.js +18 -3
- package/src/engine/template-engine.js +12 -3
- package/src/filters/array.js +14 -6
- package/src/filters/index.js +165 -17
- package/src/filters/rdf.js +3 -3
- package/src/{index.js → index.mjs} +46 -0
- package/src/index.test.mjs +40 -0
- package/src/inheritance/index.js +19 -1
- package/src/injection/atomic-writer.js +22 -1
- package/src/injection/idempotency-manager.js +33 -0
- package/src/injection/injection-engine.js +46 -1
- package/src/injection/integration.js +3 -3
- package/src/injection/modes/index.js +30 -0
- package/src/injection/rollback-manager.js +26 -2
- package/src/injection/target-resolver.js +48 -3
- package/src/injection/tests/injection-engine.test.js +3 -3
- package/src/injection/tests/integration.test.js +2 -1
- package/src/injection/tests/run-tests.js +3 -0
- package/src/injection/validation-engine.js +71 -5
- package/src/linter/determinism-linter.js +20 -5
- package/src/linter/determinism.js +8 -2
- package/src/linter/index.js +3 -1
- package/src/linter/test-doubles.js +151 -4
- package/src/parser/frontmatter.js +6 -0
- package/src/parser/variables.js +7 -1
- package/src/rdf/filters.js +393 -0
- package/src/rdf/index.js +444 -0
- package/src/renderer/deterministic.js +6 -0
- package/src/renderer/index.js +3 -1
- package/src/templates/rdf/DELIVERY-SUMMARY.md +266 -0
- package/src/templates/rdf/README.md +595 -0
- package/src/templates/rdf/dataset.njk +83 -0
- package/src/templates/rdf/index.js +106 -0
- package/src/templates/rdf/jsonld-context.njk +63 -0
- package/src/templates/rdf/ontology.njk +107 -0
- package/src/templates/rdf/schema.njk +79 -0
- package/src/templates/rdf/shapes.njk +89 -0
- package/src/templates/rdf/sparql-queries.njk +70 -0
- package/src/templates/rdf/vocabulary.njk +79 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file RDF Templates Index
|
|
3
|
+
* @description Exports all RDF template paths for programmatic use
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { dirname, join } from 'path';
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = dirname(__filename);
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* RDF template definitions
|
|
14
|
+
*/
|
|
15
|
+
export const RDF_TEMPLATES = {
|
|
16
|
+
ontology: {
|
|
17
|
+
name: 'ontology.njk',
|
|
18
|
+
path: join(__dirname, 'ontology.njk'),
|
|
19
|
+
description: 'OWL ontology template with classes and properties',
|
|
20
|
+
requiredVars: ['ontologyIRI', 'title']
|
|
21
|
+
},
|
|
22
|
+
schema: {
|
|
23
|
+
name: 'schema.njk',
|
|
24
|
+
path: join(__dirname, 'schema.njk'),
|
|
25
|
+
description: 'RDFS vocabulary schema template',
|
|
26
|
+
requiredVars: ['schemaIRI', 'title']
|
|
27
|
+
},
|
|
28
|
+
dataset: {
|
|
29
|
+
name: 'dataset.njk',
|
|
30
|
+
path: join(__dirname, 'dataset.njk'),
|
|
31
|
+
description: 'DCAT dataset metadata template',
|
|
32
|
+
requiredVars: ['datasetIRI', 'title', 'description']
|
|
33
|
+
},
|
|
34
|
+
vocabulary: {
|
|
35
|
+
name: 'vocabulary.njk',
|
|
36
|
+
path: join(__dirname, 'vocabulary.njk'),
|
|
37
|
+
description: 'SKOS concept scheme template',
|
|
38
|
+
requiredVars: ['schemeIRI', 'title']
|
|
39
|
+
},
|
|
40
|
+
shapes: {
|
|
41
|
+
name: 'shapes.njk',
|
|
42
|
+
path: join(__dirname, 'shapes.njk'),
|
|
43
|
+
description: 'SHACL validation shapes template',
|
|
44
|
+
requiredVars: ['shapesGraphIRI', 'shapes']
|
|
45
|
+
},
|
|
46
|
+
sparqlQueries: {
|
|
47
|
+
name: 'sparql-queries.njk',
|
|
48
|
+
path: join(__dirname, 'sparql-queries.njk'),
|
|
49
|
+
description: 'SPARQL query collection template',
|
|
50
|
+
requiredVars: ['title', 'queries']
|
|
51
|
+
},
|
|
52
|
+
jsonldContext: {
|
|
53
|
+
name: 'jsonld-context.njk',
|
|
54
|
+
path: join(__dirname, 'jsonld-context.njk'),
|
|
55
|
+
description: 'JSON-LD context mapping template',
|
|
56
|
+
requiredVars: ['terms']
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get template path by name
|
|
62
|
+
* @param {string} name - Template name (e.g., 'ontology', 'schema')
|
|
63
|
+
* @returns {string} Full path to template file
|
|
64
|
+
*/
|
|
65
|
+
export function getTemplatePath(name) {
|
|
66
|
+
const template = RDF_TEMPLATES[name];
|
|
67
|
+
if (!template) {
|
|
68
|
+
throw new Error(`Unknown RDF template: ${name}`);
|
|
69
|
+
}
|
|
70
|
+
return template.path;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* List all available RDF templates
|
|
75
|
+
* @returns {Array<{name: string, description: string, requiredVars: string[]}>}
|
|
76
|
+
*/
|
|
77
|
+
export function listTemplates() {
|
|
78
|
+
return Object.entries(RDF_TEMPLATES).map(([key, value]) => ({
|
|
79
|
+
key,
|
|
80
|
+
name: value.name,
|
|
81
|
+
description: value.description,
|
|
82
|
+
requiredVars: value.requiredVars
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Validate data against template requirements
|
|
88
|
+
* @param {string} templateName - Template name
|
|
89
|
+
* @param {Object} data - Data to validate
|
|
90
|
+
* @returns {{valid: boolean, missing: string[]}}
|
|
91
|
+
*/
|
|
92
|
+
export function validateTemplateData(templateName, data) {
|
|
93
|
+
const template = RDF_TEMPLATES[templateName];
|
|
94
|
+
if (!template) {
|
|
95
|
+
return { valid: false, missing: ['Unknown template'] };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const missing = template.requiredVars.filter(varName => !data[varName]);
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
valid: missing.length === 0,
|
|
102
|
+
missing
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export default RDF_TEMPLATES;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{#
|
|
2
|
+
JSON-LD Context Template
|
|
3
|
+
|
|
4
|
+
Generates a JSON-LD context file for mapping JSON to RDF.
|
|
5
|
+
|
|
6
|
+
Expected frontmatter variables:
|
|
7
|
+
- contextIRI: The IRI of the context (optional, for @id)
|
|
8
|
+
- vocab: Default vocabulary IRI (optional, for @vocab)
|
|
9
|
+
- base: Base IRI for relative IRIs (optional, for @base)
|
|
10
|
+
- prefixes: Object mapping prefixes to namespace IRIs (optional)
|
|
11
|
+
- terms: Object mapping terms to IRIs or term definitions (required)
|
|
12
|
+
Simple mapping: termName: iri
|
|
13
|
+
Complex mapping:
|
|
14
|
+
termName:
|
|
15
|
+
id: IRI
|
|
16
|
+
type: @id, @vocab, or XSD datatype
|
|
17
|
+
container: @list, @set, @language, etc. (optional)
|
|
18
|
+
language: Language tag (optional)
|
|
19
|
+
reverse: Boolean (optional)
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
---
|
|
23
|
+
contextIRI: http://example.org/contexts/person
|
|
24
|
+
vocab: http://schema.org/
|
|
25
|
+
prefixes:
|
|
26
|
+
foaf: http://xmlns.com/foaf/0.1/
|
|
27
|
+
xsd: http://www.w3.org/2001/XMLSchema#
|
|
28
|
+
terms:
|
|
29
|
+
Person: foaf:Person
|
|
30
|
+
name: foaf:name
|
|
31
|
+
email:
|
|
32
|
+
id: foaf:mbox
|
|
33
|
+
type: @id
|
|
34
|
+
age:
|
|
35
|
+
id: foaf:age
|
|
36
|
+
type: xsd:integer
|
|
37
|
+
knows:
|
|
38
|
+
id: foaf:knows
|
|
39
|
+
type: @id
|
|
40
|
+
container: @set
|
|
41
|
+
---
|
|
42
|
+
#}{
|
|
43
|
+
"@context": {
|
|
44
|
+
{% if contextIRI %} "@id": "{{ contextIRI }}",
|
|
45
|
+
{% endif %}
|
|
46
|
+
{% if vocab %} "@vocab": "{{ vocab }}",
|
|
47
|
+
{% endif %}
|
|
48
|
+
{% if base %} "@base": "{{ base }}",
|
|
49
|
+
{% endif %}
|
|
50
|
+
{% if prefixes %}{% for prefix, uri in prefixes %} "{{ prefix }}": "{{ uri }}",
|
|
51
|
+
{% endfor %}{% endif %}
|
|
52
|
+
{% if terms %}{% for term, def in terms %}{% if def.id %} "{{ term }}": {
|
|
53
|
+
"@id": "{{ def.id }}"{% if def.type %},
|
|
54
|
+
"@type": "{{ def.type }}"{% endif %}{% if def.container %},
|
|
55
|
+
"@container": "{{ def.container }}"{% endif %}{% if def.language %},
|
|
56
|
+
"@language": "{{ def.language }}"{% endif %}{% if def.reverse %},
|
|
57
|
+
"@reverse": "{{ def.reverse }}"{% endif %}
|
|
58
|
+
}{% if not loop.last %},{% endif %}
|
|
59
|
+
{% else %} "{{ term }}": "{{ def }}"{% if not loop.last %},{% endif %}
|
|
60
|
+
{% endif %}
|
|
61
|
+
{% endfor %}{% endif %}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
{#
|
|
2
|
+
OWL Ontology Template
|
|
3
|
+
|
|
4
|
+
Generates a complete OWL ontology with classes, properties, and metadata.
|
|
5
|
+
|
|
6
|
+
Expected frontmatter variables:
|
|
7
|
+
- ontologyIRI: The IRI of the ontology (required)
|
|
8
|
+
- version: Version string (optional)
|
|
9
|
+
- title: Ontology title (required)
|
|
10
|
+
- description: Ontology description (optional)
|
|
11
|
+
- creator: Creator name/IRI (optional)
|
|
12
|
+
- created: Creation date (ISO format) (optional)
|
|
13
|
+
- license: License IRI (optional)
|
|
14
|
+
- classes: Array of class definitions (optional)
|
|
15
|
+
- iri: Class IRI
|
|
16
|
+
- label: rdfs:label
|
|
17
|
+
- comment: rdfs:comment
|
|
18
|
+
- subClassOf: Parent class IRI (optional)
|
|
19
|
+
- objectProperties: Array of object properties (optional)
|
|
20
|
+
- iri: Property IRI
|
|
21
|
+
- label: rdfs:label
|
|
22
|
+
- comment: rdfs:comment
|
|
23
|
+
- domain: Domain class IRI
|
|
24
|
+
- range: Range class IRI
|
|
25
|
+
- datatypeProperties: Array of datatype properties (optional)
|
|
26
|
+
- iri: Property IRI
|
|
27
|
+
- label: rdfs:label
|
|
28
|
+
- comment: rdfs:comment
|
|
29
|
+
- domain: Domain class IRI
|
|
30
|
+
- range: XSD datatype IRI
|
|
31
|
+
|
|
32
|
+
Example:
|
|
33
|
+
---
|
|
34
|
+
ontologyIRI: http://example.org/ontology/myonto
|
|
35
|
+
version: 1.0.0
|
|
36
|
+
title: My Example Ontology
|
|
37
|
+
description: An example OWL ontology
|
|
38
|
+
creator: http://example.org/people/john-doe
|
|
39
|
+
created: 2026-01-11
|
|
40
|
+
classes:
|
|
41
|
+
- iri: http://example.org/ontology/myonto#Person
|
|
42
|
+
label: Person
|
|
43
|
+
comment: Represents a person
|
|
44
|
+
- iri: http://example.org/ontology/myonto#Organization
|
|
45
|
+
label: Organization
|
|
46
|
+
comment: Represents an organization
|
|
47
|
+
objectProperties:
|
|
48
|
+
- iri: http://example.org/ontology/myonto#worksFor
|
|
49
|
+
label: works for
|
|
50
|
+
comment: Relates a person to their employer
|
|
51
|
+
domain: http://example.org/ontology/myonto#Person
|
|
52
|
+
range: http://example.org/ontology/myonto#Organization
|
|
53
|
+
---
|
|
54
|
+
#}
|
|
55
|
+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
|
56
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
57
|
+
@prefix owl: <http://www.w3.org/2002/07/owl#> .
|
|
58
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
59
|
+
@prefix dc: <http://purl.org/dc/elements/1.1/> .
|
|
60
|
+
@prefix dcterms: <http://purl.org/dc/terms/> .
|
|
61
|
+
{% if prefix %}@prefix {{ prefix }}: <{{ ontologyIRI }}#> .{% endif %}
|
|
62
|
+
|
|
63
|
+
# Ontology Declaration
|
|
64
|
+
<{{ ontologyIRI }}> a owl:Ontology ;
|
|
65
|
+
dc:title "{{ title }}"@en ;
|
|
66
|
+
{% if description %} dc:description "{{ description }}"@en ;{% endif %}
|
|
67
|
+
{% if version %} owl:versionInfo "{{ version }}" ;{% endif %}
|
|
68
|
+
{% if creator %} dcterms:creator <{{ creator }}> ;{% endif %}
|
|
69
|
+
{% if created %} dcterms:created "{{ created }}"^^xsd:date ;{% endif %}
|
|
70
|
+
{% if license %} dcterms:license <{{ license }}> ;{% endif %}
|
|
71
|
+
dcterms:modified "{{ now | date('YYYY-MM-DD') }}"^^xsd:date .
|
|
72
|
+
|
|
73
|
+
{% if classes and classes.length > 0 %}
|
|
74
|
+
# Classes
|
|
75
|
+
{% for class in classes %}
|
|
76
|
+
<{{ class.iri }}> a owl:Class ;
|
|
77
|
+
rdfs:label "{{ class.label }}"@en ;
|
|
78
|
+
{% if class.comment %} rdfs:comment "{{ class.comment }}"@en ;{% endif %}
|
|
79
|
+
{% if class.subClassOf %} rdfs:subClassOf <{{ class.subClassOf }}> ;{% endif %}
|
|
80
|
+
rdfs:isDefinedBy <{{ ontologyIRI }}> .
|
|
81
|
+
|
|
82
|
+
{% endfor %}
|
|
83
|
+
{% endif %}
|
|
84
|
+
{% if objectProperties and objectProperties.length > 0 %}
|
|
85
|
+
# Object Properties
|
|
86
|
+
{% for prop in objectProperties %}
|
|
87
|
+
<{{ prop.iri }}> a owl:ObjectProperty ;
|
|
88
|
+
rdfs:label "{{ prop.label }}"@en ;
|
|
89
|
+
{% if prop.comment %} rdfs:comment "{{ prop.comment }}"@en ;{% endif %}
|
|
90
|
+
{% if prop.domain %} rdfs:domain <{{ prop.domain }}> ;{% endif %}
|
|
91
|
+
{% if prop.range %} rdfs:range <{{ prop.range }}> ;{% endif %}
|
|
92
|
+
rdfs:isDefinedBy <{{ ontologyIRI }}> .
|
|
93
|
+
|
|
94
|
+
{% endfor %}
|
|
95
|
+
{% endif %}
|
|
96
|
+
{% if datatypeProperties and datatypeProperties.length > 0 %}
|
|
97
|
+
# Datatype Properties
|
|
98
|
+
{% for prop in datatypeProperties %}
|
|
99
|
+
<{{ prop.iri }}> a owl:DatatypeProperty ;
|
|
100
|
+
rdfs:label "{{ prop.label }}"@en ;
|
|
101
|
+
{% if prop.comment %} rdfs:comment "{{ prop.comment }}"@en ;{% endif %}
|
|
102
|
+
{% if prop.domain %} rdfs:domain <{{ prop.domain }}> ;{% endif %}
|
|
103
|
+
{% if prop.range %} rdfs:range <{{ prop.range }}> ;{% endif %}
|
|
104
|
+
rdfs:isDefinedBy <{{ ontologyIRI }}> .
|
|
105
|
+
|
|
106
|
+
{% endfor %}
|
|
107
|
+
{% endif %}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{#
|
|
2
|
+
RDFS Schema Template
|
|
3
|
+
|
|
4
|
+
Generates an RDFS vocabulary with classes and properties.
|
|
5
|
+
|
|
6
|
+
Expected frontmatter variables:
|
|
7
|
+
- schemaIRI: The IRI of the schema (required)
|
|
8
|
+
- title: Schema title (required)
|
|
9
|
+
- description: Schema description (optional)
|
|
10
|
+
- version: Version string (optional)
|
|
11
|
+
- classes: Array of RDFS class definitions (optional)
|
|
12
|
+
- iri: Class IRI
|
|
13
|
+
- label: rdfs:label
|
|
14
|
+
- comment: rdfs:comment
|
|
15
|
+
- subClassOf: Parent class IRI (optional)
|
|
16
|
+
- properties: Array of RDF properties (optional)
|
|
17
|
+
- iri: Property IRI
|
|
18
|
+
- label: rdfs:label
|
|
19
|
+
- comment: rdfs:comment
|
|
20
|
+
- domain: Domain class IRI (optional)
|
|
21
|
+
- range: Range class/datatype IRI (optional)
|
|
22
|
+
- subPropertyOf: Parent property IRI (optional)
|
|
23
|
+
|
|
24
|
+
Example:
|
|
25
|
+
---
|
|
26
|
+
schemaIRI: http://example.org/schema/vocab
|
|
27
|
+
title: Example Vocabulary
|
|
28
|
+
description: A simple RDFS vocabulary
|
|
29
|
+
version: 1.0.0
|
|
30
|
+
classes:
|
|
31
|
+
- iri: http://example.org/schema/vocab#Document
|
|
32
|
+
label: Document
|
|
33
|
+
comment: A textual document
|
|
34
|
+
properties:
|
|
35
|
+
- iri: http://example.org/schema/vocab#title
|
|
36
|
+
label: title
|
|
37
|
+
comment: The title of a document
|
|
38
|
+
domain: http://example.org/schema/vocab#Document
|
|
39
|
+
range: http://www.w3.org/2001/XMLSchema#string
|
|
40
|
+
---
|
|
41
|
+
#}
|
|
42
|
+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
|
43
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
44
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
45
|
+
@prefix dc: <http://purl.org/dc/elements/1.1/> .
|
|
46
|
+
@prefix dcterms: <http://purl.org/dc/terms/> .
|
|
47
|
+
{% if prefix %}@prefix {{ prefix }}: <{{ schemaIRI }}#> .{% endif %}
|
|
48
|
+
|
|
49
|
+
# Schema Metadata
|
|
50
|
+
<{{ schemaIRI }}> a rdfs:Resource ;
|
|
51
|
+
rdfs:label "{{ title }}"@en ;
|
|
52
|
+
{% if description %} rdfs:comment "{{ description }}"@en ;{% endif %}
|
|
53
|
+
{% if version %} dc:version "{{ version }}" ;{% endif %}
|
|
54
|
+
dcterms:modified "{{ now | date('YYYY-MM-DD') }}"^^xsd:date .
|
|
55
|
+
|
|
56
|
+
{% if classes and classes.length > 0 %}
|
|
57
|
+
# Class Definitions
|
|
58
|
+
{% for class in classes %}
|
|
59
|
+
<{{ class.iri }}> a rdfs:Class ;
|
|
60
|
+
rdfs:label "{{ class.label }}"@en ;
|
|
61
|
+
{% if class.comment %} rdfs:comment "{{ class.comment }}"@en ;{% endif %}
|
|
62
|
+
{% if class.subClassOf %} rdfs:subClassOf <{{ class.subClassOf }}> ;{% endif %}
|
|
63
|
+
rdfs:isDefinedBy <{{ schemaIRI }}> .
|
|
64
|
+
|
|
65
|
+
{% endfor %}
|
|
66
|
+
{% endif %}
|
|
67
|
+
{% if properties and properties.length > 0 %}
|
|
68
|
+
# Property Definitions
|
|
69
|
+
{% for prop in properties %}
|
|
70
|
+
<{{ prop.iri }}> a rdf:Property ;
|
|
71
|
+
rdfs:label "{{ prop.label }}"@en ;
|
|
72
|
+
{% if prop.comment %} rdfs:comment "{{ prop.comment }}"@en ;{% endif %}
|
|
73
|
+
{% if prop.domain %} rdfs:domain <{{ prop.domain }}> ;{% endif %}
|
|
74
|
+
{% if prop.range %} rdfs:range <{{ prop.range }}> ;{% endif %}
|
|
75
|
+
{% if prop.subPropertyOf %} rdfs:subPropertyOf <{{ prop.subPropertyOf }}> ;{% endif %}
|
|
76
|
+
rdfs:isDefinedBy <{{ schemaIRI }}> .
|
|
77
|
+
|
|
78
|
+
{% endfor %}
|
|
79
|
+
{% endif %}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{#
|
|
2
|
+
SHACL Shapes Template
|
|
3
|
+
|
|
4
|
+
Generates SHACL (Shapes Constraint Language) shapes for RDF validation.
|
|
5
|
+
|
|
6
|
+
Expected frontmatter variables:
|
|
7
|
+
- shapesGraphIRI: The IRI of the shapes graph (required)
|
|
8
|
+
- title: Shapes graph title (optional)
|
|
9
|
+
- description: Description of the shapes (optional)
|
|
10
|
+
- shapes: Array of shape definitions (required)
|
|
11
|
+
- iri: Shape IRI
|
|
12
|
+
- targetClass: Target class IRI (optional)
|
|
13
|
+
- targetNode: Target node IRI (optional)
|
|
14
|
+
- label: Shape label (optional)
|
|
15
|
+
- description: Shape description (optional)
|
|
16
|
+
- closed: Boolean - whether shape is closed (optional)
|
|
17
|
+
- properties: Array of property constraints
|
|
18
|
+
- path: Property path IRI
|
|
19
|
+
- minCount: Minimum cardinality (optional)
|
|
20
|
+
- maxCount: Maximum cardinality (optional)
|
|
21
|
+
- datatype: Datatype IRI for datatype properties (optional)
|
|
22
|
+
- class: Class IRI for object properties (optional)
|
|
23
|
+
- pattern: Regex pattern for string validation (optional)
|
|
24
|
+
- minLength: Minimum string length (optional)
|
|
25
|
+
- maxLength: Maximum string length (optional)
|
|
26
|
+
- minInclusive: Minimum numeric value (optional)
|
|
27
|
+
- maxInclusive: Maximum numeric value (optional)
|
|
28
|
+
|
|
29
|
+
Example:
|
|
30
|
+
---
|
|
31
|
+
shapesGraphIRI: http://example.org/shapes/person
|
|
32
|
+
title: Person Shapes
|
|
33
|
+
description: Validation shapes for Person data
|
|
34
|
+
shapes:
|
|
35
|
+
- iri: http://example.org/shapes/person#PersonShape
|
|
36
|
+
targetClass: http://example.org/ontology/Person
|
|
37
|
+
label: Person Shape
|
|
38
|
+
description: Validates Person instances
|
|
39
|
+
closed: false
|
|
40
|
+
properties:
|
|
41
|
+
- path: http://xmlns.com/foaf/0.1/name
|
|
42
|
+
minCount: 1
|
|
43
|
+
maxCount: 1
|
|
44
|
+
datatype: http://www.w3.org/2001/XMLSchema#string
|
|
45
|
+
- path: http://xmlns.com/foaf/0.1/mbox
|
|
46
|
+
minCount: 0
|
|
47
|
+
datatype: http://www.w3.org/2001/XMLSchema#string
|
|
48
|
+
pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
|
|
49
|
+
---
|
|
50
|
+
#}
|
|
51
|
+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
|
52
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
53
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
54
|
+
@prefix sh: <http://www.w3.org/ns/shacl#> .
|
|
55
|
+
@prefix dc: <http://purl.org/dc/elements/1.1/> .
|
|
56
|
+
{% if prefix %}@prefix {{ prefix }}: <{{ shapesGraphIRI }}#> .{% endif %}
|
|
57
|
+
|
|
58
|
+
# Shapes Graph Metadata
|
|
59
|
+
<{{ shapesGraphIRI }}> a sh:ShapesGraph ;
|
|
60
|
+
{% if title %} dc:title "{{ title }}"@en ;{% endif %}
|
|
61
|
+
{% if description %} dc:description "{{ description }}"@en ;{% endif %}
|
|
62
|
+
.
|
|
63
|
+
|
|
64
|
+
{% if shapes and shapes.length > 0 %}
|
|
65
|
+
# Shape Definitions
|
|
66
|
+
{% for shape in shapes %}
|
|
67
|
+
<{{ shape.iri }}> a sh:NodeShape ;
|
|
68
|
+
{% if shape.targetClass %} sh:targetClass <{{ shape.targetClass }}> ;{% endif %}
|
|
69
|
+
{% if shape.targetNode %} sh:targetNode <{{ shape.targetNode }}> ;{% endif %}
|
|
70
|
+
{% if shape.label %} rdfs:label "{{ shape.label }}"@en ;{% endif %}
|
|
71
|
+
{% if shape.description %} rdfs:comment "{{ shape.description }}"@en ;{% endif %}
|
|
72
|
+
{% if shape.closed %} sh:closed {{ shape.closed }} ;{% endif %}
|
|
73
|
+
{% if shape.properties and shape.properties.length > 0 %}{% for prop in shape.properties %} sh:property [
|
|
74
|
+
sh:path <{{ prop.path }}> ;
|
|
75
|
+
{% if prop.minCount !== undefined %} sh:minCount {{ prop.minCount }} ;{% endif %}
|
|
76
|
+
{% if prop.maxCount !== undefined %} sh:maxCount {{ prop.maxCount }} ;{% endif %}
|
|
77
|
+
{% if prop.datatype %} sh:datatype <{{ prop.datatype }}> ;{% endif %}
|
|
78
|
+
{% if prop.class %} sh:class <{{ prop.class }}> ;{% endif %}
|
|
79
|
+
{% if prop.pattern %} sh:pattern "{{ prop.pattern }}" ;{% endif %}
|
|
80
|
+
{% if prop.minLength !== undefined %} sh:minLength {{ prop.minLength }} ;{% endif %}
|
|
81
|
+
{% if prop.maxLength !== undefined %} sh:maxLength {{ prop.maxLength }} ;{% endif %}
|
|
82
|
+
{% if prop.minInclusive !== undefined %} sh:minInclusive {{ prop.minInclusive }} ;{% endif %}
|
|
83
|
+
{% if prop.maxInclusive !== undefined %} sh:maxInclusive {{ prop.maxInclusive }} ;{% endif %}
|
|
84
|
+
] ;
|
|
85
|
+
{% endfor %}{% endif %}
|
|
86
|
+
.
|
|
87
|
+
|
|
88
|
+
{% endfor %}
|
|
89
|
+
{% endif %}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{#
|
|
2
|
+
SPARQL Queries Template
|
|
3
|
+
|
|
4
|
+
Generates a collection of SPARQL queries with metadata.
|
|
5
|
+
|
|
6
|
+
Expected frontmatter variables:
|
|
7
|
+
- title: Query collection title (required)
|
|
8
|
+
- description: Collection description (optional)
|
|
9
|
+
- queries: Array of query definitions (required)
|
|
10
|
+
- name: Query name/identifier
|
|
11
|
+
- description: Query description
|
|
12
|
+
- type: Query type (SELECT, CONSTRUCT, ASK, DESCRIBE)
|
|
13
|
+
- prefixes: Object with prefix mappings (optional)
|
|
14
|
+
- variables: Array of variable names for SELECT (optional)
|
|
15
|
+
- where: Array of WHERE clause patterns
|
|
16
|
+
- orderBy: Array of ORDER BY variables (optional)
|
|
17
|
+
- limit: LIMIT value (optional)
|
|
18
|
+
- offset: OFFSET value (optional)
|
|
19
|
+
|
|
20
|
+
Example:
|
|
21
|
+
---
|
|
22
|
+
title: Common SPARQL Queries
|
|
23
|
+
description: Frequently used SPARQL queries
|
|
24
|
+
queries:
|
|
25
|
+
- name: getAllPersons
|
|
26
|
+
description: Retrieve all persons with their names
|
|
27
|
+
type: SELECT
|
|
28
|
+
prefixes:
|
|
29
|
+
foaf: http://xmlns.com/foaf/0.1/
|
|
30
|
+
rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
|
|
31
|
+
variables:
|
|
32
|
+
- person
|
|
33
|
+
- name
|
|
34
|
+
where:
|
|
35
|
+
- "?person a foaf:Person"
|
|
36
|
+
- "?person foaf:name ?name"
|
|
37
|
+
orderBy:
|
|
38
|
+
- name
|
|
39
|
+
limit: 100
|
|
40
|
+
---
|
|
41
|
+
#}
|
|
42
|
+
{# Query Collection: {{ title }} #}
|
|
43
|
+
{% if description %}{# {{ description }} #}{% endif %}
|
|
44
|
+
|
|
45
|
+
{% for query in queries %}
|
|
46
|
+
{# Query: {{ query.name }} #}
|
|
47
|
+
{% if query.description %}{# Description: {{ query.description }} #}{% endif %}
|
|
48
|
+
|
|
49
|
+
{% if query.type === 'SELECT' %}SELECT {% if query.variables %}{% for v in query.variables %}?{{ v }}{% if not loop.last %} {% endif %}{% endfor %}{% else %}*{% endif %}
|
|
50
|
+
{% elif query.type === 'CONSTRUCT' %}CONSTRUCT {
|
|
51
|
+
{% for pattern in query.construct %} {{ pattern }} .
|
|
52
|
+
{% endfor %}}
|
|
53
|
+
{% elif query.type === 'ASK' %}ASK
|
|
54
|
+
{% elif query.type === 'DESCRIBE' %}DESCRIBE {% if query.resources %}{{ query.resources | join(' ') }}{% else %}?resource{% endif %}
|
|
55
|
+
{% endif %}
|
|
56
|
+
{% if query.prefixes %}{% for prefix, uri in query.prefixes %}PREFIX {{ prefix }}: <{{ uri }}>
|
|
57
|
+
{% endfor %}{% endif %}
|
|
58
|
+
WHERE {
|
|
59
|
+
{% for pattern in query.where %} {{ pattern }} .
|
|
60
|
+
{% endfor %}}
|
|
61
|
+
{% if query.orderBy %}ORDER BY {% for v in query.orderBy %}?{{ v }} {% endfor %}{% endif %}
|
|
62
|
+
{% if query.limit %}LIMIT {{ query.limit }}{% endif %}
|
|
63
|
+
{% if query.offset %}
|
|
64
|
+
OFFSET {{ query.offset }}{% endif %}
|
|
65
|
+
|
|
66
|
+
{% if not loop.last %}
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
{% endif %}
|
|
70
|
+
{% endfor %}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{#
|
|
2
|
+
SKOS Vocabulary Template
|
|
3
|
+
|
|
4
|
+
Generates a SKOS (Simple Knowledge Organization System) concept scheme.
|
|
5
|
+
|
|
6
|
+
Expected frontmatter variables:
|
|
7
|
+
- schemeIRI: The IRI of the concept scheme (required)
|
|
8
|
+
- title: Scheme title (required)
|
|
9
|
+
- description: Scheme description (optional)
|
|
10
|
+
- creator: Creator name/IRI (optional)
|
|
11
|
+
- created: Creation date (ISO format) (optional)
|
|
12
|
+
- concepts: Array of concept definitions (optional)
|
|
13
|
+
- iri: Concept IRI
|
|
14
|
+
- prefLabel: Preferred label
|
|
15
|
+
- altLabel: Alternative labels (array, optional)
|
|
16
|
+
- definition: Definition text (optional)
|
|
17
|
+
- broader: Broader concept IRI (optional)
|
|
18
|
+
- narrower: Array of narrower concept IRIs (optional)
|
|
19
|
+
- related: Array of related concept IRIs (optional)
|
|
20
|
+
- notation: Notation string (optional)
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
---
|
|
24
|
+
schemeIRI: http://example.org/vocabularies/topics
|
|
25
|
+
title: Topic Vocabulary
|
|
26
|
+
description: A controlled vocabulary of topics
|
|
27
|
+
creator: http://example.org/people/jane-doe
|
|
28
|
+
created: 2026-01-11
|
|
29
|
+
concepts:
|
|
30
|
+
- iri: http://example.org/vocabularies/topics#Science
|
|
31
|
+
prefLabel: Science
|
|
32
|
+
definition: Natural and formal sciences
|
|
33
|
+
narrower:
|
|
34
|
+
- http://example.org/vocabularies/topics#Physics
|
|
35
|
+
- http://example.org/vocabularies/topics#Biology
|
|
36
|
+
- iri: http://example.org/vocabularies/topics#Physics
|
|
37
|
+
prefLabel: Physics
|
|
38
|
+
definition: The study of matter and energy
|
|
39
|
+
broader: http://example.org/vocabularies/topics#Science
|
|
40
|
+
---
|
|
41
|
+
#}
|
|
42
|
+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
|
43
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
44
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
45
|
+
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
|
|
46
|
+
@prefix dc: <http://purl.org/dc/elements/1.1/> .
|
|
47
|
+
@prefix dcterms: <http://purl.org/dc/terms/> .
|
|
48
|
+
{% if prefix %}@prefix {{ prefix }}: <{{ schemeIRI }}#> .{% endif %}
|
|
49
|
+
|
|
50
|
+
# Concept Scheme
|
|
51
|
+
<{{ schemeIRI }}> a skos:ConceptScheme ;
|
|
52
|
+
dc:title "{{ title }}"@en ;
|
|
53
|
+
{% if description %} dc:description "{{ description }}"@en ;{% endif %}
|
|
54
|
+
{% if creator %} dcterms:creator <{{ creator }}> ;{% endif %}
|
|
55
|
+
{% if created %} dcterms:created "{{ created }}"^^xsd:date ;{% endif %}
|
|
56
|
+
dcterms:modified "{{ now | date('YYYY-MM-DD') }}"^^xsd:date ;
|
|
57
|
+
{% if concepts and concepts.length > 0 %}{% for concept in concepts %} skos:hasTopConcept <{{ concept.iri }}> ;
|
|
58
|
+
{% endfor %}{% endif %}
|
|
59
|
+
.
|
|
60
|
+
|
|
61
|
+
{% if concepts and concepts.length > 0 %}
|
|
62
|
+
# Concepts
|
|
63
|
+
{% for concept in concepts %}
|
|
64
|
+
<{{ concept.iri }}> a skos:Concept ;
|
|
65
|
+
skos:inScheme <{{ schemeIRI }}> ;
|
|
66
|
+
skos:prefLabel "{{ concept.prefLabel }}"@en ;
|
|
67
|
+
{% if concept.altLabel and concept.altLabel.length > 0 %}{% for alt in concept.altLabel %} skos:altLabel "{{ alt }}"@en ;
|
|
68
|
+
{% endfor %}{% endif %}
|
|
69
|
+
{% if concept.definition %} skos:definition "{{ concept.definition }}"@en ;{% endif %}
|
|
70
|
+
{% if concept.notation %} skos:notation "{{ concept.notation }}" ;{% endif %}
|
|
71
|
+
{% if concept.broader %} skos:broader <{{ concept.broader }}> ;{% endif %}
|
|
72
|
+
{% if concept.narrower and concept.narrower.length > 0 %}{% for narrow in concept.narrower %} skos:narrower <{{ narrow }}> ;
|
|
73
|
+
{% endfor %}{% endif %}
|
|
74
|
+
{% if concept.related and concept.related.length > 0 %}{% for rel in concept.related %} skos:related <{{ rel }}> ;
|
|
75
|
+
{% endfor %}{% endif %}
|
|
76
|
+
.
|
|
77
|
+
|
|
78
|
+
{% endfor %}
|
|
79
|
+
{% endif %}
|