@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/index.cjs.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var N3 = require('n3');
|
|
6
|
-
var jsonldLib = require('jsonld');
|
|
7
6
|
var rdfxmlStreamingParser = require('rdfxml-streaming-parser');
|
|
8
7
|
|
|
9
8
|
function _interopNamespaceDefault(e) {
|
|
@@ -24,85 +23,85 @@ function _interopNamespaceDefault(e) {
|
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
var N3__namespace = /*#__PURE__*/_interopNamespaceDefault(N3);
|
|
27
|
-
var jsonldLib__namespace = /*#__PURE__*/_interopNamespaceDefault(jsonldLib);
|
|
28
26
|
|
|
29
|
-
const jsonFetch = async url => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
});
|
|
35
|
-
return await response.json();
|
|
27
|
+
const jsonFetch = async (url) => {
|
|
28
|
+
const response = await fetch(url, {
|
|
29
|
+
headers: { 'Accept': 'application/json' },
|
|
30
|
+
});
|
|
31
|
+
return await response.json();
|
|
36
32
|
};
|
|
37
|
-
const mergeContexts = definitions => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
const mergeContexts = (definitions) => {
|
|
34
|
+
const mergePair = (a, b) => {
|
|
35
|
+
if (!a || !Object.keys(a).length) {
|
|
36
|
+
return b;
|
|
37
|
+
}
|
|
38
|
+
const result = { ...a };
|
|
39
|
+
for (const [k, v] of Object.entries(b)) {
|
|
40
|
+
result[k] = v;
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
44
43
|
};
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
if (!definitions.length) {
|
|
45
|
+
return {};
|
|
47
46
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
let currentContext = definitions[0];
|
|
57
|
-
for (let i = 1; i < definitions.length; i++) {
|
|
58
|
-
currentContext = mergePair(currentContext, definitions[i]);
|
|
59
|
-
}
|
|
60
|
-
return currentContext;
|
|
47
|
+
if (definitions.length === 1) {
|
|
48
|
+
return definitions[0];
|
|
49
|
+
}
|
|
50
|
+
let currentContext = definitions[0];
|
|
51
|
+
for (let i = 1; i < definitions.length; i++) {
|
|
52
|
+
currentContext = mergePair(currentContext, definitions[i]);
|
|
53
|
+
}
|
|
54
|
+
return currentContext;
|
|
61
55
|
};
|
|
62
56
|
async function loadContext(context) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
57
|
+
const loadedUrls = new Map();
|
|
58
|
+
const walk = async (definition, refChain) => {
|
|
59
|
+
for (const [key, value] of Object.entries(definition)) {
|
|
60
|
+
if (key === '@context') {
|
|
61
|
+
// @ts-ignore
|
|
62
|
+
definition[key] = await load(value, refChain);
|
|
63
|
+
}
|
|
64
|
+
else if (typeof value === 'object' && value !== null) {
|
|
65
|
+
await walk(value, refChain);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const load = async (context, refChain) => {
|
|
70
|
+
if (context === null || typeof context === 'undefined') {
|
|
71
|
+
return {};
|
|
72
|
+
}
|
|
73
|
+
if (Array.isArray(context)) {
|
|
74
|
+
// fetch and merge
|
|
75
|
+
const contextEntries = await Promise.all(context.map(e => load(e, refChain)));
|
|
76
|
+
return mergeContexts(contextEntries);
|
|
77
|
+
}
|
|
78
|
+
else if (typeof context === 'object') {
|
|
79
|
+
await walk(context, refChain);
|
|
80
|
+
return context;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
if (refChain === null || refChain === void 0 ? void 0 : refChain.includes(context)) {
|
|
84
|
+
throw new Error('Circular dependencies found: ' + refChain.join(' -> ') + ' -> ' + context);
|
|
85
|
+
}
|
|
86
|
+
const newRefChain = Array.isArray(refChain) ? refChain === null || refChain === void 0 ? void 0 : refChain.slice() : [];
|
|
87
|
+
newRefChain.push(context);
|
|
88
|
+
let newContext;
|
|
89
|
+
if (!loadedUrls.has(context)) {
|
|
90
|
+
newContext = await jsonFetch(context);
|
|
91
|
+
loadedUrls.set(context, newContext);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
newContext = loadedUrls.get(context);
|
|
95
|
+
}
|
|
96
|
+
return load(newContext['@context'], newRefChain);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
if (typeof context === 'object' && context !== null && '@context' in context) {
|
|
100
|
+
return load(context['@context']);
|
|
77
101
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const contextEntries = await Promise.all(context.map(e => load(e, refChain)));
|
|
81
|
-
return mergeContexts(contextEntries);
|
|
82
|
-
} else if (typeof context === 'object') {
|
|
83
|
-
await walk(context, refChain);
|
|
84
|
-
return context;
|
|
85
|
-
} else {
|
|
86
|
-
if (refChain === null || refChain === void 0 ? void 0 : refChain.includes(context)) {
|
|
87
|
-
throw new Error('Circular dependencies found: ' + refChain.join(' -> ') + ' -> ' + context);
|
|
88
|
-
}
|
|
89
|
-
const newRefChain = Array.isArray(refChain) ? refChain === null || refChain === void 0 ? void 0 : refChain.slice() : [];
|
|
90
|
-
newRefChain.push(context);
|
|
91
|
-
let newContext;
|
|
92
|
-
if (!loadedUrls.has(context)) {
|
|
93
|
-
newContext = await jsonFetch(context);
|
|
94
|
-
loadedUrls.set(context, newContext);
|
|
95
|
-
} else {
|
|
96
|
-
newContext = loadedUrls.get(context);
|
|
97
|
-
}
|
|
98
|
-
return load(newContext['@context'], newRefChain);
|
|
102
|
+
else {
|
|
103
|
+
return load(context);
|
|
99
104
|
}
|
|
100
|
-
};
|
|
101
|
-
if (typeof context === 'object' && context !== null && '@context' in context) {
|
|
102
|
-
return load(context['@context']);
|
|
103
|
-
} else {
|
|
104
|
-
return load(context);
|
|
105
|
-
}
|
|
106
105
|
}
|
|
107
106
|
|
|
108
107
|
var jsonld = /*#__PURE__*/Object.freeze({
|
|
@@ -110,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 = [
|
|
121
|
-
|
|
119
|
+
const labelPredicates = [
|
|
120
|
+
SKOS('prefLabel'),
|
|
121
|
+
DCT('title'),
|
|
122
|
+
DC('title'),
|
|
123
|
+
SDO('name'),
|
|
124
|
+
FOAF('name'),
|
|
125
|
+
RDFS('label'),
|
|
126
|
+
];
|
|
127
|
+
const descriptionPredicates = [
|
|
128
|
+
SKOS('definition'),
|
|
129
|
+
DCT('description'),
|
|
130
|
+
DC('description'),
|
|
131
|
+
RDFS('comment'),
|
|
132
|
+
];
|
|
122
133
|
|
|
123
134
|
const defaultFetchResourceOptions = {
|
|
124
|
-
|
|
125
|
-
|
|
135
|
+
labelPredicates,
|
|
136
|
+
descriptionPredicates,
|
|
126
137
|
};
|
|
127
138
|
const fetchResourceCache = {};
|
|
128
|
-
const
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
214
|
-
|
|
215
|
-
headers: {
|
|
216
|
-
|
|
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
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
query: getSparqlQuery(uri)
|
|
235
|
-
});
|
|
236
|
-
result = await tryFetchAndParse(() => fetch(endpoint, {
|
|
237
|
-
method: 'POST',
|
|
238
|
-
headers: {
|
|
239
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
|
240
|
-
'Accept': 'text/turtle, application/n-triples'
|
|
241
|
-
},
|
|
242
|
-
body: formBody.toString()
|
|
243
|
-
}), uri, options);
|
|
244
|
-
}
|
|
245
|
-
if (!result) {
|
|
246
|
-
throw new Error(`No label data found for <${uri}>`);
|
|
247
|
-
}
|
|
248
|
-
return result;
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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
|
-
|
|
286
|
-
|
|
348
|
+
replaceElements: true,
|
|
349
|
+
...defaultFetchResourceOptions,
|
|
287
350
|
};
|
|
288
351
|
function createPropertiesTable(feature, container, options = {
|
|
289
|
-
|
|
352
|
+
propertiesField: 'properties',
|
|
290
353
|
}) {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
} else if (value === null || typeof value === 'undefined' || typeof value !== 'object') {
|
|
299
|
-
const span = document.createElement('span');
|
|
300
|
-
span.classList.add('literal-value');
|
|
301
|
-
span.textContent = '' + value;
|
|
302
|
-
parent.appendChild(span);
|
|
303
|
-
return span;
|
|
304
|
-
} else {
|
|
305
|
-
const table = document.createElement('table');
|
|
306
|
-
table.classList.add('object-table');
|
|
307
|
-
if (addHeaders) {
|
|
308
|
-
table.innerHTML = '<thead><tr><th>Property</th><th>Value</th></tr></thead>';
|
|
309
|
-
}
|
|
310
|
-
const tbody = document.createElement('tbody');
|
|
311
|
-
Object.entries(value).forEach(([k, v]) => {
|
|
312
|
-
const row = document.createElement('tr');
|
|
313
|
-
const keyCell = document.createElement('td');
|
|
314
|
-
keyCell.classList.add('object-property');
|
|
315
|
-
keyCell.setAttribute('data-property', k);
|
|
316
|
-
keyCell.textContent = k;
|
|
317
|
-
row.appendChild(keyCell);
|
|
318
|
-
const valueCell = document.createElement('td');
|
|
319
|
-
valueCell.classList.add('object-value');
|
|
320
|
-
createLevel(valueCell, v);
|
|
321
|
-
row.appendChild(valueCell);
|
|
322
|
-
tbody.appendChild(row);
|
|
323
|
-
});
|
|
324
|
-
table.appendChild(tbody);
|
|
325
|
-
parent.appendChild(table);
|
|
326
|
-
return table;
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
if (options.propertiesField) {
|
|
330
|
-
createLevel(container, feature[options.propertiesField], true);
|
|
331
|
-
} else {
|
|
332
|
-
createLevel(container, feature, true);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
async function augment(rootElem, context, options = {}) {
|
|
336
|
-
const mergedOptions = {
|
|
337
|
-
...defaultAugmentOptions,
|
|
338
|
-
...options
|
|
339
|
-
};
|
|
340
|
-
const resolveTerm = (term, contextStack, useVocab = true, useBase = false) => {
|
|
341
|
-
if (term.indexOf('://') !== -1) {
|
|
342
|
-
return {
|
|
343
|
-
'@id': term
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
let closestVocab = null;
|
|
347
|
-
let closestBase = null;
|
|
348
|
-
for (let i = contextStack.length - 1; i >= 0; i--) {
|
|
349
|
-
if (term in contextStack[i]) {
|
|
350
|
-
let resolvedTerm = contextStack[i][term];
|
|
351
|
-
let resolvedId;
|
|
352
|
-
if (resolvedTerm === null || typeof resolvedTerm === 'undefined' || typeof resolvedTerm === 'boolean' || Array.isArray(resolvedTerm)) {
|
|
353
|
-
continue;
|
|
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
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
resolvedId = resolvedTerm;
|
|
362
|
-
resolvedTerm = {
|
|
363
|
-
'@id': resolvedTerm
|
|
364
|
-
};
|
|
365
|
-
} else if (typeof resolvedTerm === 'object' && '@id' in resolvedTerm && typeof resolvedTerm['@id'] === 'string') {
|
|
366
|
-
resolvedId = resolvedTerm['@id'];
|
|
367
|
-
} else {
|
|
368
|
-
continue;
|
|
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
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
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
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
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
|
-
|
|
394
|
-
|
|
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
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
if (node !== elem && nodeElem.classList.contains('object-value')) {
|
|
412
|
-
return NodeFilter.FILTER_REJECT;
|
|
413
|
-
}
|
|
414
|
-
if (nodeElem.classList.contains('object-property')) {
|
|
415
|
-
return NodeFilter.FILTER_ACCEPT;
|
|
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
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
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 (
|
|
436
|
-
|
|
437
|
-
|
|
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
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
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
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
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
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
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
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
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
|
-
|
|
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
|
-
|
|
527
|
-
|
|
528
|
-
|
|
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
|