@ulb-darmstadt/shacl-form 1.9.0 → 1.9.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/config.d.ts +0 -1
- package/dist/form-bootstrap.js +69 -69
- package/dist/form-default.js +66 -66
- package/dist/form-material.js +104 -104
- package/dist/plugins/leaflet.js +1 -1
- package/dist/util.d.ts +4 -0
- package/package.json +4 -4
- package/src/config.ts +2 -10
- package/src/loader.ts +19 -41
- package/src/util.ts +105 -3
package/dist/util.d.ts
CHANGED
|
@@ -11,3 +11,7 @@ export declare function removePrefixes(id: string, prefixes: Prefixes): string;
|
|
|
11
11
|
export declare function findInstancesOf(clazz: NamedNode, template: ShaclPropertyTemplate): InputListEntry[];
|
|
12
12
|
export declare function isURL(input: string): boolean;
|
|
13
13
|
export declare function prioritizeByLanguage(languages: string[], text1?: Literal, text2?: Literal): Literal | undefined;
|
|
14
|
+
export declare function extractLists(store: Store, { remove, ignoreErrors }?: {
|
|
15
|
+
remove?: boolean | undefined;
|
|
16
|
+
ignoreErrors?: boolean | undefined;
|
|
17
|
+
}): Record<string, Term[]>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ulb-darmstadt/shacl-form",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.2",
|
|
4
4
|
"description": "SHACL form generator",
|
|
5
5
|
"main": "dist/form-default.js",
|
|
6
6
|
"module": "dist/form-default.js",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@types/uuid": "^10.0.0",
|
|
56
56
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
57
57
|
"typescript": "^5.8.3",
|
|
58
|
-
"vite": "^7.0.
|
|
58
|
+
"vite": "^7.0.6",
|
|
59
59
|
"vite-plugin-dts": "^4.5.4"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"bootstrap": "^5.3.7",
|
|
64
64
|
"jsonld": "^8.3.3",
|
|
65
65
|
"leaflet": "^1.9.4",
|
|
66
|
-
"leaflet-editable": "^1.3.
|
|
66
|
+
"leaflet-editable": "^1.3.2",
|
|
67
67
|
"leaflet.fullscreen": "^4.0.0",
|
|
68
68
|
"mapbox-gl": "^3.13.0",
|
|
69
69
|
"n3": "^1.26.0",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"uuid": "^11.1.0"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
|
-
"@ro-kit/ui-widgets": "^0.0.
|
|
75
|
+
"@ro-kit/ui-widgets": "^0.0.34",
|
|
76
76
|
"mdui": "^2.1.4"
|
|
77
77
|
}
|
|
78
78
|
}
|
package/src/config.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { PREFIX_SHACL, RDF_PREDICATE_TYPE } from './constants'
|
|
|
4
4
|
import { ClassInstanceProvider } from './plugin'
|
|
5
5
|
import { Loader } from './loader'
|
|
6
6
|
import { Theme } from './theme'
|
|
7
|
+
import { extractLists } from './util'
|
|
7
8
|
|
|
8
9
|
export class ElementAttributes {
|
|
9
10
|
shapes: string | null = null
|
|
@@ -99,19 +100,10 @@ export class Config {
|
|
|
99
100
|
|
|
100
101
|
set store(store: Store) {
|
|
101
102
|
this._store = store
|
|
102
|
-
this.lists =
|
|
103
|
+
this.lists = extractLists(store)
|
|
103
104
|
this.groups = []
|
|
104
105
|
store.forSubjects(subject => {
|
|
105
106
|
this.groups.push(subject.id)
|
|
106
107
|
}, RDF_PREDICATE_TYPE, `${PREFIX_SHACL}PropertyGroup`, null)
|
|
107
108
|
}
|
|
108
|
-
|
|
109
|
-
registerPrefixes(prefixes: Prefixes) {
|
|
110
|
-
for (const key in prefixes) {
|
|
111
|
-
// ignore empty (default) namespace
|
|
112
|
-
if (key) {
|
|
113
|
-
this.prefixes[key] = prefixes[key]
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
109
|
}
|
package/src/loader.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Store, Quad, NamedNode, DataFactory,
|
|
1
|
+
import { Store, Quad, NamedNode, DataFactory, StreamParser } from 'n3'
|
|
2
2
|
import { DATA_GRAPH, DCTERMS_PREDICATE_CONFORMS_TO, OWL_PREDICATE_IMPORTS, RDF_PREDICATE_TYPE, SHACL_PREDICATE_CLASS, SHAPES_GRAPH } from './constants'
|
|
3
3
|
import { Config } from './config'
|
|
4
4
|
import { isURL } from './util'
|
|
@@ -11,7 +11,6 @@ import { toRDF } from 'jsonld'
|
|
|
11
11
|
// that import the same resources
|
|
12
12
|
const loadedURLCache: Record<string, Promise<string>> = {}
|
|
13
13
|
const loadedClassesCache: Record<string, Promise<string>> = {}
|
|
14
|
-
const ttlParser = new Parser()
|
|
15
14
|
let sharedShapesGraph: Store | undefined
|
|
16
15
|
|
|
17
16
|
export class Loader {
|
|
@@ -69,7 +68,8 @@ export class Loader {
|
|
|
69
68
|
const parse = async (input: string) => {
|
|
70
69
|
const dependencies: Promise<void>[] = []
|
|
71
70
|
await new Promise((resolve, reject) => {
|
|
72
|
-
const
|
|
71
|
+
const parser = guessContentType(input) === 'xml' ? new RdfXmlParser() : new StreamParser()
|
|
72
|
+
parser.on('data', (quad: Quad) => {
|
|
73
73
|
store.add(new Quad(quad.subject, quad.predicate, quad.object, graph))
|
|
74
74
|
// check if this is an owl:imports predicate and try to load the url
|
|
75
75
|
if (this.config.attributes.ignoreOwlImports === null && OWL_PREDICATE_IMPORTS.equals(quad.predicate)) {
|
|
@@ -98,44 +98,22 @@ export class Loader {
|
|
|
98
98
|
dependencies.push(this.importRDF(promise, store, graph))
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
})
|
|
118
|
-
.on('end', () => {
|
|
119
|
-
resolve(null)
|
|
120
|
-
})
|
|
121
|
-
parser.write(input)
|
|
122
|
-
parser.end()
|
|
123
|
-
} else {
|
|
124
|
-
ttlParser.parse(input, (error: Error, quad: Quad, prefixes: Prefixes) => {
|
|
125
|
-
if (error) {
|
|
126
|
-
console.warn('failed parsing graph', graph, error.message)
|
|
127
|
-
return reject(error)
|
|
128
|
-
}
|
|
129
|
-
if (quad) {
|
|
130
|
-
addQuad(quad)
|
|
131
|
-
return
|
|
132
|
-
}
|
|
133
|
-
if (prefixes) {
|
|
134
|
-
this.config.registerPrefixes(prefixes)
|
|
135
|
-
}
|
|
136
|
-
resolve(null)
|
|
137
|
-
})
|
|
138
|
-
}
|
|
101
|
+
})
|
|
102
|
+
.on('error', (error) => {
|
|
103
|
+
console.warn('failed parsing graph', graph, error.message)
|
|
104
|
+
reject(error)
|
|
105
|
+
})
|
|
106
|
+
.on('prefix', (prefix, iri) => {
|
|
107
|
+
// ignore empty (default) namespace
|
|
108
|
+
if (prefix) {
|
|
109
|
+
this.config.prefixes[prefix] = iri
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
.on('end', () => {
|
|
113
|
+
resolve(null)
|
|
114
|
+
})
|
|
115
|
+
parser.write(input)
|
|
116
|
+
parser.end()
|
|
139
117
|
})
|
|
140
118
|
try {
|
|
141
119
|
await Promise.allSettled(dependencies)
|
package/src/util.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Literal, NamedNode, Prefixes, Quad, Store } from 'n3'
|
|
2
|
-
import { DATA_GRAPH, PREFIX_FOAF, PREFIX_RDFS, PREFIX_SHACL, PREFIX_SKOS, RDFS_PREDICATE_SUBCLASS_OF, RDF_PREDICATE_TYPE, SHAPES_GRAPH, SKOS_PREDICATE_BROADER, SKOS_PREDICATE_NARROWER } from './constants'
|
|
2
|
+
import { DATA_GRAPH, PREFIX_FOAF, PREFIX_RDF, PREFIX_RDFS, PREFIX_SHACL, PREFIX_SKOS, RDFS_PREDICATE_SUBCLASS_OF, RDF_PREDICATE_TYPE, SHAPES_GRAPH, SKOS_PREDICATE_BROADER, SKOS_PREDICATE_NARROWER } from './constants'
|
|
3
3
|
import { Term } from '@rdfjs/types'
|
|
4
4
|
import { InputListEntry } from './theme'
|
|
5
5
|
import { ShaclPropertyTemplate } from './property-template'
|
|
@@ -44,7 +44,7 @@ export function findObjectByPredicate(quads: Quad[], predicate: string, prefix:
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export function focusFirstInputElement(context: HTMLElement) {
|
|
47
|
-
(context.querySelector('
|
|
47
|
+
(context.querySelector('.editor') as HTMLElement)?.focus()
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
export function findLabel(quads: Quad[], languages: string[]): string {
|
|
@@ -170,4 +170,106 @@ export function prioritizeByLanguage(languages: string[], text1?: Literal, text2
|
|
|
170
170
|
return text1
|
|
171
171
|
}
|
|
172
172
|
return index2 > index1 ? text1 : text2
|
|
173
|
-
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/*
|
|
176
|
+
This code is taken from https://github.com/rdfjs/N3.js/blob/main/src/N3Store.js and adapted to allow rdf:type triples in lists.
|
|
177
|
+
Can be removed as soon as https://github.com/rdfjs/N3.js/issues/546 is fixed.
|
|
178
|
+
*/
|
|
179
|
+
export function extractLists(store: Store, { remove = false, ignoreErrors = false } = {}) {
|
|
180
|
+
const lists: Record<string, Term[]> = {} // has scalar keys so could be a simple Object
|
|
181
|
+
const onError = ignoreErrors ? (() => true) :
|
|
182
|
+
((node: Term, message: string) => { throw new Error(`${node.value} ${message}`) })
|
|
183
|
+
|
|
184
|
+
// Traverse each list from its tail
|
|
185
|
+
const tails = store.getQuads(null, PREFIX_RDF + 'rest', PREFIX_RDF + 'nil', null)
|
|
186
|
+
const toRemove = remove ? [...tails] : []
|
|
187
|
+
tails.forEach(tailQuad => {
|
|
188
|
+
const items = [] // the members found as objects of rdf:first quads
|
|
189
|
+
let malformed = false // signals whether the current list is malformed
|
|
190
|
+
let head // the head of the list (_:b1 in above example)
|
|
191
|
+
let headPos: string // set to subject or object when head is set
|
|
192
|
+
const graph = tailQuad.graph // make sure list is in exactly one graph
|
|
193
|
+
|
|
194
|
+
// Traverse the list from tail to end
|
|
195
|
+
let current: Term | null = tailQuad.subject
|
|
196
|
+
while (current && !malformed) {
|
|
197
|
+
const objectQuads = store.getQuads(null, null, current, null)
|
|
198
|
+
const subjectQuads = store.getQuads(current, null, null, null).filter(quad => !quad.predicate.equals(RDF_PREDICATE_TYPE))
|
|
199
|
+
let quad, first = null, rest = null, parent = null
|
|
200
|
+
|
|
201
|
+
// Find the first and rest of this list node
|
|
202
|
+
for (let i = 0; i < subjectQuads.length && !malformed; i++) {
|
|
203
|
+
quad = subjectQuads[i]
|
|
204
|
+
if (!quad.graph.equals(graph))
|
|
205
|
+
malformed = onError(current, 'not confined to single graph')
|
|
206
|
+
else if (head)
|
|
207
|
+
malformed = onError(current, 'has non-list arcs out')
|
|
208
|
+
|
|
209
|
+
// one rdf:first
|
|
210
|
+
else if (quad.predicate.value === PREFIX_RDF + 'first') {
|
|
211
|
+
if (first)
|
|
212
|
+
malformed = onError(current, 'has multiple rdf:first arcs')
|
|
213
|
+
else
|
|
214
|
+
toRemove.push(first = quad)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// one rdf:rest
|
|
218
|
+
else if (quad.predicate.value === PREFIX_RDF + 'rest') {
|
|
219
|
+
if (rest)
|
|
220
|
+
malformed = onError(current, 'has multiple rdf:rest arcs')
|
|
221
|
+
else
|
|
222
|
+
toRemove.push(rest = quad)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// alien triple
|
|
226
|
+
else if (objectQuads.length)
|
|
227
|
+
malformed = onError(current, 'can\'t be subject and object')
|
|
228
|
+
else {
|
|
229
|
+
head = quad // e.g. { (1 2 3) :p :o }
|
|
230
|
+
headPos = 'subject'
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// { :s :p (1 2) } arrives here with no head
|
|
235
|
+
// { (1 2) :p :o } arrives here with head set to the list.
|
|
236
|
+
for (let i = 0; i < objectQuads.length && !malformed; ++i) {
|
|
237
|
+
quad = objectQuads[i]
|
|
238
|
+
if (head)
|
|
239
|
+
malformed = onError(current, 'can\'t have coreferences')
|
|
240
|
+
// one rdf:rest
|
|
241
|
+
else if (quad.predicate.value === PREFIX_RDF + 'rest') {
|
|
242
|
+
if (parent)
|
|
243
|
+
malformed = onError(current, 'has incoming rdf:rest arcs')
|
|
244
|
+
else
|
|
245
|
+
parent = quad
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
head = quad // e.g. { :s :p (1 2) }
|
|
249
|
+
headPos = 'object'
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Store the list item and continue with parent
|
|
254
|
+
if (!first)
|
|
255
|
+
malformed = onError(current, 'has no list head')
|
|
256
|
+
else
|
|
257
|
+
items.unshift(first.object)
|
|
258
|
+
current = parent && parent.subject
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Don't remove any quads if the list is malformed
|
|
262
|
+
if (malformed)
|
|
263
|
+
remove = false
|
|
264
|
+
// Store the list under the value of its head
|
|
265
|
+
else if (head) {
|
|
266
|
+
// @ts-ignore
|
|
267
|
+
lists[head[headPos].value] = items
|
|
268
|
+
}
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
// Remove list quads if requested
|
|
272
|
+
if (remove)
|
|
273
|
+
store.removeQuads(toRemove)
|
|
274
|
+
return lists
|
|
275
|
+
}
|