@opengeospatial/jsonld-ui-utils 0.2.0 → 0.2.7
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 +96 -74
- package/dist/index.cjs.js +458 -423
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.esm.js +458 -422
- package/dist/index.esm.js.map +1 -1
- package/dist/jsonld-ui-utils-leaflet.min.js +26 -0
- package/dist/jsonld-ui-utils-leaflet.min.js.map +1 -0
- package/dist/jsonld-ui-utils.css +45 -0
- package/dist/jsonld-ui-utils.min.js +4 -49
- package/dist/jsonld-ui-utils.min.js.map +1 -1
- package/dist/jsonld.d.ts +2 -2
- package/dist/leaflet.cjs.js +549 -0
- package/dist/leaflet.cjs.js.map +1 -0
- package/dist/leaflet.d.ts +10 -0
- package/dist/leaflet.esm.js +528 -0
- package/dist/leaflet.esm.js.map +1 -0
- package/dist/resource.d.ts +1 -2
- package/package.json +30 -8
package/dist/index.cjs.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var N3 = require('n3');
|
|
6
|
-
var jsonldLib = require('jsonld');
|
|
7
6
|
var rdfxmlStreamingParser = require('rdfxml-streaming-parser');
|
|
8
7
|
|
|
9
8
|
function _interopNamespaceDefault(e) {
|
|
@@ -24,85 +23,85 @@ function _interopNamespaceDefault(e) {
|
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
var N3__namespace = /*#__PURE__*/_interopNamespaceDefault(N3);
|
|
27
|
-
var jsonldLib__namespace = /*#__PURE__*/_interopNamespaceDefault(jsonldLib);
|
|
28
26
|
|
|
29
|
-
const jsonFetch = async url => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
});
|
|
35
|
-
return await response.json();
|
|
27
|
+
const jsonFetch = async (url) => {
|
|
28
|
+
const response = await fetch(url, {
|
|
29
|
+
headers: { 'Accept': 'application/json' },
|
|
30
|
+
});
|
|
31
|
+
return await response.json();
|
|
36
32
|
};
|
|
37
|
-
const mergeContexts = definitions => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
const mergeContexts = (definitions) => {
|
|
34
|
+
const mergePair = (a, b) => {
|
|
35
|
+
if (!a || !Object.keys(a).length) {
|
|
36
|
+
return b;
|
|
37
|
+
}
|
|
38
|
+
const result = { ...a };
|
|
39
|
+
for (const [k, v] of Object.entries(b)) {
|
|
40
|
+
result[k] = v;
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
44
43
|
};
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
if (!definitions.length) {
|
|
45
|
+
return {};
|
|
47
46
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
let currentContext = definitions[0];
|
|
57
|
-
for (let i = 1; i < definitions.length; i++) {
|
|
58
|
-
currentContext = mergePair(currentContext, definitions[i]);
|
|
59
|
-
}
|
|
60
|
-
return currentContext;
|
|
47
|
+
if (definitions.length === 1) {
|
|
48
|
+
return definitions[0];
|
|
49
|
+
}
|
|
50
|
+
let currentContext = definitions[0];
|
|
51
|
+
for (let i = 1; i < definitions.length; i++) {
|
|
52
|
+
currentContext = mergePair(currentContext, definitions[i]);
|
|
53
|
+
}
|
|
54
|
+
return currentContext;
|
|
61
55
|
};
|
|
62
56
|
async function loadContext(context) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
57
|
+
const loadedUrls = new Map();
|
|
58
|
+
const walk = async (definition, refChain) => {
|
|
59
|
+
for (const [key, value] of Object.entries(definition)) {
|
|
60
|
+
if (key === '@context') {
|
|
61
|
+
// @ts-ignore
|
|
62
|
+
definition[key] = await load(value, refChain);
|
|
63
|
+
}
|
|
64
|
+
else if (typeof value === 'object' && value !== null) {
|
|
65
|
+
await walk(value, refChain);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const load = async (context, refChain) => {
|
|
70
|
+
if (context === null || typeof context === 'undefined') {
|
|
71
|
+
return {};
|
|
72
|
+
}
|
|
73
|
+
if (Array.isArray(context)) {
|
|
74
|
+
// fetch and merge
|
|
75
|
+
const contextEntries = await Promise.all(context.map(e => load(e, refChain)));
|
|
76
|
+
return mergeContexts(contextEntries);
|
|
77
|
+
}
|
|
78
|
+
else if (typeof context === 'object') {
|
|
79
|
+
await walk(context, refChain);
|
|
80
|
+
return context;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
if (refChain === null || refChain === void 0 ? void 0 : refChain.includes(context)) {
|
|
84
|
+
throw new Error('Circular dependencies found: ' + refChain.join(' -> ') + ' -> ' + context);
|
|
85
|
+
}
|
|
86
|
+
const newRefChain = Array.isArray(refChain) ? refChain === null || refChain === void 0 ? void 0 : refChain.slice() : [];
|
|
87
|
+
newRefChain.push(context);
|
|
88
|
+
let newContext;
|
|
89
|
+
if (!loadedUrls.has(context)) {
|
|
90
|
+
newContext = await jsonFetch(context);
|
|
91
|
+
loadedUrls.set(context, newContext);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
newContext = loadedUrls.get(context);
|
|
95
|
+
}
|
|
96
|
+
return load(newContext['@context'], newRefChain);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
if (typeof context === 'object' && context !== null && '@context' in context) {
|
|
100
|
+
return load(context['@context']);
|
|
77
101
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const contextEntries = await Promise.all(context.map(e => load(e, refChain)));
|
|
81
|
-
return mergeContexts(contextEntries);
|
|
82
|
-
} else if (typeof context === 'object') {
|
|
83
|
-
await walk(context, refChain);
|
|
84
|
-
return context;
|
|
85
|
-
} else {
|
|
86
|
-
if (refChain === null || refChain === void 0 ? void 0 : refChain.includes(context)) {
|
|
87
|
-
throw new Error('Circular dependencies found: ' + refChain.join(' -> ') + ' -> ' + context);
|
|
88
|
-
}
|
|
89
|
-
const newRefChain = Array.isArray(refChain) ? refChain === null || refChain === void 0 ? void 0 : refChain.slice() : [];
|
|
90
|
-
newRefChain.push(context);
|
|
91
|
-
let newContext;
|
|
92
|
-
if (!loadedUrls.has(context)) {
|
|
93
|
-
newContext = await jsonFetch(context);
|
|
94
|
-
loadedUrls.set(context, newContext);
|
|
95
|
-
} else {
|
|
96
|
-
newContext = loadedUrls.get(context);
|
|
97
|
-
}
|
|
98
|
-
return load(newContext['@context'], newRefChain);
|
|
102
|
+
else {
|
|
103
|
+
return load(context);
|
|
99
104
|
}
|
|
100
|
-
};
|
|
101
|
-
if (typeof context === 'object' && context !== null && '@context' in context) {
|
|
102
|
-
return load(context['@context']);
|
|
103
|
-
} else {
|
|
104
|
-
return load(context);
|
|
105
|
-
}
|
|
106
105
|
}
|
|
107
106
|
|
|
108
107
|
var jsonld = /*#__PURE__*/Object.freeze({
|
|
@@ -110,168 +109,206 @@ var jsonld = /*#__PURE__*/Object.freeze({
|
|
|
110
109
|
loadContext: loadContext
|
|
111
110
|
});
|
|
112
111
|
|
|
113
|
-
const ns = base => local => `${base}${local}`;
|
|
112
|
+
const ns = (base) => (local) => `${base}${local}`;
|
|
114
113
|
const SKOS = ns('http://www.w3.org/2004/02/skos/core#');
|
|
115
114
|
const RDFS = ns('http://www.w3.org/2000/01/rdf-schema#');
|
|
116
115
|
const DCT = ns('http://purl.org/dc/terms/');
|
|
117
116
|
const DC = ns('http://purl.org/dc/elements/1.1/');
|
|
118
117
|
const SDO = ns('https://schema.org/');
|
|
119
118
|
const FOAF = ns('http://xmlns.com/foaf/0.1/');
|
|
120
|
-
const labelPredicates = [
|
|
121
|
-
|
|
119
|
+
const labelPredicates = [
|
|
120
|
+
SKOS('prefLabel'),
|
|
121
|
+
DCT('title'),
|
|
122
|
+
DC('title'),
|
|
123
|
+
SDO('name'),
|
|
124
|
+
FOAF('name'),
|
|
125
|
+
RDFS('label'),
|
|
126
|
+
];
|
|
127
|
+
const descriptionPredicates = [
|
|
128
|
+
SKOS('definition'),
|
|
129
|
+
DCT('description'),
|
|
130
|
+
DC('description'),
|
|
131
|
+
RDFS('comment'),
|
|
132
|
+
];
|
|
122
133
|
|
|
123
134
|
const defaultFetchResourceOptions = {
|
|
124
|
-
|
|
125
|
-
|
|
135
|
+
labelPredicates,
|
|
136
|
+
descriptionPredicates,
|
|
126
137
|
};
|
|
127
138
|
const fetchResourceCache = {};
|
|
128
|
-
const
|
|
129
|
-
const
|
|
139
|
+
const requestCache = {};
|
|
140
|
+
const N3_CONTENT_TYPES = new Set([
|
|
141
|
+
'text/turtle',
|
|
142
|
+
'text/n3',
|
|
143
|
+
'application/n-triples',
|
|
144
|
+
'application/n-quads',
|
|
145
|
+
'application/trig',
|
|
146
|
+
'text/anot+turtle',
|
|
147
|
+
]);
|
|
148
|
+
const ACCEPT_HEADER = [
|
|
149
|
+
'text/turtle',
|
|
150
|
+
'application/n-triples',
|
|
151
|
+
'application/n-quads',
|
|
152
|
+
'application/trig',
|
|
153
|
+
'application/ld+json',
|
|
154
|
+
'application/rdf+xml',
|
|
155
|
+
].join(', ');
|
|
130
156
|
function findInStore(store, subjectUri, predicates) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
157
|
+
var _a;
|
|
158
|
+
const subj = N3__namespace.DataFactory.namedNode(subjectUri);
|
|
159
|
+
for (const predUri of predicates) {
|
|
160
|
+
const quads = store
|
|
161
|
+
.getQuads(subj, N3__namespace.DataFactory.namedNode(predUri), null, null)
|
|
162
|
+
.filter(q => q.object.termType === 'Literal');
|
|
163
|
+
if (!quads.length) {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const en = quads.find(q => q.object.language === 'en');
|
|
167
|
+
const noLang = quads.find(q => !q.object.language);
|
|
168
|
+
return ((_a = en !== null && en !== void 0 ? en : noLang) !== null && _a !== void 0 ? _a : quads[0]).object.value;
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
141
171
|
}
|
|
142
172
|
function parseTurtle(text, baseIRI, contentType) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
173
|
+
const store = new N3__namespace.Store();
|
|
174
|
+
const format = contentType === 'text/anot+turtle' ? 'text/turtle' : contentType;
|
|
175
|
+
const parser = new N3__namespace.Parser({ baseIRI, format });
|
|
176
|
+
return new Promise((resolve, reject) => {
|
|
177
|
+
parser.parse(text, (err, quad) => {
|
|
178
|
+
if (err) {
|
|
179
|
+
return reject(err);
|
|
180
|
+
}
|
|
181
|
+
if (quad) {
|
|
182
|
+
store.addQuad(quad);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
resolve(store);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
153
188
|
});
|
|
154
|
-
});
|
|
155
189
|
}
|
|
156
190
|
async function parseJsonLd(text, baseIRI) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
191
|
+
const jsonldMod = await import('jsonld');
|
|
192
|
+
if (!jsonldMod) {
|
|
193
|
+
throw new Error('jsonld peer dependency is not available');
|
|
194
|
+
}
|
|
195
|
+
const doc = JSON.parse(text);
|
|
196
|
+
const nquads = await jsonldMod.toRDF(doc, { format: 'application/n-quads', base: baseIRI });
|
|
197
|
+
return parseTurtle(nquads, baseIRI, 'application/n-quads');
|
|
163
198
|
}
|
|
164
199
|
async function parseRdfXml(text, baseIRI) {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
200
|
+
const store = new N3__namespace.Store();
|
|
201
|
+
return new Promise((resolve, reject) => {
|
|
202
|
+
const parser = new rdfxmlStreamingParser.RdfXmlParser({ baseIRI });
|
|
203
|
+
parser.on('data', (quad) => store.addQuad(quad));
|
|
204
|
+
parser.on('error', reject);
|
|
205
|
+
parser.on('end', () => resolve(store));
|
|
206
|
+
parser.write(text);
|
|
207
|
+
parser.end();
|
|
169
208
|
});
|
|
170
|
-
parser.on('data', quad => store.addQuad(quad));
|
|
171
|
-
parser.on('error', reject);
|
|
172
|
-
parser.on('end', () => resolve(store));
|
|
173
|
-
parser.write(text);
|
|
174
|
-
parser.end();
|
|
175
|
-
});
|
|
176
209
|
}
|
|
177
|
-
const toArray = val => !val ? [] : Array.isArray(val) ? val : [val];
|
|
178
|
-
const getSparqlQuery = uri => `DESCRIBE <${uri}>`;
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
210
|
+
const toArray = (val) => !val ? [] : Array.isArray(val) ? val : [val];
|
|
211
|
+
const getSparqlQuery = (uri) => `DESCRIBE <${uri}>`;
|
|
212
|
+
const fetchAndParse = async (fetchFn, baseIRI) => {
|
|
213
|
+
var _a;
|
|
214
|
+
let response;
|
|
215
|
+
try {
|
|
216
|
+
response = await fetchFn();
|
|
217
|
+
if (!response.ok) {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (_b) {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
const contentType = ((_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.split(';')[0].trim()) || 'text/turtle';
|
|
225
|
+
const text = await response.text();
|
|
226
|
+
try {
|
|
227
|
+
if (N3_CONTENT_TYPES.has(contentType)) {
|
|
228
|
+
return parseTurtle(text, baseIRI, contentType);
|
|
229
|
+
}
|
|
230
|
+
if (contentType === 'application/ld+json') {
|
|
231
|
+
return parseJsonLd(text, baseIRI);
|
|
232
|
+
}
|
|
233
|
+
if (contentType === 'application/rdf+xml') {
|
|
234
|
+
return parseRdfXml(text, baseIRI);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch (_c) {
|
|
200
238
|
}
|
|
201
|
-
} catch (_c) {
|
|
202
239
|
return null;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
240
|
+
};
|
|
241
|
+
const fetchAndParseDocument = (docUrl, fetchFn) => {
|
|
242
|
+
if (!(docUrl in requestCache)) {
|
|
243
|
+
requestCache[docUrl] = fetchAndParse(fetchFn, docUrl);
|
|
244
|
+
}
|
|
245
|
+
return requestCache[docUrl];
|
|
246
|
+
};
|
|
247
|
+
const findResourceInStore = async (storePromise, uri, options) => {
|
|
248
|
+
const store = await storePromise;
|
|
249
|
+
if (!store) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
const label = findInStore(store, uri, options.labelPredicates);
|
|
253
|
+
if (!label) {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
return { uri, label, description: findInStore(store, uri, options.descriptionPredicates) };
|
|
211
257
|
};
|
|
212
258
|
const actualFetchResource = async (uri, options) => {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
headers: {
|
|
216
|
-
|
|
259
|
+
const docUrl = uri.includes('#') ? uri.split('#')[0] : uri;
|
|
260
|
+
// 1. Direct (cached by document URL so hash siblings share one request)
|
|
261
|
+
let result = await findResourceInStore(fetchAndParseDocument(docUrl, () => fetch(docUrl, { headers: { 'Accept': ACCEPT_HEADER } })), uri, options);
|
|
262
|
+
// 2. Rainbow proxies (in order) — not supported for hash URIs
|
|
263
|
+
const isHashUri = uri.includes('#');
|
|
264
|
+
for (const instance of [...toArray(options.fallbackRainbowInstances), ...toArray(options.fallbackRainbowInstance)]) {
|
|
265
|
+
if (result || isHashUri) {
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
const rainbowURL = new URL(instance);
|
|
269
|
+
rainbowURL.searchParams.set('uri', uri);
|
|
270
|
+
const rainbowUrlStr = rainbowURL.toString();
|
|
271
|
+
result = await findResourceInStore(fetchAndParseDocument(rainbowUrlStr, () => fetch(rainbowUrlStr, { headers: { 'Accept': ACCEPT_HEADER } })), uri, options);
|
|
217
272
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
query: getSparqlQuery(uri)
|
|
235
|
-
});
|
|
236
|
-
result = await tryFetchAndParse(() => fetch(endpoint, {
|
|
237
|
-
method: 'POST',
|
|
238
|
-
headers: {
|
|
239
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
|
240
|
-
'Accept': 'text/turtle, application/n-triples'
|
|
241
|
-
},
|
|
242
|
-
body: formBody.toString()
|
|
243
|
-
}), uri, options);
|
|
244
|
-
}
|
|
245
|
-
if (!result) {
|
|
246
|
-
throw new Error(`No label data found for <${uri}>`);
|
|
247
|
-
}
|
|
248
|
-
return result;
|
|
273
|
+
// 3. SPARQL endpoints (in order) — each DESCRIBE is unique per URI, no request cache
|
|
274
|
+
for (const endpoint of [...toArray(options.fallbackSparqlEndpoints), ...toArray(options.fallbackSparqlEndpoint)]) {
|
|
275
|
+
if (result) {
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
const formBody = new URLSearchParams({ query: getSparqlQuery(uri) });
|
|
279
|
+
result = await findResourceInStore(fetchAndParse(() => fetch(endpoint, {
|
|
280
|
+
method: 'POST',
|
|
281
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'text/turtle, application/n-triples' },
|
|
282
|
+
body: formBody.toString(),
|
|
283
|
+
}), uri), uri, options);
|
|
284
|
+
}
|
|
285
|
+
if (!result) {
|
|
286
|
+
throw new Error(`No label data found for <${uri}>`);
|
|
287
|
+
}
|
|
288
|
+
return result;
|
|
249
289
|
};
|
|
250
290
|
async function fetchResource(uri, options = {}) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
fetchResourceCache[uri] = actualFetchResource(uri, mergedOptions);
|
|
257
|
-
}
|
|
258
|
-
return fetchResourceCache[uri];
|
|
291
|
+
const mergedOptions = { ...defaultFetchResourceOptions, ...options };
|
|
292
|
+
if (!(uri in fetchResourceCache)) {
|
|
293
|
+
fetchResourceCache[uri] = actualFetchResource(uri, mergedOptions);
|
|
294
|
+
}
|
|
295
|
+
return fetchResourceCache[uri];
|
|
259
296
|
}
|
|
260
297
|
async function loadFeature(url) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
298
|
+
const response = await fetch(url, {
|
|
299
|
+
headers: {
|
|
300
|
+
'Accept': 'application/ld+json, application/json;q=0.9, */*;q=0.1',
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
if (!response.ok) {
|
|
304
|
+
throw new Error(`Could not load feature ${url}: ${response.status} - ${response.statusText}`);
|
|
264
305
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
return {
|
|
272
|
-
feature,
|
|
273
|
-
context
|
|
274
|
-
};
|
|
306
|
+
const feature = await response.json();
|
|
307
|
+
const context = await loadContext(feature);
|
|
308
|
+
return {
|
|
309
|
+
feature,
|
|
310
|
+
context,
|
|
311
|
+
};
|
|
275
312
|
}
|
|
276
313
|
|
|
277
314
|
var resource = /*#__PURE__*/Object.freeze({
|
|
@@ -282,238 +319,236 @@ var resource = /*#__PURE__*/Object.freeze({
|
|
|
282
319
|
});
|
|
283
320
|
|
|
284
321
|
const defaultAugmentOptions = {
|
|
285
|
-
|
|
286
|
-
|
|
322
|
+
replaceElements: true,
|
|
323
|
+
...defaultFetchResourceOptions,
|
|
287
324
|
};
|
|
288
325
|
function createPropertiesTable(feature, container, options = {
|
|
289
|
-
|
|
326
|
+
propertiesField: 'properties',
|
|
290
327
|
}) {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
} else if (value === null || typeof value === 'undefined' || typeof value !== 'object') {
|
|
299
|
-
const span = document.createElement('span');
|
|
300
|
-
span.classList.add('literal-value');
|
|
301
|
-
span.textContent = '' + value;
|
|
302
|
-
parent.appendChild(span);
|
|
303
|
-
return span;
|
|
304
|
-
} else {
|
|
305
|
-
const table = document.createElement('table');
|
|
306
|
-
table.classList.add('object-table');
|
|
307
|
-
if (addHeaders) {
|
|
308
|
-
table.innerHTML = '<thead><tr><th>Property</th><th>Value</th></tr></thead>';
|
|
309
|
-
}
|
|
310
|
-
const tbody = document.createElement('tbody');
|
|
311
|
-
Object.entries(value).forEach(([k, v]) => {
|
|
312
|
-
const row = document.createElement('tr');
|
|
313
|
-
const keyCell = document.createElement('td');
|
|
314
|
-
keyCell.classList.add('object-property');
|
|
315
|
-
keyCell.setAttribute('data-property', k);
|
|
316
|
-
keyCell.textContent = k;
|
|
317
|
-
row.appendChild(keyCell);
|
|
318
|
-
const valueCell = document.createElement('td');
|
|
319
|
-
valueCell.classList.add('object-value');
|
|
320
|
-
createLevel(valueCell, v);
|
|
321
|
-
row.appendChild(valueCell);
|
|
322
|
-
tbody.appendChild(row);
|
|
323
|
-
});
|
|
324
|
-
table.appendChild(tbody);
|
|
325
|
-
parent.appendChild(table);
|
|
326
|
-
return table;
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
if (options.propertiesField) {
|
|
330
|
-
createLevel(container, feature[options.propertiesField], true);
|
|
331
|
-
} else {
|
|
332
|
-
createLevel(container, feature, true);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
async function augment(rootElem, context, options = {}) {
|
|
336
|
-
const mergedOptions = {
|
|
337
|
-
...defaultAugmentOptions,
|
|
338
|
-
...options
|
|
339
|
-
};
|
|
340
|
-
const resolveTerm = (term, contextStack, useVocab = true, useBase = false) => {
|
|
341
|
-
if (term.indexOf('://') !== -1) {
|
|
342
|
-
return {
|
|
343
|
-
'@id': term
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
let closestVocab = null;
|
|
347
|
-
let closestBase = null;
|
|
348
|
-
for (let i = contextStack.length - 1; i >= 0; i--) {
|
|
349
|
-
if (term in contextStack[i]) {
|
|
350
|
-
let resolvedTerm = contextStack[i][term];
|
|
351
|
-
let resolvedId;
|
|
352
|
-
if (resolvedTerm === null || typeof resolvedTerm === 'undefined' || typeof resolvedTerm === 'boolean' || Array.isArray(resolvedTerm)) {
|
|
353
|
-
continue;
|
|
328
|
+
const createLevel = (parent, value, addHeaders = false) => {
|
|
329
|
+
if (Array.isArray(value)) {
|
|
330
|
+
for (const entry of value) {
|
|
331
|
+
const newElem = createLevel(parent, entry);
|
|
332
|
+
newElem.classList.add('array-entry');
|
|
333
|
+
}
|
|
334
|
+
return parent;
|
|
354
335
|
}
|
|
355
|
-
if (typeof
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
resolvedId = resolvedTerm;
|
|
362
|
-
resolvedTerm = {
|
|
363
|
-
'@id': resolvedTerm
|
|
364
|
-
};
|
|
365
|
-
} else if (typeof resolvedTerm === 'object' && '@id' in resolvedTerm && typeof resolvedTerm['@id'] === 'string') {
|
|
366
|
-
resolvedId = resolvedTerm['@id'];
|
|
367
|
-
} else {
|
|
368
|
-
continue;
|
|
336
|
+
else if (value === null || typeof value === 'undefined' || typeof value !== 'object') {
|
|
337
|
+
const span = document.createElement('span');
|
|
338
|
+
span.classList.add('literal-value');
|
|
339
|
+
span.textContent = '' + value;
|
|
340
|
+
parent.appendChild(span);
|
|
341
|
+
return span;
|
|
369
342
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
343
|
+
else {
|
|
344
|
+
const table = document.createElement('table');
|
|
345
|
+
table.classList.add('object-table');
|
|
346
|
+
if (addHeaders) {
|
|
347
|
+
table.innerHTML = '<thead><tr><th>Property</th><th>Value</th></tr></thead>';
|
|
348
|
+
}
|
|
349
|
+
const tbody = document.createElement('tbody');
|
|
350
|
+
Object.entries(value).forEach(([k, v]) => {
|
|
351
|
+
const row = document.createElement('tr');
|
|
352
|
+
const keyCell = document.createElement('td');
|
|
353
|
+
keyCell.classList.add('object-property');
|
|
354
|
+
keyCell.setAttribute('data-property', k);
|
|
355
|
+
keyCell.textContent = k;
|
|
356
|
+
row.appendChild(keyCell);
|
|
357
|
+
const valueCell = document.createElement('td');
|
|
358
|
+
valueCell.classList.add('object-value');
|
|
359
|
+
createLevel(valueCell, v);
|
|
360
|
+
row.appendChild(valueCell);
|
|
361
|
+
tbody.appendChild(row);
|
|
362
|
+
});
|
|
363
|
+
table.appendChild(tbody);
|
|
364
|
+
parent.appendChild(table);
|
|
365
|
+
return table;
|
|
384
366
|
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
}
|
|
367
|
+
};
|
|
368
|
+
const wrapper = document.createElement('div');
|
|
369
|
+
wrapper.classList.add('object-properties');
|
|
370
|
+
container.appendChild(wrapper);
|
|
371
|
+
if (options.propertiesField) {
|
|
372
|
+
createLevel(wrapper, feature[options.propertiesField], true);
|
|
392
373
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
return {
|
|
396
|
-
'@id': `${closestVocab}${term}`
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
if (useBase && closestBase) {
|
|
400
|
-
return {
|
|
401
|
-
'@id': `${closestBase}${term}`
|
|
402
|
-
};
|
|
403
|
-
}
|
|
374
|
+
else {
|
|
375
|
+
createLevel(wrapper, feature, true);
|
|
404
376
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
if (node !== elem && nodeElem.classList.contains('object-value')) {
|
|
412
|
-
return NodeFilter.FILTER_REJECT;
|
|
413
|
-
}
|
|
414
|
-
if (nodeElem.classList.contains('object-property')) {
|
|
415
|
-
return NodeFilter.FILTER_ACCEPT;
|
|
377
|
+
}
|
|
378
|
+
async function augment(rootElem, context, options = {}) {
|
|
379
|
+
const mergedOptions = { ...defaultAugmentOptions, ...options };
|
|
380
|
+
const resolveTerm = (term, contextStack, useVocab = true, useBase = false) => {
|
|
381
|
+
if (term.indexOf('://') !== -1) {
|
|
382
|
+
return { '@id': term };
|
|
416
383
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
384
|
+
let closestVocab = null;
|
|
385
|
+
let closestBase = null;
|
|
386
|
+
for (let i = contextStack.length - 1; i >= 0; i--) {
|
|
387
|
+
if (term in contextStack[i]) {
|
|
388
|
+
let resolvedTerm = contextStack[i][term];
|
|
389
|
+
let resolvedId;
|
|
390
|
+
if (resolvedTerm === null || typeof resolvedTerm === 'undefined' || typeof resolvedTerm === 'boolean'
|
|
391
|
+
|| Array.isArray(resolvedTerm)) {
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
if (typeof resolvedTerm === 'string') {
|
|
395
|
+
if (resolvedTerm === '@type') {
|
|
396
|
+
return { '@id': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' };
|
|
397
|
+
}
|
|
398
|
+
resolvedId = resolvedTerm;
|
|
399
|
+
resolvedTerm = { '@id': resolvedTerm };
|
|
400
|
+
}
|
|
401
|
+
else if (typeof resolvedTerm === 'object' && '@id' in resolvedTerm && typeof resolvedTerm['@id'] === 'string') {
|
|
402
|
+
resolvedId = resolvedTerm['@id'];
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
const idx = resolvedId.indexOf(':');
|
|
408
|
+
if (idx > -1) {
|
|
409
|
+
const prefix = resolvedId.substring(0, idx);
|
|
410
|
+
const localPart = resolvedId.substring(idx + 1);
|
|
411
|
+
if (localPart.startsWith('//')) {
|
|
412
|
+
// Full URI -> return
|
|
413
|
+
return resolvedTerm;
|
|
414
|
+
}
|
|
415
|
+
const resolvedPrefix = resolveTerm(prefix, contextStack);
|
|
416
|
+
if (resolvedPrefix !== null && '@id' in resolvedPrefix && typeof resolvedPrefix['@id'] === 'string') {
|
|
417
|
+
// Prefix found and resolved
|
|
418
|
+
resolvedTerm['@id'] = `${resolvedPrefix['@id']}${localPart}`;
|
|
419
|
+
}
|
|
420
|
+
return resolvedTerm;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
if (closestVocab === null && contextStack[i]['@vocab']) {
|
|
424
|
+
closestVocab = contextStack[i]['@vocab'];
|
|
425
|
+
}
|
|
426
|
+
if (closestBase === null && contextStack[i]['@base']) {
|
|
427
|
+
closestBase = contextStack[i]['@base'];
|
|
428
|
+
}
|
|
434
429
|
}
|
|
435
|
-
if (
|
|
436
|
-
|
|
437
|
-
|
|
430
|
+
if (term.indexOf(':') === -1) {
|
|
431
|
+
if (useVocab && closestVocab) {
|
|
432
|
+
return { '@id': `${closestVocab}${term}` };
|
|
433
|
+
}
|
|
434
|
+
if (useBase && closestBase) {
|
|
435
|
+
return { '@id': `${closestBase}${term}` };
|
|
436
|
+
}
|
|
438
437
|
}
|
|
439
|
-
return
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
438
|
+
return null;
|
|
439
|
+
};
|
|
440
|
+
const findPropertyChildren = (elem) => {
|
|
441
|
+
const walker = document.createTreeWalker(elem, NodeFilter.SHOW_ELEMENT, {
|
|
442
|
+
acceptNode(node) {
|
|
443
|
+
const nodeElem = node;
|
|
444
|
+
if (node !== elem && nodeElem.classList.contains('object-value')) {
|
|
445
|
+
return NodeFilter.FILTER_REJECT;
|
|
446
|
+
}
|
|
447
|
+
if (nodeElem.classList.contains('object-property')) {
|
|
448
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
449
|
+
}
|
|
450
|
+
return NodeFilter.FILTER_SKIP;
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
const result = [];
|
|
454
|
+
let cur;
|
|
455
|
+
while ((cur = walker.nextNode())) {
|
|
456
|
+
result.push(cur);
|
|
454
457
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
458
|
+
return result;
|
|
459
|
+
};
|
|
460
|
+
const findLiteralChildren = (elem) => {
|
|
461
|
+
const result = [];
|
|
462
|
+
const walker = document.createTreeWalker(elem, NodeFilter.SHOW_ELEMENT, {
|
|
463
|
+
acceptNode(node) {
|
|
464
|
+
const nodeElem = node;
|
|
465
|
+
if (nodeElem.classList.contains('object-property') || nodeElem.classList.contains('object-value')) {
|
|
466
|
+
return NodeFilter.FILTER_REJECT;
|
|
467
|
+
}
|
|
468
|
+
if (nodeElem.classList.contains('literal-value')) {
|
|
469
|
+
result.push(nodeElem);
|
|
470
|
+
return NodeFilter.FILTER_REJECT;
|
|
471
|
+
}
|
|
472
|
+
return NodeFilter.FILTER_SKIP;
|
|
473
|
+
},
|
|
474
|
+
});
|
|
475
|
+
while (walker.nextNode()) {
|
|
460
476
|
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
477
|
+
return result;
|
|
478
|
+
};
|
|
479
|
+
const updateElement = (elem, resourceUri, replaceElements = true) => {
|
|
480
|
+
elem.setAttribute('data-uri', resourceUri);
|
|
481
|
+
elem.classList.add('resource-loading');
|
|
482
|
+
fetchResource(resourceUri, mergedOptions)
|
|
483
|
+
.then(resourceData => {
|
|
484
|
+
let elemToUpdate = elem.querySelector('.resource-link') || elem;
|
|
485
|
+
if (resourceData.label) {
|
|
486
|
+
elem.setAttribute('data-label', resourceData.label);
|
|
487
|
+
if (mergedOptions.replaceElements) {
|
|
488
|
+
elemToUpdate.textContent = resourceData.label;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (resourceData.description) {
|
|
492
|
+
elem.setAttribute('data-description', resourceData.description);
|
|
493
|
+
if (mergedOptions.replaceElements) {
|
|
494
|
+
elemToUpdate.title = resourceData.description;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
elem.classList.add('resource-resolved');
|
|
498
|
+
})
|
|
499
|
+
.catch(e => {
|
|
500
|
+
console.error(`Error resolving URI ${resourceUri}: ${e}`, { cause: e });
|
|
501
|
+
elem.classList.add('resource-error');
|
|
502
|
+
})
|
|
503
|
+
.finally(() => {
|
|
504
|
+
elem.classList.remove('resource-loading');
|
|
505
|
+
});
|
|
506
|
+
if (replaceElements) {
|
|
507
|
+
const link = document.createElement("a");
|
|
508
|
+
link.href = resourceUri;
|
|
509
|
+
link.target = '_blank';
|
|
510
|
+
link.classList.add('resource-link');
|
|
511
|
+
while (elem.firstChild) {
|
|
512
|
+
link.appendChild(elem.firstChild);
|
|
513
|
+
}
|
|
514
|
+
elem.appendChild(link);
|
|
499
515
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
516
|
+
};
|
|
517
|
+
const augmentInner = (elem, contextStack) => {
|
|
518
|
+
var _a;
|
|
519
|
+
const propElems = findPropertyChildren(elem);
|
|
520
|
+
for (const propElem of propElems) {
|
|
521
|
+
let propertyName = null;
|
|
522
|
+
propertyName = propElem.getAttribute('data-property');
|
|
523
|
+
if (!propertyName) {
|
|
524
|
+
propertyName = propElem.textContent.trim();
|
|
525
|
+
}
|
|
526
|
+
const resolvedProperty = resolveTerm(propertyName, contextStack);
|
|
527
|
+
let newContextStack = contextStack;
|
|
528
|
+
const valueElem = (_a = propElem.parentElement) === null || _a === void 0 ? void 0 : _a.querySelector('.object-value');
|
|
529
|
+
if (resolvedProperty && '@id' in resolvedProperty && typeof resolvedProperty['@id'] === 'string') {
|
|
530
|
+
const propertyUri = resolvedProperty['@id'];
|
|
531
|
+
updateElement(propElem, propertyUri, mergedOptions.replaceElements);
|
|
532
|
+
if ('@context' in resolvedProperty) {
|
|
533
|
+
newContextStack = [...contextStack, resolvedProperty['@context']];
|
|
534
|
+
}
|
|
535
|
+
if (resolvedProperty['@type'] === '@id' && valueElem) {
|
|
536
|
+
const literalElems = findLiteralChildren(valueElem);
|
|
537
|
+
literalElems.forEach(literalElem => {
|
|
538
|
+
const resolvedLiteral = resolveTerm(literalElem.textContent.trim(), newContextStack, false, true);
|
|
539
|
+
if (resolvedLiteral && '@id' in resolvedLiteral && typeof resolvedLiteral['@id'] === 'string') {
|
|
540
|
+
const resourceUri = resolvedLiteral['@id'];
|
|
541
|
+
updateElement(literalElem, resourceUri, mergedOptions.replaceElements);
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
if (valueElem) {
|
|
547
|
+
augmentInner(valueElem, newContextStack);
|
|
507
548
|
}
|
|
508
|
-
});
|
|
509
549
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
augmentInner(valueElem, newContextStack);
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
};
|
|
516
|
-
augmentInner(rootElem, [context]);
|
|
550
|
+
};
|
|
551
|
+
augmentInner(rootElem, [context]);
|
|
517
552
|
}
|
|
518
553
|
|
|
519
554
|
var augment$1 = /*#__PURE__*/Object.freeze({
|
|
@@ -523,9 +558,9 @@ var augment$1 = /*#__PURE__*/Object.freeze({
|
|
|
523
558
|
});
|
|
524
559
|
|
|
525
560
|
var index = {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
561
|
+
...resource,
|
|
562
|
+
...jsonld,
|
|
563
|
+
...augment$1,
|
|
529
564
|
};
|
|
530
565
|
|
|
531
566
|
exports.augment = augment;
|