@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/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
- const response = await fetch(url, {
31
- headers: {
32
- 'Accept': 'application/json'
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
- const mergePair = (a, b) => {
39
- if (!a || !Object.keys(a).length) {
40
- return b;
41
- }
42
- const result = {
43
- ...a
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
- for (const [k, v] of Object.entries(b)) {
46
- result[k] = v;
44
+ if (!definitions.length) {
45
+ return {};
47
46
  }
48
- return result;
49
- };
50
- if (!definitions.length) {
51
- return {};
52
- }
53
- if (definitions.length === 1) {
54
- return definitions[0];
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
- const loadedUrls = new Map();
64
- const walk = async (definition, refChain) => {
65
- for (const [key, value] of Object.entries(definition)) {
66
- if (key === '@context') {
67
- // @ts-ignore
68
- definition[key] = await load(value, refChain);
69
- } else if (typeof value === 'object' && value !== null) {
70
- await walk(value, refChain);
71
- }
72
- }
73
- };
74
- const load = async (context, refChain) => {
75
- if (context === null || typeof context === 'undefined') {
76
- return {};
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
- if (Array.isArray(context)) {
79
- // fetch and merge
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 = [SKOS('prefLabel'), DCT('title'), DC('title'), SDO('name'), FOAF('name'), RDFS('label')];
121
- const descriptionPredicates = [SKOS('definition'), DCT('description'), DC('description'), RDFS('comment')];
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
- labelPredicates,
125
- descriptionPredicates
135
+ labelPredicates,
136
+ descriptionPredicates,
126
137
  };
127
138
  const fetchResourceCache = {};
128
- const N3_CONTENT_TYPES = new Set(['text/turtle', 'text/n3', 'application/n-triples', 'application/n-quads', 'application/trig', 'text/anot+turtle']);
129
- const ACCEPT_HEADER = ['text/turtle', 'application/n-triples', 'application/n-quads', 'application/trig', 'application/ld+json', 'application/rdf+xml'].join(', ');
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
- var _a;
132
- const subj = N3__namespace.DataFactory.namedNode(subjectUri);
133
- for (const predUri of predicates) {
134
- const quads = store.getQuads(subj, N3__namespace.DataFactory.namedNode(predUri), null, null).filter(q => q.object.termType === 'Literal');
135
- if (!quads.length) continue;
136
- const en = quads.find(q => q.object.language === 'en');
137
- const noLang = quads.find(q => !q.object.language);
138
- return ((_a = en !== null && en !== void 0 ? en : noLang) !== null && _a !== void 0 ? _a : quads[0]).object.value;
139
- }
140
- return null;
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
- const store = new N3__namespace.Store();
144
- const format = contentType === 'text/anot+turtle' ? 'text/turtle' : contentType;
145
- const parser = new N3__namespace.Parser({
146
- baseIRI,
147
- format
148
- });
149
- return new Promise((resolve, reject) => {
150
- parser.parse(text, (err, quad) => {
151
- if (err) return reject(err);
152
- if (quad) store.addQuad(quad);else resolve(store);
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
- const doc = JSON.parse(text);
158
- const nquads = await jsonldLib__namespace.toRDF(doc, {
159
- format: 'application/n-quads',
160
- base: baseIRI
161
- });
162
- return parseTurtle(nquads, baseIRI, 'application/n-quads');
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
- const store = new N3__namespace.Store();
166
- return new Promise((resolve, reject) => {
167
- const parser = new rdfxmlStreamingParser.RdfXmlParser({
168
- baseIRI
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 tryFetchAndParse = async (fetchFn, uri, options) => {
180
- var _a;
181
- let response;
182
- try {
183
- response = await fetchFn();
184
- if (!response.ok) return null;
185
- } catch (_b) {
186
- return null;
187
- }
188
- const contentType = ((_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.split(';')[0].trim()) || 'text/turtle';
189
- const text = await response.text();
190
- let store;
191
- try {
192
- if (N3_CONTENT_TYPES.has(contentType)) {
193
- store = await parseTurtle(text, uri, contentType);
194
- } else if (contentType === 'application/ld+json') {
195
- store = await parseJsonLd(text, uri);
196
- } else if (contentType === 'application/rdf+xml') {
197
- store = await parseRdfXml(text, uri);
198
- } else {
199
- return null;
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
- const label = findInStore(store, uri, options.labelPredicates);
205
- if (!label) return null;
206
- return {
207
- uri,
208
- label,
209
- description: findInStore(store, uri, options.descriptionPredicates)
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
- // 1. Direct
214
- let result = await tryFetchAndParse(() => fetch(uri, {
215
- headers: {
216
- 'Accept': ACCEPT_HEADER
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
- }), uri, options);
219
- // 2. Rainbow proxies (in order)
220
- for (const instance of [...toArray(options.fallbackRainbowInstances), ...toArray(options.fallbackRainbowInstance)]) {
221
- if (result) break;
222
- const rainbowURL = new URL(instance);
223
- rainbowURL.searchParams.set('uri', uri);
224
- result = await tryFetchAndParse(() => fetch(rainbowURL.toString(), {
225
- headers: {
226
- 'Accept': ACCEPT_HEADER
227
- }
228
- }), uri, options);
229
- }
230
- // 3. SPARQL endpoints (in order)
231
- for (const endpoint of [...toArray(options.fallbackSparqlEndpoints), ...toArray(options.fallbackSparqlEndpoint)]) {
232
- if (result) break;
233
- const formBody = new URLSearchParams({
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
- const mergedOptions = {
252
- ...defaultFetchResourceOptions,
253
- ...options
254
- };
255
- if (!(uri in fetchResourceCache)) {
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
- const response = await fetch(url, {
262
- headers: {
263
- 'Accept': 'application/ld+json, application/json;q=0.9, */*;q=0.1'
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
- if (!response.ok) {
267
- throw new Error(`Could not load feature ${url}: ${response.status} - ${response.statusText}`);
268
- }
269
- const feature = await response.json();
270
- const context = await loadContext(feature);
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
- replaceElements: true,
286
- ...defaultFetchResourceOptions
322
+ replaceElements: true,
323
+ ...defaultFetchResourceOptions,
287
324
  };
288
325
  function createPropertiesTable(feature, container, options = {
289
- propertiesField: 'properties'
326
+ propertiesField: 'properties',
290
327
  }) {
291
- const createLevel = (parent, value, addHeaders = false) => {
292
- if (Array.isArray(value)) {
293
- for (const entry of value) {
294
- const newElem = createLevel(parent, entry);
295
- newElem.classList.add('array-entry');
296
- }
297
- return parent;
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 resolvedTerm === 'string') {
356
- if (resolvedTerm === '@type') {
357
- return {
358
- '@id': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'
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
- const idx = resolvedId.indexOf(':');
371
- if (idx > -1) {
372
- const prefix = resolvedId.substring(0, idx);
373
- const localPart = resolvedId.substring(idx + 1);
374
- if (localPart.startsWith('//')) {
375
- // Full URI -> return
376
- return resolvedTerm;
377
- }
378
- const resolvedPrefix = resolveTerm(prefix, contextStack);
379
- if (resolvedPrefix !== null && '@id' in resolvedPrefix && typeof resolvedPrefix['@id'] === 'string') {
380
- // Prefix found and resolved
381
- resolvedTerm['@id'] = `${resolvedPrefix['@id']}${localPart}`;
382
- }
383
- return resolvedTerm;
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
- if (closestVocab === null && contextStack[i]['@vocab']) {
387
- closestVocab = contextStack[i]['@vocab'];
388
- }
389
- if (closestBase === null && contextStack[i]['@base']) {
390
- closestBase = contextStack[i]['@base'];
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
- if (term.indexOf(':') === -1) {
394
- if (useVocab && closestVocab) {
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
- return null;
406
- };
407
- const findPropertyChildren = elem => {
408
- const walker = document.createTreeWalker(elem, NodeFilter.SHOW_ELEMENT, {
409
- acceptNode(node) {
410
- const nodeElem = node;
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
- return NodeFilter.FILTER_SKIP;
418
- }
419
- });
420
- const result = [];
421
- let cur;
422
- while (cur = walker.nextNode()) {
423
- result.push(cur);
424
- }
425
- return result;
426
- };
427
- const findLiteralChildren = elem => {
428
- const result = [];
429
- const walker = document.createTreeWalker(elem, NodeFilter.SHOW_ELEMENT, {
430
- acceptNode(node) {
431
- const nodeElem = node;
432
- if (nodeElem.classList.contains('object-property') || nodeElem.classList.contains('object-value')) {
433
- return NodeFilter.FILTER_REJECT;
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 (nodeElem.classList.contains('literal-value')) {
436
- result.push(nodeElem);
437
- return NodeFilter.FILTER_REJECT;
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 NodeFilter.FILTER_SKIP;
440
- }
441
- });
442
- while (walker.nextNode()) {}
443
- return result;
444
- };
445
- const updateElement = (elem, resourceUri, replaceElements = true) => {
446
- elem.setAttribute('data-uri', resourceUri);
447
- elem.classList.add('resource-loading');
448
- fetchResource(resourceUri, mergedOptions).then(resourceData => {
449
- let elemToUpdate = elem.querySelector('.resource-link') || elem;
450
- if (resourceData.label) {
451
- elem.setAttribute('data-label', resourceData.label);
452
- if (mergedOptions.replaceElements) {
453
- elemToUpdate.textContent = resourceData.label;
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
- if (resourceData.description) {
457
- elem.setAttribute('data-description', resourceData.description);
458
- if (mergedOptions.replaceElements) {
459
- elemToUpdate.title = resourceData.description;
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
- elem.classList.add('resource-resolved');
463
- }).catch(e => {
464
- console.error(`Error resolving URI ${resourceUri}: ${e}`, {
465
- cause: e
466
- });
467
- elem.classList.add('resource-error');
468
- }).finally(() => {
469
- elem.classList.remove('resource-loading');
470
- });
471
- if (replaceElements) {
472
- const link = document.createElement("a");
473
- link.href = resourceUri;
474
- link.target = '_blank';
475
- link.classList.add('resource-link');
476
- while (elem.firstChild) {
477
- link.appendChild(elem.firstChild);
478
- }
479
- elem.appendChild(link);
480
- }
481
- };
482
- const augmentInner = (elem, contextStack) => {
483
- var _a;
484
- const propElems = findPropertyChildren(elem);
485
- for (const propElem of propElems) {
486
- let propertyName = null;
487
- propertyName = propElem.getAttribute('data-property');
488
- if (!propertyName) {
489
- propertyName = propElem.textContent.trim();
490
- }
491
- const resolvedProperty = resolveTerm(propertyName, contextStack);
492
- let newContextStack = contextStack;
493
- const valueElem = (_a = propElem.parentElement) === null || _a === void 0 ? void 0 : _a.querySelector('.object-value');
494
- if (resolvedProperty && '@id' in resolvedProperty && typeof resolvedProperty['@id'] === 'string') {
495
- const propertyUri = resolvedProperty['@id'];
496
- updateElement(propElem, propertyUri, mergedOptions.replaceElements);
497
- if ('@context' in resolvedProperty) {
498
- newContextStack = [...contextStack, resolvedProperty['@context']];
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
- if (resolvedProperty['@type'] === '@id' && valueElem) {
501
- const literalElems = findLiteralChildren(valueElem);
502
- literalElems.forEach(literalElem => {
503
- const resolvedLiteral = resolveTerm(literalElem.textContent.trim(), newContextStack, false, true);
504
- if (resolvedLiteral && '@id' in resolvedLiteral && typeof resolvedLiteral['@id'] === 'string') {
505
- const resourceUri = resolvedLiteral['@id'];
506
- updateElement(literalElem, resourceUri, mergedOptions.replaceElements);
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
- if (valueElem) {
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
- ...resource,
527
- ...jsonld,
528
- ...augment$1
561
+ ...resource,
562
+ ...jsonld,
563
+ ...augment$1,
529
564
  };
530
565
 
531
566
  exports.augment = augment;