Skip to content

Commit

Permalink
improved plugin registration
Browse files Browse the repository at this point in the history
  • Loading branch information
s-tittel committed Apr 9, 2024
1 parent 0bc98b7 commit f6da5d8
Show file tree
Hide file tree
Showing 12 changed files with 351 additions and 278 deletions.
13 changes: 3 additions & 10 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
</script>
<script type="module">
import '@ulb-darmstadt/shacl-form/form-default.js'
import { registerPlugin } from '@ulb-darmstadt/shacl-form/form-default.js'
import { LeafletPlugin } from '@ulb-darmstadt/shacl-form/plugins/leaflet.js'
registerPlugin(new LeafletPlugin({ datatype: 'http://www.opengis.net/ont/geosparql#wktLiteral' }))
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/styles/vs.min.css">
<script src="https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/highlight.min.js"></script>
Expand Down Expand Up @@ -187,13 +190,9 @@ <h1>&lt;shacl-form&gt; demo</h1>
<fieldset id="shacl-output" class="mt-1"><legend>Output generated by the form</legend><pre></pre></fieldset>
<script type="module">
// import { MapboxPlugin } from '@ulb-darmstadt/shacl-form/plugins/mapbox.js'
import { LeafletPlugin } from '@ulb-darmstadt/shacl-form/plugins/leaflet.js'

