@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/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,410 +109,472 @@ 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(', ');
130
- 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;
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(', ');
156
+ function getUserLanguages() {
157
+ var _a;
158
+ if (typeof navigator !== 'undefined' && ((_a = navigator.languages) === null || _a === void 0 ? void 0 : _a.length)) {
159
+ return Array.from(navigator.languages);
160
+ }
161
+ try {
162
+ return [Intl.DateTimeFormat().resolvedOptions().locale];
163
+ }
164
+ catch (_b) {
165
+ return [];
166
+ }
167
+ }
168
+ function findInStore(store, subjectUri, predicates, userLangs = getUserLanguages()) {
169
+ const subj = N3__namespace.DataFactory.namedNode(subjectUri);
170
+ for (const predUri of predicates) {
171
+ const quads = store
172
+ .getQuads(subj, N3__namespace.DataFactory.namedNode(predUri), null, null)
173
+ .filter(q => q.object.termType === 'Literal');
174
+ if (!quads.length) {
175
+ continue;
176
+ }
177
+ for (const lang of userLangs) {
178
+ const base = lang.split('-')[0].toLowerCase();
179
+ const match = quads.find(q => {
180
+ var _a;
181
+ const qLang = (_a = q.object.language) === null || _a === void 0 ? void 0 : _a.toLowerCase();
182
+ return qLang === lang.toLowerCase() || (qLang === null || qLang === void 0 ? void 0 : qLang.split('-')[0]) === base;
183
+ });
184
+ if (match) {
185
+ return match.object.value;
186
+ }
187
+ }
188
+ const noLang = quads.find(q => !q.object.language);
189
+ if (noLang) {
190
+ return noLang.object.value;
191
+ }
192
+ const en = quads.find(q => { var _a; return ((_a = q.object.language) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'en'; });
193
+ return (en !== null && en !== void 0 ? en : quads[0]).object.value;
194
+ }
195
+ return null;
141
196
  }
142
197
  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);
198
+ const store = new N3__namespace.Store();
199
+ const format = contentType === 'text/anot+turtle' ? 'text/turtle' : contentType;
200
+ const parser = new N3__namespace.Parser({ baseIRI, format });
201
+ return new Promise((resolve, reject) => {
202
+ parser.parse(text, (err, quad) => {
203
+ if (err) {
204
+ return reject(err);
205
+ }
206
+ if (quad) {
207
+ store.addQuad(quad);
208
+ }
209
+ else {
210
+ resolve(store);
211
+ }
212
+ });
153
213
  });
154
- });
155
214
  }
156
215
  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');
216
+ const jsonldMod = await import('jsonld');
217
+ if (!jsonldMod) {
218
+ throw new Error('jsonld peer dependency is not available');
219
+ }
220
+ const doc = JSON.parse(text);
221
+ const nquads = await jsonldMod.toRDF(doc, { format: 'application/n-quads', base: baseIRI });
222
+ return parseTurtle(nquads, baseIRI, 'application/n-quads');
163
223
  }
164
224
  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
