@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ulb-darmstadt/shacl-form",
3
- "version": "1.9.4",
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
- "@ro-kit/ui-widgets": "^0.0.36",
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, setSharedShapesGraph } from './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, RDF_PREDICATE_TYPE, SHACL_PREDICATE_CLASS, SHAPES_GRAPH } from './constants'
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
- if (!store) {
35
- store = new Store()
36
- promises.push(this.importRDF(this.config.attributes.shapes ? this.config.attributes.shapes : this.config.attributes.shapesUrl ? fetchRDF(this.config.attributes.shapesUrl) : '', store, SHAPES_GRAPH))
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
- // then try to load the referenced object into the shapes graph
44
- if (!sharedShapesGraph && store.countQuads(null, null, null, SHAPES_GRAPH) === 0 && this.config.attributes.valuesSubject) {
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
- async function fetchRDF(url: string): Promise<string> {
165
- // try to load from cache first
166
- if (url in loadedURLCache) {
167
- return loadedURLCache[url]
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 `${PREFIX_SHACL}node`:
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 (editor.dataset.class || editor.dataset.nodeKind === PREFIX_SHACL + 'IRI') {
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)
@@ -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