@ulb-darmstadt/shacl-form 1.9.4 → 1.10.1
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/README.md +1 -5
- package/dist/config.d.ts +1 -0
- package/dist/constants.d.ts +1 -0
- package/dist/exports.d.ts +1 -1
- package/dist/form-bootstrap.js +89 -67
- package/dist/form-default.js +87 -65
- package/dist/form-material.js +129 -107
- package/dist/form.d.ts +0 -1
- package/dist/loader.d.ts +1 -1
- package/dist/plugins/leaflet.js +2 -2
- package/dist/plugins/mapbox.js +15 -15
- package/package.json +3 -3
- package/src/config.ts +2 -1
- package/src/constants.ts +1 -0
- package/src/exports.ts +1 -1
- package/src/form.ts +1 -7
- package/src/loader.ts +29 -32
- package/src/node.ts +2 -2
- package/src/property.ts +1 -0
- package/src/serialize.ts +3 -1
- package/src/themes/default.ts +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ulb-darmstadt/shacl-form",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.1",
|
|
4
4
|
"description": "SHACL form generator",
|
|
5
5
|
"main": "dist/form-default.js",
|
|
6
6
|
"module": "dist/form-default.js",
|
|
@@ -69,7 +69,6 @@
|
|
|
69
69
|
"leaflet": "^1.9.4",
|
|
70
70
|
"leaflet-editable": "^1.3.2",
|
|
71
71
|
"leaflet.fullscreen": "^4.0.0",
|
|
72
|
-
"lit": "^3.3.1",
|
|
73
72
|
"mapbox-gl": "^3.14.0",
|
|
74
73
|
"n3": "^1.26.0",
|
|
75
74
|
"rdfxml-streaming-parser": "^3.1.0",
|
|
@@ -77,7 +76,8 @@
|
|
|
77
76
|
"uuid": "^11.1.0"
|
|
78
77
|
},
|
|
79
78
|
"peerDependencies": {
|
|
80
|
-
"
|
|
79
|
+
"lit": "^3.3.1",
|
|
80
|
+
"@ro-kit/ui-widgets": "^0.0.43",
|
|
81
81
|
"mdui": "^2.1.4"
|
|
82
82
|
}
|
|
83
83
|
}
|
package/src/config.ts
CHANGED
|
@@ -22,6 +22,7 @@ export class ElementAttributes {
|
|
|
22
22
|
view: string | null = null
|
|
23
23
|
language: string | null = null
|
|
24
24
|
loading: string = 'Loading\u2026'
|
|
25
|
+
proxy: string | null = null
|
|
25
26
|
ignoreOwlImports: string | null = null
|
|
26
27
|
collapse: string | null = null
|
|
27
28
|
submitButton: string | null = null
|
|
@@ -100,7 +101,7 @@ export class Config {
|
|
|
100
101
|
|
|
101
102
|
set store(store: Store) {
|
|
102
103
|
this._store = store
|
|
103
|
-
this.lists = extractLists(store)
|
|
104
|
+
this.lists = extractLists(store, { ignoreErrors: true })
|
|
104
105
|
this.groups = []
|
|
105
106
|
store.forSubjects(subject => {
|
|
106
107
|
this.groups.push(subject.id)
|
package/src/constants.ts
CHANGED
|
@@ -24,6 +24,7 @@ export const SHACL_OBJECT_NODE_SHAPE = DataFactory.namedNode(PREFIX_SHACL + 'Nod
|
|
|
24
24
|
export const SHACL_OBJECT_IRI = DataFactory.namedNode(PREFIX_SHACL + 'IRI')
|
|
25
25
|
export const SHACL_PREDICATE_PROPERTY = DataFactory.namedNode(PREFIX_SHACL + 'property')
|
|
26
26
|
export const SHACL_PREDICATE_CLASS = DataFactory.namedNode(PREFIX_SHACL + 'class')
|
|
27
|
+
export const SHACL_PREDICATE_NODE = DataFactory.namedNode(PREFIX_SHACL + 'node')
|
|
27
28
|
export const SHACL_PREDICATE_TARGET_CLASS = DataFactory.namedNode(PREFIX_SHACL + 'targetClass')
|
|
28
29
|
export const SHACL_PREDICATE_NODE_KIND = DataFactory.namedNode(PREFIX_SHACL + 'nodeKind')
|
|
29
30
|
export const XSD_DATATYPE_STRING = DataFactory.namedNode(PREFIX_XSD + 'string')
|
package/src/exports.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { InputListEntry, Editor } from './theme'
|
|
2
2
|
export { Theme } from './theme'
|
|
3
|
-
export { Loader
|
|
3
|
+
export { Loader } from './loader'
|
|
4
4
|
export { Config } from './config'
|
|
5
5
|
export { Plugin, registerPlugin } from './plugin'
|
|
6
6
|
export { ShaclPropertyTemplate } from './property-template'
|
package/src/form.ts
CHANGED
|
@@ -6,7 +6,6 @@ import { DATA_GRAPH, DCTERMS_PREDICATE_CONFORMS_TO, PREFIX_SHACL, RDF_PREDICATE_
|
|
|
6
6
|
import { Editor, Theme } from './theme'
|
|
7
7
|
import { serialize } from './serialize'
|
|
8
8
|
import { Validator } from 'shacl-engine'
|
|
9
|
-
import { setSharedShapesGraph } from './loader'
|
|
10
9
|
import { RokitCollapsible } from '@ro-kit/ui-widgets'
|
|
11
10
|
|
|
12
11
|
export class ShaclForm extends HTMLElement {
|
|
@@ -140,11 +139,6 @@ export class ShaclForm extends HTMLElement {
|
|
|
140
139
|
this.initialize()
|
|
141
140
|
}
|
|
142
141
|
|
|
143
|
-
public setSharedShapesGraph(graph: Store) {
|
|
144
|
-
setSharedShapesGraph(graph)
|
|
145
|
-
this.initialize()
|
|
146
|
-
}
|
|
147
|
-
|
|
148
142
|
public setClassInstanceProvider(provider: ClassInstanceProvider) {
|
|
149
143
|
this.config.classInstanceProvider = provider
|
|
150
144
|
this.initialize()
|
|
@@ -165,8 +159,8 @@ export class ShaclForm extends HTMLElement {
|
|
|
165
159
|
}
|
|
166
160
|
|
|
167
161
|
this.config.store.deleteGraph(this.config.valuesGraphId || '')
|
|
168
|
-
this.shape?.toRDF(this.config.store)
|
|
169
162
|
if (this.shape) {
|
|
163
|
+
this.shape.toRDF(this.config.store)
|
|
170
164
|
// add node target for validation. this is required in case of missing sh:targetClass in root shape
|
|
171
165
|
this.config.store.add(new Quad(this.shape.shaclSubject, DataFactory.namedNode(PREFIX_SHACL + 'targetNode'), this.shape.nodeId, this.config.valuesGraphId))
|
|
172
166
|
}
|
package/src/loader.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Store, Quad, NamedNode, DataFactory, StreamParser } from 'n3'
|
|
2
|
-
import { DATA_GRAPH, DCTERMS_PREDICATE_CONFORMS_TO, OWL_PREDICATE_IMPORTS,
|
|
2
|
+
import { DATA_GRAPH, DCTERMS_PREDICATE_CONFORMS_TO, OWL_PREDICATE_IMPORTS, SHACL_PREDICATE_CLASS, SHACL_PREDICATE_TARGET_CLASS, SHAPES_GRAPH } from './constants'
|
|
3
3
|
import { Config } from './config'
|
|
4
4
|
import { isURL } from './util'
|
|
5
5
|
import { RdfXmlParser } from 'rdfxml-streaming-parser'
|
|
@@ -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
|
-
let sharedShapesGraph: Store | undefined
|
|
15
14
|
|
|
16
15
|
export class Loader {
|
|
17
16
|
private config: Config
|
|
@@ -26,24 +25,22 @@ export class Loader {
|
|
|
26
25
|
// clear local caches
|
|
27
26
|
this.loadedExternalUrls = []
|
|
28
27
|
this.loadedClasses = []
|
|
29
|
-
|
|
30
|
-
let store = sharedShapesGraph
|
|
31
28
|
this.config.prefixes = {}
|
|
32
29
|
|
|
30
|
+
|
|
33
31
|
const promises: Promise<void>[] = []
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
promises.push(this.importRDF(this.config.attributes.values ? this.config.attributes.values : this.config.attributes.valuesUrl ? fetchRDF(this.config.attributes.valuesUrl) : '', store, DATA_GRAPH))
|
|
32
|
+
const store = new Store()
|
|
33
|
+
promises.push(this.importRDF(this.config.attributes.shapes ? this.config.attributes.shapes : this.config.attributes.shapesUrl ? this.fetchRDF(this.config.attributes.shapesUrl) : '', store, SHAPES_GRAPH))
|
|
34
|
+
promises.push(this.importRDF(this.config.attributes.values ? this.config.attributes.values : this.config.attributes.valuesUrl ? this.fetchRDF(this.config.attributes.valuesUrl) : '', store, DATA_GRAPH))
|
|
39
35
|
await Promise.all(promises)
|
|
40
36
|
|
|
41
37
|
// if shapes graph is empty, but we have the following triples:
|
|
42
38
|
// <valueSubject> a <uri> or <valueSubject> dcterms:conformsTo <uri>
|
|
43
|
-
//
|
|
44
|
-
|
|
39
|
+
// or if we have data-shape-subject set on the form,
|
|
40
|
+
// then try to load the referenced object(s) into the shapes graph
|
|
41
|
+
if (store.countQuads(null, null, null, SHAPES_GRAPH) === 0 && this.config.attributes.valuesSubject) {
|
|
45
42
|
const shapeCandidates = [
|
|
46
|
-
...store.getObjects(this.config.attributes.valuesSubject, RDF_PREDICATE_TYPE, DATA_GRAPH),
|
|
43
|
+
// ...store.getObjects(this.config.attributes.valuesSubject, RDF_PREDICATE_TYPE, DATA_GRAPH),
|
|
47
44
|
...store.getObjects(this.config.attributes.valuesSubject, DCTERMS_PREDICATE_CONFORMS_TO, DATA_GRAPH)
|
|
48
45
|
]
|
|
49
46
|
const promises: Promise<void>[] = []
|
|
@@ -51,7 +48,7 @@ export class Loader {
|
|
|
51
48
|
const url = this.toURL(uri.value)
|
|
52
49
|
if (url && this.loadedExternalUrls.indexOf(url) < 0) {
|
|
53
50
|
this.loadedExternalUrls.push(url)
|
|
54
|
-
promises.push(this.importRDF(fetchRDF(url), store, SHAPES_GRAPH))
|
|
51
|
+
promises.push(this.importRDF(this.fetchRDF(url), store, SHAPES_GRAPH))
|
|
55
52
|
}
|
|
56
53
|
}
|
|
57
54
|
try {
|
|
@@ -78,11 +75,11 @@ export class Loader {
|
|
|
78
75
|
if (url && this.loadedExternalUrls.indexOf(url) < 0) {
|
|
79
76
|
this.loadedExternalUrls.push(url)
|
|
80
77
|
// import into separate graph
|
|
81
|
-
dependencies.push(this.importRDF(fetchRDF(url), store, DataFactory.namedNode(url)))
|
|
78
|
+
dependencies.push(this.importRDF(this.fetchRDF(url), store, DataFactory.namedNode(url)))
|
|
82
79
|
}
|
|
83
80
|
}
|
|
84
81
|
// check if this is an sh:class predicate and invoke class instance provider
|
|
85
|
-
if (this.config.classInstanceProvider && SHACL_PREDICATE_CLASS.equals(quad.predicate)) {
|
|
82
|
+
if (this.config.classInstanceProvider && (SHACL_PREDICATE_CLASS.equals(quad.predicate) || SHACL_PREDICATE_TARGET_CLASS.equals(quad.predicate))) {
|
|
86
83
|
const className = quad.object.value
|
|
87
84
|
// import class definitions only once
|
|
88
85
|
if (this.loadedClasses.indexOf(className) < 0) {
|
|
@@ -159,20 +156,24 @@ export class Loader {
|
|
|
159
156
|
return null
|
|
160
157
|
}
|
|
161
158
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
159
|
+
async fetchRDF(url: string): Promise<string> {
|
|
160
|
+
// try to load from cache first
|
|
161
|
+
if (url in loadedURLCache) {
|
|
162
|
+
return loadedURLCache[url]
|
|
163
|
+
}
|
|
164
|
+
let proxiedURL = url
|
|
165
|
+
// if we have a proxy configured, then load url via proxy
|
|
166
|
+
if (this.config.attributes.proxy) {
|
|
167
|
+
proxiedURL = this.config.attributes.proxy + encodeURIComponent(url)
|
|
168
|
+
}
|
|
169
|
+
const promise = fetch(proxiedURL, {
|
|
170
|
+
headers: {
|
|
171
|
+
'Accept': 'text/turtle, application/trig, application/n-triples, application/n-quads, text/n3, application/ld+json'
|
|
172
|
+
},
|
|
173
|
+
}).then(resp => resp.text())
|
|
174
|
+
loadedURLCache[url] = promise
|
|
175
|
+
return promise
|
|
168
176
|
}
|
|
169
|
-
const promise = fetch(url, {
|
|
170
|
-
headers: {
|
|
171
|
-
'Accept': 'text/turtle, application/trig, application/n-triples, application/n-quads, text/n3, application/ld+json'
|
|
172
|
-
},
|
|
173
|
-
}).then(resp => resp.text())
|
|
174
|
-
loadedURLCache[url] = promise
|
|
175
|
-
return promise
|
|
176
177
|
}
|
|
177
178
|
|
|
178
179
|
/* Can't rely on HTTP content-type header, since many resources are delivered with text/plain */
|
|
@@ -184,7 +185,3 @@ function guessContentType(input: string) {
|
|
|
184
185
|
}
|
|
185
186
|
return 'ttl'
|
|
186
187
|
}
|
|
187
|
-
|
|
188
|
-
export function setSharedShapesGraph(graph: Store) {
|
|
189
|
-
sharedShapesGraph = graph
|
|
190
|
-
}
|
package/src/node.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BlankNode, DataFactory, NamedNode, Store } from 'n3'
|
|
2
2
|
import { Term } from '@rdfjs/types'
|
|
3
|
-
import { PREFIX_SHACL, RDF_PREDICATE_TYPE, OWL_PREDICATE_IMPORTS, SHACL_PREDICATE_PROPERTY } from './constants'
|
|
3
|
+
import { PREFIX_SHACL, RDF_PREDICATE_TYPE, OWL_PREDICATE_IMPORTS, SHACL_PREDICATE_PROPERTY, SHACL_PREDICATE_NODE } from './constants'
|
|
4
4
|
import { ShaclProperty } from './property'
|
|
5
5
|
import { createShaclGroup } from './group'
|
|
6
6
|
import { v4 as uuidv4 } from 'uuid'
|
|
@@ -97,7 +97,7 @@ export class ShaclNode extends HTMLElement {
|
|
|
97
97
|
console.error('list not found:', quad.object.value, 'existing lists:', config.lists)
|
|
98
98
|
}
|
|
99
99
|
break;
|
|
100
|
-
case
|
|
100
|
+
case SHACL_PREDICATE_NODE.id:
|
|
101
101
|
// inheritance via sh:node
|
|
102
102
|
this.prepend(new ShaclNode(quad.object as NamedNode, config, valueSubject, this))
|
|
103
103
|
break;
|
package/src/property.ts
CHANGED
|
@@ -192,6 +192,7 @@ export class ShaclProperty extends HTMLElement {
|
|
|
192
192
|
addButton.dense = true
|
|
193
193
|
addButton.label = "+ " + this.template.label
|
|
194
194
|
addButton.title = 'Add ' + this.template.label
|
|
195
|
+
addButton.autoGrowLabelWidth = true
|
|
195
196
|
addButton.classList.add('add-button')
|
|
196
197
|
|
|
197
198
|
// load potential value candidates for linking
|
package/src/serialize.ts
CHANGED
|
@@ -49,7 +49,9 @@ export function toRDF(editor: Editor): Literal | NamedNode | undefined {
|
|
|
49
49
|
let languageOrDatatype: NamedNode<string> | string | undefined = editor.shaclDatatype
|
|
50
50
|
let value: number | string = editor.value
|
|
51
51
|
if (value) {
|
|
52
|
-
if (
|
|
52
|
+
if (value.startsWith('<') && value.endsWith('>') && value.indexOf(':') > -1) {
|
|
53
|
+
return DataFactory.namedNode(value.substring(1, value.length - 1))
|
|
54
|
+
} else if (editor.dataset.class || editor.dataset.nodeKind === PREFIX_SHACL + 'IRI') {
|
|
53
55
|
return DataFactory.namedNode(value)
|
|
54
56
|
} else if (editor.dataset.link) {
|
|
55
57
|
return JSON.parse(editor.dataset.link)
|
package/src/themes/default.ts
CHANGED
|
@@ -220,8 +220,10 @@ export class DefaultTheme extends Theme {
|
|
|
220
220
|
} else {
|
|
221
221
|
if (entry.value instanceof Literal && entry.value.datatype.equals(XSD_DATATYPE_STRING)) {
|
|
222
222
|
li.dataset.value = entry.value.value
|
|
223
|
+
} else if (entry.value instanceof NamedNode) {
|
|
224
|
+
li.dataset.value = '<' + entry.value.value + ">"
|
|
223
225
|
} else {
|
|
224
|
-
// this is needed for typed rdf literals
|
|
226
|
+
// this is needed for typed rdf literals e.g. "ex"^^xsd:anyUri
|
|
225
227
|
li.dataset.value = (entry.value as N3Term).id
|
|
226
228
|
}
|
|
227
229
|
li.innerText = entry.label ? entry.label : entry.value.value
|