225
+ const store = new N3__namespace.Store();
226
+ return new Promise((resolve, reject) => {
227
+ const parser = new rdfxmlStreamingParser.RdfXmlParser({ baseIRI });
228
+ parser.on('data', (quad) => store.addQuad(quad));
229
+ parser.on('error', reject);
230
+ parser.on('end', () => resolve(store));
231
+ parser.write(text);
232
+ parser.end();
169
233
  });
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
234
  }
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;
235
+ const toArray = (val) => !val ? [] : Array.isArray(val) ? val : [val];
236
+ const getSparqlQuery = (uri) => `DESCRIBE <${uri}>`;
237
+ const fetchAndParse = async (fetchFn, baseIRI) => {
238
+ var _a;
239
+ let response;
240
+ try {
241
+ response = await fetchFn();
242
+ if (!response.ok) {
243
+ return null;
244
+ }
245
+ }
246
+ catch (_b) {
247
+ return null;
248
+ }
249
+ const contentType = ((_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.split(';')[0].trim()) || 'text/turtle';
250
+ const text = await response.text();
251
+ try {
252
+ if (N3_CONTENT_TYPES.has(contentType)) {
253
+ return parseTurtle(text, baseIRI, contentType);
254
+ }
255
+ if (contentType === 'application/ld+json') {
256
+ return parseJsonLd(text, baseIRI);
257
+ }
258
+ if (contentType === 'application/rdf+xml') {
259
+ return parseRdfXml(text, baseIRI);
260
+ }
261
+ }
262
+ catch (_c) {
200
263
  }
201
- } catch (_c) {
202
264
  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
- };
265
+ };
266
+ const fetchAndParseDocument = (docUrl, fetchFn) => {
267
+ if (!(docUrl in requestCache)) {
268
+ requestCache[docUrl] = fetchAndParse(fetchFn, docUrl);
269
+ }
270
+ return requestCache[docUrl];
271
+ };
272
+ const findResourceInStore = async (storePromise, uri, options) => {
273
+ const store = await storePromise;
274
+ if (!store) {
275
+ return null;
276
+ }
277
+ const label = findInStore(store, uri, options.labelPredicates);
278
+ if (!label) {
279
+ return null;
280
+ }
281
+ return { uri, label, description: findInStore(store, uri, options.descriptionPredicates) };
211
282
  };
212
283
  const actualFetchResource = async (uri, options) => {
213
- // 1. Direct
214
- let result = await tryFetchAndParse(() => fetch(uri, {
215
- headers: {
216
- 'Accept': ACCEPT_HEADER
284
+ const docUrl = uri.includes('#') ? uri.split('#')[0] : uri;
285
+ // 1. Direct (cached by document URL so hash siblings share one request)
286
+ let result = await findResourceInStore(fetchAndParseDocument(docUrl, () => fetch(docUrl, { headers: { 'Accept': ACCEPT_HEADER } })), uri, options);
287
+ // 2. Rainbow proxies (in order) — not supported for hash URIs
288
+ const isHashUri = uri.includes('#');
289
+ for (const instance of [...toArray(options.fallbackRainbowInstances), ...toArray(options.fallbackRainbowInstance)]) {
290
+ if (result || isHashUri) {
291
+ break;
292
+ }
293
+ const rainbowURL = new URL(instance);
294
+ rainbowURL.searchParams.set('uri', uri);
295
+ const rainbowUrlStr = rainbowURL.toString();
296
+ result = await findResourceInStore(fetchAndParseDocument(rainbowUrlStr, () => fetch(rainbowUrlStr, { headers: { 'Accept': ACCEPT_HEADER } })), uri, options);
217
297
  }
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;
298
+ // 3. SPARQL endpoints (in order) — each DESCRIBE is unique per URI, no request cache
299
+ for (const endpoint of [...toArray(options.fallbackSparqlEndpoints), ...toArray(options.fallbackSparqlEndpoint)]) {
300
+ if (result) {
301
+ break;
302
+ }
303
+ const formBody = new URLSearchParams({ query: getSparqlQuery(uri) });
304
+ result = await findResourceInStore(fetchAndParse(() => fetch(endpoint, {
305
+ method: 'POST',
306
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'text/turtle, application/n-triples' },
307
+ body: formBody.toString(),
308
+ }), uri), uri, options);
309
+ }
310
+ if (!result) {
311
+ throw new Error(`No label data found for <${uri}>`);
312
+ }
313
+ return result;
249
314
  };
250
315
  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];
316
+ const mergedOptions = { ...defaultFetchResourceOptions, ...options };
317
+ if (!(uri in fetchResourceCache)) {
318
+ fetchResourceCache[uri] = actualFetchResource(uri, mergedOptions);
319
+ }
320
+ return fetchResourceCache[uri];
259
321
  }
260
322
  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'
323
+ const response = await fetch(url, {
324
+ headers: {
325
+ 'Accept': 'application/ld+json, application/json;q=0.9, */*;q=0.1',
326
+ },
327
+ });
328
+ if (!response.ok) {
329
+ throw new Error(`Could not load feature ${url}: ${response.status} - ${response.statusText}`);
264
330
  }
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
- };
331
+ const feature = await response.json();
332
+ const context = await loadContext(feature);
333
+ return {
334
+ feature,
335
+ context,
336
+ };
275
337
  }