setTimeout(async () => {
const form = document.getElementById("shacl-form")
// form.registerPlugin(new MapboxPlugin({ datatype: 'http://www.opengis.net/ont/geosparql#wktLiteral' }, 'pk.eyJ1IjoiaHViZXJtb3NlciIsImEiOiJja3c2NDI2MXAwbWx0MnVudnJiOGV6NjRqIn0.va4IWkUk-USoL2Z8FylNzA'))
form.registerPlugin(new LeafletPlugin({ datatype: 'http://www.opengis.net/ont/geosparql#wktLiteral' }))

const shapes = document.getElementById("shacl-shape-input")
const data = document.getElementById("shacl-data-input")
const output = document.getElementById("shacl-output")
Expand Down Expand Up @@ -235,14 +234,8 @@ <h1>&lt;shacl-form&gt; demo</h1>
<fieldset><legend>Generated viewer</legend><shacl-form id="shacl-form" data-collapse="open" data-view data-value-subject="http://example.org/4f2a8de3-9fc8-40a9-9237-d5964520ec54"></shacl-form></fieldset>
</div>
<script type="module">
// import { MapboxPlugin } from '@ulb-darmstadt/shacl-form/plugins/mapbox.js'
import { LeafletPlugin } from '@ulb-darmstadt/shacl-form/plugins/leaflet.js'

setTimeout(async () => {
const form = document.getElementById("shacl-form")
// form.registerPlugin(new MapboxPlugin({ datatype: 'http://www.opengis.net/ont/geosparql#wktLiteral' }, 'pk.eyJ1IjoiaHViZXJtb3NlciIsImEiOiJja3c2NDI2MXAwbWx0MnVudnJiOGV6NjRqIn0.va4IWkUk-USoL2Z8FylNzA'))
form.registerPlugin(new LeafletPlugin({ datatype: 'http://www.opengis.net/ont/geosparql#wktLiteral' }))

const shapes = document.getElementById("shacl-shape-input")
const data = document.getElementById("shacl-data-input")
form.setClassInstanceProvider((clazz) => {
Expand Down
324 changes: 192 additions & 132 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
},
"devDependencies": {
"@types/jsonld": "^1.5.13",
"@types/leaflet": "^1.9.8",
"@types/leaflet-draw": "^1.0.11",
"@types/leaflet": "^1.9.9",
"@types/leaflet-editable": "^1.2.6",
"@types/leaflet.fullscreen": "^3.0.2",
"@types/mapbox__mapbox-gl-draw": "^1.4.6",
"@types/n3": "^1.16.4",
Expand All @@ -53,10 +53,10 @@
"bootstrap": "^5.3.3",
"jsonld": "^8.3.2",
"leaflet": "^1.9.4",
"leaflet-draw": "^1.0.4",
"leaflet-editable": "^1.2.0",
"leaflet.fullscreen": "^3.0.1",
"mapbox-gl": "^3.2.0",
"n3": "^1.17.2",
"n3": "^1.17.3",
"rdf-validate-shacl": "^0.5.3",
"uuid": "^9.0.1"
}
Expand Down
3 changes: 1 addition & 2 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Prefixes, Store } from 'n3'
import { Term } from '@rdfjs/types'
import { PREFIX_SHACL, RDF_PREDICATE_TYPE, SHAPES_GRAPH } from './constants'
import { ClassInstanceProvider, Plugins } from './plugin'
import { ClassInstanceProvider } from './plugin'
import { Loader } from './loader'
import { Theme } from './theme'

Expand All @@ -26,7 +26,6 @@ export class Config {
loader = new Loader(this)
classInstanceProvider: ClassInstanceProvider | undefined
prefixes: Prefixes = {}
plugins = new Plugins()
editMode = true

dataGraph = new Store()
Expand Down
2 changes: 1 addition & 1 deletion src/exports.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { Theme, InputListEntry, Editor } from './theme'
export { Loader } from './loader'
export { Config } from './config'
export { Plugin } from './plugin'
export { Plugin, registerPlugin } from './plugin'
export { ShaclPropertyTemplate } from './property-template'
export { findLabel } from './util'
8 changes: 4 additions & 4 deletions src/form.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ShaclNode } from './node'
import { Config } from './config'
import { ClassInstanceProvider, Plugin, PluginOptions } from './plugin'
import { ClassInstanceProvider, Plugin, listPlugins, registerPlugin } from './plugin'
import { Quad, Store, NamedNode, DataFactory } from 'n3'
import { RDF_PREDICATE_TYPE, SHACL_OBJECT_NODE_SHAPE, SHACL_PREDICATE_TARGET_CLASS, SHAPES_GRAPH } from './constants'
import { Editor, Theme } from './theme'
Expand Down Expand Up @@ -60,7 +60,7 @@ export class ShaclForm extends HTMLElement {
this.config.theme.apply(this.form)
// adopt stylesheets from theme and plugins
const styles: CSSStyleSheet[] = [ this.config.theme.stylesheet ]
for (const plugin of this.config.plugins.list()) {
for (const plugin of listPlugins()) {
if (plugin.stylesheet) {
styles.push(plugin.stylesheet)
}
Expand Down Expand Up @@ -117,8 +117,8 @@ export class ShaclForm extends HTMLElement {
return graph
}

public registerPlugin(plugin: Plugin, options?: PluginOptions) {
this.config.plugins.register(plugin)
public registerPlugin(plugin: Plugin) {
registerPlugin(plugin)
this.initialize()
}

Expand Down
18 changes: 9 additions & 9 deletions src/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,17 @@ export class ShaclNode extends HTMLElement {
nodeKind = spec[0] as NamedNode
}
}
if (nodeKind === undefined && config.attributes.valuesNamespace) {
// if nodeKind is not set, but a value namespace is configured or if nodeKind is sh:IRI, then create a NamedNode
if ((nodeKind === undefined && config.attributes.valuesNamespace) || nodeKind?.id === `${PREFIX_SHACL}IRI`) {
// no requirements on node type, so create a NamedNode and use configured value namespace
nodeId = DataFactory.namedNode(config.attributes.valuesNamespace + uuidv4())
}
else if (nodeKind?.id === `${PREFIX_SHACL}IRI`) {
nodeId = DataFactory.namedNode(config.attributes.valuesNamespace + uuidv4())
}
else {
// default to BlankNode
} else {
// otherwise create a BlankNode
nodeId = DataFactory.blankNode(uuidv4())
}
}
this.nodeId = nodeId
this.dataset.nodeId = this.nodeId.id


const quads = config.shapesGraph.getQuads(shaclSubject, null, null, SHAPES_GRAPH)
let list: Term[] | undefined
Expand All @@ -66,7 +62,11 @@ export class ShaclNode extends HTMLElement {
console.warn('ignoring unknown group reference', groupRef[0])
}
}
parent.appendChild(new ShaclProperty(quad.object as NamedNode | BlankNode, config, this.nodeId, valueSubject))
const property = new ShaclProperty(quad.object as NamedNode | BlankNode, config, this.nodeId, valueSubject)
// do not add empty properties (i.e. properties with no instances). This can be the case e.g. in viewer mode when there is no data for the respective property.
if (property.childElementCount > 0) {
parent.appendChild(property)
}
break;
case `${PREFIX_SHACL}and`:
// inheritance via sh:and
Expand Down
49 changes: 24 additions & 25 deletions src/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,34 @@
import { ShaclPropertyTemplate } from './property-template'
import { Term } from '@rdfjs/types'

export class Plugins {
private plugins: Record<string, Plugin> = {}

register(plugin: Plugin) {
if (plugin.predicate === undefined && plugin.datatype === undefined) {
console.warn('not registering plugin because it does neither define "predicate" nor "datatype"', plugin)
} else {
this.plugins[`${plugin.predicate}^${plugin.datatype}`] = plugin
}
// store plugins in module scope so that they apply to all shacl-form elements
const plugins: Record<string, Plugin> = {}

export function registerPlugin(plugin: Plugin) {
if (plugin.predicate === undefined && plugin.datatype === undefined) {
console.warn('not registering plugin because it does neither define "predicate" nor "datatype"', plugin)
} else {
plugins[`${plugin.predicate}^${plugin.datatype}`] = plugin
}
}

list(): Plugin[] {
return Object.entries(this.plugins).map((value: [_: string, plugin: Plugin]) => { return value[1] })
}
export function listPlugins(): Plugin[] {
return Object.entries(plugins).map((value: [_: string, plugin: Plugin]) => { return value[1] })
}

find(predicate: string | undefined, datatype: string | undefined): Plugin | undefined {
// first try to find plugin with matching predicate and datatype
let plugin = this.plugins[`${predicate}^${datatype}`]
if (plugin) {
return plugin
}
// now prefer predicate over datatype
plugin = this.plugins[`${predicate}^${undefined}`]
if (plugin) {
return plugin
}
// last, try to find plugin with matching datatype
return this.plugins[`${undefined}^${datatype}`]
export function findPlugin(predicate: string | undefined, datatype: string | undefined): Plugin | undefined {
// first try to find plugin with matching predicate and datatype
let plugin = plugins[`${predicate}^${datatype}`]
if (plugin) {
return plugin
}
// now prefer predicate over datatype
plugin = plugins[`${predicate}^${undefined}`]
if (plugin) {
return plugin
}
// last, try to find plugin with matching datatype
return plugins[`${undefined}^${datatype}`]
}

export type PluginOptions = {
Expand Down
Loading

0 comments on commit f6da5d8

Please sign in to comment.