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