276
338
 
277
339
  var resource = /*#__PURE__*/Object.freeze({
278
340
  __proto__: null,
279
341
  defaultFetchResourceOptions: defaultFetchResourceOptions,
280
342
  fetchResource: fetchResource,
343
+ findInStore: findInStore,
281
344
  loadFeature: loadFeature
282
345
  });
283
346
 
284
347
  const defaultAugmentOptions = {
285
- replaceElements: true,
286
- ...defaultFetchResourceOptions
348
+ replaceElements: true,
349
+ ...defaultFetchResourceOptions,
287
350
  };
288
351
  function createPropertiesTable(feature, container, options = {
289
- propertiesField: 'properties'
352
+ propertiesField: 'properties',
290
353
  }) {
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;
354
+ const createLevel = (parent, value, addHeaders = false) => {
355
+ if (Array.isArray(value)) {
356
+ for (const entry of value) {
357
+ const newElem = createLevel(parent, entry);
358
+ newElem.classList.add('array-entry');
359
+ }
360
+ return parent;
354
361
  }
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;
362
+ else if (value === null || typeof value === 'undefined' || typeof value !== 'object') {
363
+ const span = document.createElement('span');
364
+ span.classList.add('literal-value');
365
+ span.textContent = '' + value;
366
+ parent.appendChild(span);
367
+ return span;
369
368
  }
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;
369
+ else {
370
+ const table = document.createElement('table');
371
+ table.classList.add('object-table');
372
+ if (addHeaders) {
373
+ table.innerHTML = '<thead><tr><th>Property</th><th>Value</th></tr></thead>';
374
+ }
375
+ const tbody = document.createElement('tbody');
376
+ Object.entries(value).forEach(([k, v]) => {
377
+ const row = document.createElement('tr');
378
+ const keyCell = document.createElement('td');
379
+ keyCell.classList.add('object-property');
380
+ keyCell.setAttribute('data-property', k);
381
+ keyCell.textContent = k;
382
+ row.appendChild(keyCell);
383
+ const valueCell = document.createElement('td');
384
+ valueCell.classList.add('object-value');
385
+ createLevel(valueCell, v);
386
+ row.appendChild(valueCell);
387
+ tbody.appendChild(row);
388
+ });
389
+ table.appendChild(tbody);
390
+ parent.appendChild(table);
391
+ return table;
384
392
  }
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
- }
393
+ };
394
+ const wrapper = document.createElement('div');
395
+ wrapper.classList.add('object-properties');
396
+ container.appendChild(wrapper);
397
+ if (options.propertiesField) {
398
+ createLevel(wrapper, feature[options.propertiesField], true);
392
399
  }
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
- }
400
+ else {
401
+ createLevel(wrapper, feature, true);
404
402
  }
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;
403
+ }
404
+ async function augment(rootElem, context, options = {}) {
405
+ const mergedOptions = { ...defaultAugmentOptions, ...options };
406
+ const resolveTerm = (term, contextStack, useVocab = true, useBase = false) => {
407
+ if (term.indexOf('://') !== -1) {
408
+ return { '@id': term };
416
409
  }
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;
410
+ let closestVocab = null;
411
+ let closestBase = null;
412
+ for (let i = contextStack.length - 1; i >= 0; i--) {
413
+ if (term in contextStack[i]) {
414
+ let resolvedTerm = contextStack[i][term];
415
+ let resolvedId;
416
+ if (resolvedTerm === null || typeof resolvedTerm === 'undefined' || typeof resolvedTerm === 'boolean'
417
+ || Array.isArray(resolvedTerm)) {
418
+ continue;
419
+ }
420
+ if (typeof resolvedTerm === 'string') {
421
+ if (resolvedTerm === '@type') {
422
+ return { '@id': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' };
423
+ }
424
+ resolvedId = resolvedTerm;
425
+ resolvedTerm = { '@id': resolvedTerm };
426
+ }
427
+ else if (typeof resolvedTerm === 'object' && '@id' in resolvedTerm && typeof resolvedTerm['@id'] === 'string') {
428
+ resolvedId = resolvedTerm['@id'];
429
+ }
430
+ else {
431
+ continue;
432
+ }
433
+ const idx = resolvedId.indexOf(':');
434
+ if (idx > -1) {
435
+ const prefix = resolvedId.substring(0, idx);
436
+ const localPart = resolvedId.substring(idx + 1);
437
+ if (localPart.startsWith('//')) {
438
+ // Full URI -> return
439
+ return resolvedTerm;
440
+ }
441
+ const resolvedPrefix = resolveTerm(prefix, contextStack);
442
+ if (resolvedPrefix !== null && '@id' in resolvedPrefix && typeof resolvedPrefix['@id'] === 'string') {
443
+ // Prefix found and resolved
444
+ resolvedTerm['@id'] = `${resolvedPrefix['@id']}${localPart}`;
445
+ }
446
+ return resolvedTerm;
447
+ }
448
+ }
449
+ if (closestVocab === null && contextStack[i]['@vocab']) {
450
+ closestVocab = contextStack[i]['@vocab'];
451
+ }
452
+ if (closestBase === null && contextStack[i]['@base']) {
453
+ closestBase = contextStack[i]['@base'];
454
+ }
434
455
  }
435
- if (nodeElem.classList.contains('literal-value')) {
436
- result.push(nodeElem);
437
- return NodeFilter.FILTER_REJECT;
456
+ if (term.indexOf(':') === -1) {
457
+ if (useVocab && closestVocab) {
458
+ return { '@id': `${closestVocab}${term}` };
459
+ }
460
+ if (useBase && closestBase) {
461
+ return { '@id': `${closestBase}${term}` };
462
+ }
438
463
  }
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;
464
+ return null;
465
+ };
466
+ const findPropertyChildren = (elem) => {
467
+ const walker = document.createTreeWalker(elem, NodeFilter.SHOW_ELEMENT, {
468
+ acceptNode(node) {
469
+ const nodeElem = node;
470
+ if (node !== elem && nodeElem.classList.contains('object-value')) {
471
+ return NodeFilter.FILTER_REJECT;
472
+ }
473
+ if (nodeElem.classList.contains('object-property')) {
474
+ return NodeFilter.FILTER_ACCEPT;
475
+ }
476
+ return NodeFilter.FILTER_SKIP;
477
+ },
478
+ });
479
+ const result = [];
480
+ let cur;
481
+ while ((cur = walker.nextNode())) {
482
+ result.push(cur);
454
483
  }
455
- }
456
- if (resourceData.description) {
457
- elem.setAttribute('data-description', resourceData.description);
458
- if (mergedOptions.replaceElements) {
459
- elemToUpdate.title = resourceData.description;
484
+ return result;
485
+ };
486
+ const findLiteralChildren = (elem) => {
487
+ const result = [];
488
+ const walker = document.createTreeWalker(elem, NodeFilter.SHOW_ELEMENT, {
489
+ acceptNode(node) {
490
+ const nodeElem = node;
491
+ if (nodeElem.classList.contains('object-property') || nodeElem.classList.contains('object-value')) {
492
+ return NodeFilter.FILTER_REJECT;
493
+ }
494
+ if (nodeElem.classList.contains('literal-value')) {
495
+ result.push(nodeElem);
496
+ return NodeFilter.FILTER_REJECT;
497
+ }
498
+ return NodeFilter.FILTER_SKIP;
499
+ },
500
+ });
501
+ while (walker.nextNode()) {
460
502
  }
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']];
503
+ return result;
504
+ };
505
+ const updateElement = (elem, resourceUri, replaceElements = true) => {
506
+ elem.setAttribute('data-uri', resourceUri);
507
+ elem.classList.add('resource-loading');
508
+ fetchResource(resourceUri, mergedOptions)
509
+ .then(resourceData => {
510
+ let elemToUpdate = elem.querySelector('.resource-link') || elem;
511
+ if (resourceData.label) {
512
+ elem.setAttribute('data-label', resourceData.label);
513
+ if (mergedOptions.replaceElements) {
514
+ elemToUpdate.textContent = resourceData.label;
515
+ }
516
+ }
517
+ if (resourceData.description) {
518
+ elem.setAttribute('data-description', resourceData.description);
519
+ if (mergedOptions.replaceElements) {
520
+ elemToUpdate.title = resourceData.description;
521
+ }
522
+ }
523
+ elem.classList.add('resource-resolved');
524
+ })
525
+ .catch(e => {
526
+ console.error(`Error resolving URI ${resourceUri}: ${e}`, { cause: e });
527
+ elem.classList.add('resource-error');
528
+ })
529
+ .finally(() => {
530
+ elem.classList.remove('resource-loading');
531
+ });
532
+ if (replaceElements) {
533
+ const link = document.createElement("a");
534
+ link.href = resourceUri;
535
+ link.target = '_blank';
536
+ link.classList.add('resource-link');
537
+ while (elem.firstChild) {
538
+ link.appendChild(elem.firstChild);
539
+ }
540
+ elem.appendChild(link);
499
541
  }
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);
542
+ };
543
+ const augmentInner = (elem, contextStack) => {
544
+ var _a;
545
+ const propElems = findPropertyChildren(elem);
546
+ for (const propElem of propElems) {
547
+ let propertyName = null;
548
+ propertyName = propElem.getAttribute('data-property');
549
+ if (!propertyName) {
550
+ propertyName = propElem.textContent.trim();
551
+ }
552
+ const resolvedProperty = resolveTerm(propertyName, contextStack);
553
+ let newContextStack = contextStack;
554
+ const valueElem = (_a = propElem.parentElement) === null || _a === void 0 ? void 0 : _a.querySelector('.object-value');
555
+ if (resolvedProperty && '@id' in resolvedProperty && typeof resolvedProperty['@id'] === 'string') {
556
+ const propertyUri = resolvedProperty['@id'];
557
+ updateElement(propElem, propertyUri, mergedOptions.replaceElements);
558
+ if ('@context' in resolvedProperty) {
559
+ newContextStack = [...contextStack, resolvedProperty['@context']];
560
+ }
561
+ if (resolvedProperty['@type'] === '@id' && valueElem) {
562
+ const literalElems = findLiteralChildren(valueElem);
563
+ literalElems.forEach(literalElem => {
564
+ const resolvedLiteral = resolveTerm(literalElem.textContent.trim(), newContextStack, false, true);
565
+ if (resolvedLiteral && '@id' in resolvedLiteral && typeof resolvedLiteral['@id'] === 'string') {
566
+ const resourceUri = resolvedLiteral['@id'];
567
+ updateElement(literalElem, resourceUri, mergedOptions.replaceElements);
568
+ }
569
+ });
570
+ }
571
+ }
572
+ if (valueElem) {
573
+ augmentInner(valueElem, newContextStack);
507
574
  }
508
- });
509
575
  }
510
- }
511
- if (valueElem) {
512
- augmentInner(valueElem, newContextStack);
513
- }
514
- }
515
- };
516
- augmentInner(rootElem, [context]);
576
+ };
577
+ augmentInner(rootElem, [context]);
517
578
  }
518
579
 
519
580
  var augment$1 = /*#__PURE__*/Object.freeze({
@@ -523,9 +584,9 @@ var augment$1 = /*#__PURE__*/Object.freeze({
523
584
  });
524
585
 
525
586
  var index = {
526
- ...resource,
527
- ...jsonld,
528
- ...augment$1
587
+ ...resource,
588
+ ...jsonld,
589
+ ...augment$1,
529
590
  };
530
591
 
531
592
  exports.augment = augment;
@@ -533,6 +594,7 @@ exports.createPropertiesTable = createPropertiesTable;
533
594
  exports.default = index;
534
595
  exports.defaultFetchResourceOptions = defaultFetchResourceOptions;
535
596
  exports.fetchResource = fetchResource;
597
+ exports.findInStore = findInStore;
536
598
  exports.loadContext = loadContext;
537
599
  exports.loadFeature = loadFeature;
538
600
  //# sourceMappingURL=index.cjs.js.map