@ldforge/renderers 0.1.4 → 0.1.6
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 +15 -0
- package/dist/cards.d.ts.map +1 -1
- package/dist/cards.js +45 -0
- package/dist/cards.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -44
- package/dist/index.js.map +1 -1
- package/dist/resource-inspector.d.ts +19 -0
- package/dist/resource-inspector.d.ts.map +1 -0
- package/dist/resource-inspector.js +128 -0
- package/dist/resource-inspector.js.map +1 -0
- package/dist/table-widths.d.ts +4 -0
- package/dist/table-widths.d.ts.map +1 -0
- package/dist/table-widths.js +14 -0
- package/dist/table-widths.js.map +1 -0
- package/dist/table.d.ts +12 -0
- package/dist/table.d.ts.map +1 -0
- package/dist/table.js +268 -0
- package/dist/table.js.map +1 -0
- package/package.json +2 -2
- package/src/cards.ts +45 -0
- package/src/index.ts +25 -51
- package/src/resource-inspector.ts +142 -0
- package/src/table-widths.ts +16 -0
- package/src/table.ts +323 -0
package/dist/table.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { parseColumnWidths, validColumnWidths } from './table-widths.js';
|
|
2
|
+
import { translate, resolveLocale, createSvgIcon, graphToBindings, } from '@ldforge/core';
|
|
3
|
+
import { createResourceInspector } from './resource-inspector.js';
|
|
4
|
+
export function createTableRenderer(options = {}) {
|
|
5
|
+
if (options.columnWidths && !validColumnWidths(options.columnWidths))
|
|
6
|
+
throw new Error('columnWidths must contain positive percentages totaling 100.');
|
|
7
|
+
return {
|
|
8
|
+
id: 'table',
|
|
9
|
+
wizard: {
|
|
10
|
+
description: {
|
|
11
|
+
en: 'Accepts SELECT bindings or RDF graph results.',
|
|
12
|
+
nl: 'Voor SELECT-bindings of RDF-graafresultaten.',
|
|
13
|
+
},
|
|
14
|
+
options: [
|
|
15
|
+
{
|
|
16
|
+
key: 'columns',
|
|
17
|
+
aliases: ['colums'],
|
|
18
|
+
label: {
|
|
19
|
+
en: 'Column widths (e.g. 40%,40%,20%)',
|
|
20
|
+
nl: 'Kolombreedtes (bijv. 40%,40%,20%)',
|
|
21
|
+
},
|
|
22
|
+
type: 'text',
|
|
23
|
+
defaultValue: '',
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
bindings: [],
|
|
27
|
+
},
|
|
28
|
+
documentationUrl: 'https://ldforge.nl/plugins.html#table',
|
|
29
|
+
icon: createSvgIcon(['M3 3h18v18H3zM3 9h18M9 9v12']),
|
|
30
|
+
label: { en: 'Table', nl: 'Tabel' },
|
|
31
|
+
supports: (result) => result.kind === 'bindings' || result.kind === 'graph',
|
|
32
|
+
render(container, result, context) {
|
|
33
|
+
const graph = result.kind === 'graph' ? result : undefined;
|
|
34
|
+
if (result.kind === 'graph')
|
|
35
|
+
result = graphToBindings(result);
|
|
36
|
+
if (result.kind !== 'bindings')
|
|
37
|
+
return;
|
|
38
|
+
const doc = container.ownerDocument;
|
|
39
|
+
const table = doc.createElement('table');
|
|
40
|
+
table.className = 'ldforge-table';
|
|
41
|
+
table.style.tableLayout = 'fixed';
|
|
42
|
+
table.style.width = '100%';
|
|
43
|
+
const configured = context?.directives?.columns ?? context?.directives?.colums;
|
|
44
|
+
const requested = configured === undefined
|
|
45
|
+
? options.columnWidths
|
|
46
|
+
: parseColumnWidths(configured);
|
|
47
|
+
const invalid = (configured !== undefined && !requested) ||
|
|
48
|
+
(requested !== undefined &&
|
|
49
|
+
requested.length !== result.variables.length);
|
|
50
|
+
const widths = !invalid && requested
|
|
51
|
+
? requested
|
|
52
|
+
: result.variables.map(() => 100 / result.variables.length);
|
|
53
|
+
const columns = doc.createElement('colgroup');
|
|
54
|
+
for (const width of widths) {
|
|
55
|
+
const column = doc.createElement('col');
|
|
56
|
+
column.style.width = `${width}%`;
|
|
57
|
+
columns.append(column);
|
|
58
|
+
}
|
|
59
|
+
table.append(columns);
|
|
60
|
+
const caption = table.createCaption();
|
|
61
|
+
const locale = context?.locale ?? resolveLocale();
|
|
62
|
+
caption.textContent = translate(locale, result.bindings.length === 1 ? 'resultOne' : 'resultMany', { count: new Intl.NumberFormat(locale).format(result.bindings.length) });
|
|
63
|
+
const data = result;
|
|
64
|
+
const inspector = createResourceInspector(container, {
|
|
65
|
+
locale,
|
|
66
|
+
...(graph ? { graph } : {}),
|
|
67
|
+
...(options.loadResource ? { loadResource: options.loadResource } : {}),
|
|
68
|
+
});
|
|
69
|
+
const controls = doc.createElement('div');
|
|
70
|
+
controls.className = 'ldforge-table-controls';
|
|
71
|
+
controls.style.cssText =
|
|
72
|
+
'display:flex;flex-wrap:wrap;gap:8px;align-items:end;margin-bottom:12px';
|
|
73
|
+
const search = doc.createElement('input');
|
|
74
|
+
search.type = 'search';
|
|
75
|
+
search.style.cssText =
|
|
76
|
+
'flex:1 1 180px;min-width:0;max-width:100%;box-sizing:border-box';
|
|
77
|
+
search.placeholder =
|
|
78
|
+
locale === 'nl' ? 'Zoeken in alle kolommen' : 'Search all columns';
|
|
79
|
+
search.setAttribute('aria-label', search.placeholder);
|
|
80
|
+
controls.append(search);
|
|
81
|
+
const viewport = doc.createElement('div');
|
|
82
|
+
viewport.className = 'ldforge-table-viewport';
|
|
83
|
+
const virtual = data.bindings.length > (options.virtualizeThreshold ?? 500);
|
|
84
|
+
const height = Math.max(120, options.viewportHeight ?? 480);
|
|
85
|
+
if (virtual) {
|
|
86
|
+
viewport.style.maxHeight = `${height}px`;
|
|
87
|
+
viewport.style.overflow = 'auto';
|
|
88
|
+
viewport.style.overflowAnchor = 'none';
|
|
89
|
+
viewport.tabIndex = 0;
|
|
90
|
+
viewport.setAttribute('aria-label', locale === 'nl' ? 'Resultaten' : 'Results');
|
|
91
|
+
}
|
|
92
|
+
viewport.append(table);
|
|
93
|
+
const header = table.createTHead().insertRow();
|
|
94
|
+
const filters = [];
|
|
95
|
+
let sortColumn = -1;
|
|
96
|
+
let direction = 1;
|
|
97
|
+
let rows = [...data.bindings];
|
|
98
|
+
const collator = new Intl.Collator(locale, { numeric: true });
|
|
99
|
+
const headers = [];
|
|
100
|
+
for (const [index, variable] of data.variables.entries()) {
|
|
101
|
+
const cell = doc.createElement('th');
|
|
102
|
+
cell.scope = 'col';
|
|
103
|
+
if (virtual)
|
|
104
|
+
cell.style.top = '0';
|
|
105
|
+
cell.style.overflowWrap = 'anywhere';
|
|
106
|
+
const button = doc.createElement('button');
|
|
107
|
+
button.type = 'button';
|
|
108
|
+
button.textContent = variable;
|
|
109
|
+
button.onclick = () => {
|
|
110
|
+
direction = sortColumn === index ? -direction : 1;
|
|
111
|
+
sortColumn = index;
|
|
112
|
+
refresh();
|
|
113
|
+
};
|
|
114
|
+
cell.append(button);
|
|
115
|
+
headers.push(cell);
|
|
116
|
+
header.append(cell);
|
|
117
|
+
const filterCell = doc.createElement('label');
|
|
118
|
+
filterCell.textContent = variable;
|
|
119
|
+
filterCell.style.cssText =
|
|
120
|
+
'display:flex;flex-direction:column;flex:1 1 120px;min-width:0';
|
|
121
|
+
controls.append(filterCell);
|
|
122
|
+
const filter = doc.createElement('input');
|
|
123
|
+
filter.type = 'search';
|
|
124
|
+
filter.style.width = '100%';
|
|
125
|
+
filter.style.minWidth = '0';
|
|
126
|
+
filter.style.boxSizing = 'border-box';
|
|
127
|
+
filter.setAttribute('aria-label', `${locale === 'nl' ? 'Filter' : 'Filter'} ${variable}`);
|
|
128
|
+
filter.oninput = () => refresh();
|
|
129
|
+
filters.push(filter);
|
|
130
|
+
filterCell.append(filter);
|
|
131
|
+
}
|
|
132
|
+
const body = table.createTBody();
|
|
133
|
+
const rowHeight = 36;
|
|
134
|
+
function draw() {
|
|
135
|
+
const scrollTop = viewport.scrollTop;
|
|
136
|
+
const nextBody = doc.createElement('tbody');
|
|
137
|
+
const start = virtual
|
|
138
|
+
? Math.max(0, Math.floor((scrollTop - (table.tHead?.offsetHeight ?? 0)) / rowHeight) - 5)
|
|
139
|
+
: 0;
|
|
140
|
+
const first = Math.min(start, rows.length);
|
|
141
|
+
const end = virtual
|
|
142
|
+
? Math.min(rows.length, first + Math.ceil(height / rowHeight) + 12)
|
|
143
|
+
: rows.length;
|
|
144
|
+
function spacer(size) {
|
|
145
|
+
if (!size)
|
|
146
|
+
return;
|
|
147
|
+
const row = nextBody.insertRow();
|
|
148
|
+
row.setAttribute('aria-hidden', 'true');
|
|
149
|
+
const cell = row.insertCell();
|
|
150
|
+
cell.colSpan = Math.max(1, data.variables.length);
|
|
151
|
+
cell.style.cssText = `height:${size}px;padding:0;border:0;line-height:0`;
|
|
152
|
+
}
|
|
153
|
+
spacer(first * rowHeight);
|
|
154
|
+
for (let index = first; index < end; index++) {
|
|
155
|
+
const binding = rows[index];
|
|
156
|
+
if (!binding)
|
|
157
|
+
continue;
|
|
158
|
+
const row = nextBody.insertRow();
|
|
159
|
+
row.setAttribute('aria-rowindex', String(index + 2));
|
|
160
|
+
if (virtual)
|
|
161
|
+
row.style.height = `${rowHeight}px`;
|
|
162
|
+
for (const variable of data.variables) {
|
|
163
|
+
const cell = row.insertCell();
|
|
164
|
+
cell.style.overflowWrap = 'anywhere';
|
|
165
|
+
cell.style.whiteSpace = 'pre-wrap';
|
|
166
|
+
const term = binding[variable];
|
|
167
|
+
const value = doc.createElement('span');
|
|
168
|
+
value.textContent = term?.value ?? '';
|
|
169
|
+
if (term)
|
|
170
|
+
value.title = term.value;
|
|
171
|
+
if (virtual) {
|
|
172
|
+
cell.style.cssText +=
|
|
173
|
+
';height:36px;box-sizing:border-box;padding:5px 12px;line-height:25px';
|
|
174
|
+
cell.style.whiteSpace = 'nowrap';
|
|
175
|
+
cell.style.overflow = 'hidden';
|
|
176
|
+
value.style.cssText =
|
|
177
|
+
'display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-height:28px';
|
|
178
|
+
}
|
|
179
|
+
if (term?.type === 'uri') {
|
|
180
|
+
const button = doc.createElement('button');
|
|
181
|
+
button.type = 'button';
|
|
182
|
+
button.className = 'ldforge-resource-info';
|
|
183
|
+
button.style.cssText =
|
|
184
|
+
'display:inline-flex;align-items:center;justify-content:center;flex:0 0 24px;width:24px;height:24px;padding:3px;margin:0;border:0;border-radius:50%;background:transparent;color:inherit;box-shadow:none;cursor:pointer';
|
|
185
|
+
const label = `${locale === 'nl' ? 'Informatie over' : 'Information about'} ${term.value}`;
|
|
186
|
+
button.setAttribute('aria-label', label);
|
|
187
|
+
button.title = label;
|
|
188
|
+
const infoIcon = createSvgIcon([
|
|
189
|
+
'M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20Z',
|
|
190
|
+
'M12 11v6M12 7h.01',
|
|
191
|
+
])(doc);
|
|
192
|
+
button.append(infoIcon);
|
|
193
|
+
button.onclick = () => {
|
|
194
|
+
void inspector.open(term);
|
|
195
|
+
};
|
|
196
|
+
const resource = doc.createElement('span');
|
|
197
|
+
resource.style.cssText =
|
|
198
|
+
'display:flex;align-items:baseline;gap:4px;min-width:0';
|
|
199
|
+
value.style.minWidth = '0';
|
|
200
|
+
value.style.flex = '0 1 auto';
|
|
201
|
+
button.style.alignSelf = 'center';
|
|
202
|
+
resource.append(value, button);
|
|
203
|
+
cell.append(resource);
|
|
204
|
+
}
|
|
205
|
+
if (term?.type !== 'uri')
|
|
206
|
+
cell.append(value);
|
|
207
|
+
if (term)
|
|
208
|
+
cell.title = term['xml:lang']
|
|
209
|
+
? translate(locale, 'termLanguage', {
|
|
210
|
+
language: term['xml:lang'],
|
|
211
|
+
})
|
|
212
|
+
: (term.datatype ?? term.type);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
spacer((rows.length - end) * rowHeight);
|
|
216
|
+
body.replaceChildren(...nextBody.childNodes);
|
|
217
|
+
table.setAttribute('aria-rowcount', String(rows.length + 1));
|
|
218
|
+
if (virtual)
|
|
219
|
+
viewport.scrollTop = scrollTop;
|
|
220
|
+
}
|
|
221
|
+
function refresh() {
|
|
222
|
+
const query = search.value.toLocaleLowerCase(locale);
|
|
223
|
+
rows = data.bindings.filter((binding) => data.variables.every((variable, i) => (binding[variable]?.value ?? '')
|
|
224
|
+
.toLocaleLowerCase(locale)
|
|
225
|
+
.includes((filters[i]?.value ?? '').toLocaleLowerCase(locale))) &&
|
|
226
|
+
(!query ||
|
|
227
|
+
data.variables.some((variable) => (binding[variable]?.value ?? '')
|
|
228
|
+
.toLocaleLowerCase(locale)
|
|
229
|
+
.includes(query))));
|
|
230
|
+
const variable = data.variables[sortColumn];
|
|
231
|
+
if (variable !== undefined) {
|
|
232
|
+
rows.sort((a, b) => direction *
|
|
233
|
+
collator.compare(a[variable]?.value ?? '', b[variable]?.value ?? ''));
|
|
234
|
+
}
|
|
235
|
+
headers.forEach((cell, i) => cell.setAttribute('aria-sort', i === sortColumn
|
|
236
|
+
? direction === 1
|
|
237
|
+
? 'ascending'
|
|
238
|
+
: 'descending'
|
|
239
|
+
: 'none'));
|
|
240
|
+
caption.textContent =
|
|
241
|
+
search.value || filters.some((f) => f.value)
|
|
242
|
+
? `${rows.length} / ${data.bindings.length} ${locale === 'nl' ? 'resultaten' : 'results'}`
|
|
243
|
+
: translate(locale, rows.length === 1 ? 'resultOne' : 'resultMany', { count: new Intl.NumberFormat(locale).format(rows.length) });
|
|
244
|
+
viewport.scrollTop = 0;
|
|
245
|
+
draw();
|
|
246
|
+
}
|
|
247
|
+
search.oninput = () => refresh();
|
|
248
|
+
viewport.onscroll = () => draw();
|
|
249
|
+
refresh();
|
|
250
|
+
if (invalid) {
|
|
251
|
+
const warning = doc.createElement('p');
|
|
252
|
+
warning.setAttribute('role', 'alert');
|
|
253
|
+
warning.textContent =
|
|
254
|
+
locale === 'nl'
|
|
255
|
+
? 'Ongeldige kolombreedtes: gebruik één positief percentage per kolom, samen 100%. Gelijke breedtes worden gebruikt.'
|
|
256
|
+
: 'Invalid column widths: use one positive percentage per column, totaling 100%. Equal widths are used.';
|
|
257
|
+
container.replaceChildren(warning, controls, viewport, inspector.element);
|
|
258
|
+
}
|
|
259
|
+
else
|
|
260
|
+
container.replaceChildren(controls, viewport, inspector.element);
|
|
261
|
+
return () => {
|
|
262
|
+
viewport.onscroll = null;
|
|
263
|
+
inspector.destroy();
|
|
264
|
+
};
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.js","sourceRoot":"","sources":["../src/table.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ldforge/renderers",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "LDForge renderers: composable SPARQL tooling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "EUPL-1.2",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@ldforge/core": "^0.1.
|
|
28
|
+
"@ldforge/core": "^0.1.6"
|
|
29
29
|
},
|
|
30
30
|
"repository": {
|
|
31
31
|
"type": "git",
|
package/src/cards.ts
CHANGED
|
@@ -74,6 +74,51 @@ export function createCardsRenderer(
|
|
|
74
74
|
): ResultRendererPlugin {
|
|
75
75
|
return {
|
|
76
76
|
id: 'cards',
|
|
77
|
+
wizard: {
|
|
78
|
+
description: {
|
|
79
|
+
en: 'Return at least one of the optional card fields.',
|
|
80
|
+
nl: 'Geef ten minste \u00e9\u00e9n van de optionele kaartvelden terug.',
|
|
81
|
+
},
|
|
82
|
+
bindings: [
|
|
83
|
+
{
|
|
84
|
+
variable: 'card_title',
|
|
85
|
+
required: false,
|
|
86
|
+
description: { en: 'Card heading', nl: 'Titel van de kaart' },
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
variable: 'card_text',
|
|
90
|
+
required: false,
|
|
91
|
+
description: {
|
|
92
|
+
en: 'Card description',
|
|
93
|
+
nl: 'Beschrijving van de kaart',
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
variable: 'card_image',
|
|
98
|
+
required: false,
|
|
99
|
+
description: {
|
|
100
|
+
en: 'HTTP(S) image URL',
|
|
101
|
+
nl: 'HTTP(S)-URL van afbeelding',
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
variable: 'card_button',
|
|
106
|
+
required: false,
|
|
107
|
+
description: {
|
|
108
|
+
en: 'Button label; requires card_button_url',
|
|
109
|
+
nl: 'Knoptekst; vereist card_button_url',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
variable: 'card_button_url',
|
|
114
|
+
required: false,
|
|
115
|
+
description: {
|
|
116
|
+
en: 'HTTP(S) button link',
|
|
117
|
+
nl: 'HTTP(S)-link voor de knop',
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
},
|
|
77
122
|
label: { en: 'Cards', nl: 'Kaarten' },
|
|
78
123
|
icon: createSvgIcon(['M3 4h7v16H3zM14 4h7v16h-7zM3 10h7M14 10h7']),
|
|
79
124
|
documentationUrl: 'https://ldforge.nl/plugins.html#cards',
|
package/src/index.ts
CHANGED
|
@@ -1,60 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
translate,
|
|
3
|
-
resolveLocale,
|
|
4
|
-
createSvgIcon,
|
|
5
|
-
graphToBindings,
|
|
6
|
-
} from '@ldforge/core';
|
|
1
|
+
import { translate, resolveLocale, createSvgIcon } from '@ldforge/core';
|
|
7
2
|
import type { ResultRendererPlugin } from '@ldforge/core';
|
|
8
3
|
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const doc = container.ownerDocument;
|
|
20
|
-
const table = doc.createElement('table');
|
|
21
|
-
const caption = table.createCaption();
|
|
22
|
-
const locale = context?.locale ?? resolveLocale();
|
|
23
|
-
caption.textContent = translate(
|
|
24
|
-
locale,
|
|
25
|
-
result.bindings.length === 1 ? 'resultOne' : 'resultMany',
|
|
26
|
-
{ count: new Intl.NumberFormat(locale).format(result.bindings.length) },
|
|
27
|
-
);
|
|
28
|
-
const header = table.createTHead().insertRow();
|
|
29
|
-
for (const variable of result.variables) {
|
|
30
|
-
const cell = doc.createElement('th');
|
|
31
|
-
cell.scope = 'col';
|
|
32
|
-
cell.textContent = variable;
|
|
33
|
-
header.append(cell);
|
|
34
|
-
}
|
|
35
|
-
const body = table.createTBody();
|
|
36
|
-
for (const binding of result.bindings) {
|
|
37
|
-
const row = body.insertRow();
|
|
38
|
-
for (const variable of result.variables) {
|
|
39
|
-
const cell = row.insertCell();
|
|
40
|
-
const term = binding[variable];
|
|
41
|
-
cell.textContent = term?.value ?? '';
|
|
42
|
-
if (term)
|
|
43
|
-
cell.title = term['xml:lang']
|
|
44
|
-
? translate(locale, 'termLanguage', {
|
|
45
|
-
language: term['xml:lang'],
|
|
46
|
-
})
|
|
47
|
-
: (term.datatype ?? term.type);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
container.replaceChildren(table);
|
|
51
|
-
},
|
|
52
|
-
};
|
|
53
|
-
}
|
|
4
|
+
export { createTableRenderer } from './table.js';
|
|
5
|
+
export type { TableRendererOptions } from './table.js';
|
|
6
|
+
export {
|
|
7
|
+
createResourceInspector,
|
|
8
|
+
createResourceLoader,
|
|
9
|
+
} from './resource-inspector.js';
|
|
10
|
+
export type {
|
|
11
|
+
ResourceInspectorOptions,
|
|
12
|
+
ResourceLoader,
|
|
13
|
+
} from './resource-inspector.js';
|
|
54
14
|
|
|
55
15
|
export function createBooleanRenderer(): ResultRendererPlugin {
|
|
56
16
|
return {
|
|
57
17
|
id: 'boolean',
|
|
18
|
+
wizard: {
|
|
19
|
+
description: {
|
|
20
|
+
en: 'Requires a boolean ASK result.',
|
|
21
|
+
nl: 'Vereist een boolean ASK-resultaat.',
|
|
22
|
+
},
|
|
23
|
+
bindings: [],
|
|
24
|
+
},
|
|
58
25
|
documentationUrl: 'https://ldforge.nl/plugins.html#boolean',
|
|
59
26
|
icon: createSvgIcon(['m5 12 4 4L19 6']),
|
|
60
27
|
label: { en: 'Boolean', nl: 'Booleaans' },
|
|
@@ -76,6 +43,13 @@ export function createBooleanRenderer(): ResultRendererPlugin {
|
|
|
76
43
|
export function createJsonRenderer(): ResultRendererPlugin {
|
|
77
44
|
return {
|
|
78
45
|
id: 'json',
|
|
46
|
+
wizard: {
|
|
47
|
+
description: {
|
|
48
|
+
en: 'Accepts any query result.',
|
|
49
|
+
nl: 'Geschikt voor elk queryresultaat.',
|
|
50
|
+
},
|
|
51
|
+
bindings: [],
|
|
52
|
+
},
|
|
79
53
|
documentationUrl: 'https://ldforge.nl/plugins.html#json',
|
|
80
54
|
icon: createSvgIcon(['M8 3H6v7l-3 2 3 2v7h2M16 3h2v7l3 2-3 2v7h-2']),
|
|
81
55
|
label: 'JSON',
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type { BindingTerm, QueryExecutor, QueryResult } from '@ldforge/core';
|
|
2
|
+
|
|
3
|
+
export type ResourceLoader = (
|
|
4
|
+
iri: string,
|
|
5
|
+
signal: AbortSignal,
|
|
6
|
+
) => Promise<QueryResult>;
|
|
7
|
+
export interface ResourceInspectorOptions {
|
|
8
|
+
readonly locale?: 'en' | 'nl';
|
|
9
|
+
readonly graph?: Extract<QueryResult, { kind: 'graph' }>;
|
|
10
|
+
readonly loadResource?: ResourceLoader;
|
|
11
|
+
}
|
|
12
|
+
/** Uses the host transport, credentials and cancellation; never dereferences arbitrary URLs. */
|
|
13
|
+
export function createResourceLoader(executor: QueryExecutor): ResourceLoader {
|
|
14
|
+
return (iri, signal) => {
|
|
15
|
+
if (
|
|
16
|
+
!iri ||
|
|
17
|
+
[...iri].some((character) => character.charCodeAt(0) <= 32) ||
|
|
18
|
+
/[<>"{}|^`\\]/u.test(iri) ||
|
|
19
|
+
!/^[a-z][a-z\d+.-]*:/i.test(iri)
|
|
20
|
+
)
|
|
21
|
+
return Promise.reject(new Error('Invalid resource IRI.'));
|
|
22
|
+
return executor.execute({
|
|
23
|
+
query: `CONSTRUCT { <${iri}> ?p ?o . ?s ?incoming <${iri}> } WHERE { { <${iri}> ?p ?o } UNION { ?s ?incoming <${iri}> } } LIMIT 200`,
|
|
24
|
+
signal,
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** A reusable inline panel for tables, cards, networks and maps. */
|
|
29
|
+
export function createResourceInspector(
|
|
30
|
+
container: HTMLElement,
|
|
31
|
+
options: ResourceInspectorOptions = {},
|
|
32
|
+
) {
|
|
33
|
+
const doc = container.ownerDocument;
|
|
34
|
+
const nl = options.locale === 'nl';
|
|
35
|
+
const element = doc.createElement('section');
|
|
36
|
+
element.className = 'ldforge-resource-inspector';
|
|
37
|
+
element.hidden = true;
|
|
38
|
+
element.setAttribute(
|
|
39
|
+
'aria-label',
|
|
40
|
+
nl ? 'Resource verkennen' : 'Resource inspector',
|
|
41
|
+
);
|
|
42
|
+
element.tabIndex = -1;
|
|
43
|
+
element.style.cssText =
|
|
44
|
+
'padding:12px;border:1px solid currentColor;overflow-wrap:anywhere;font-size:12px;line-height:1.5';
|
|
45
|
+
let controller: AbortController | undefined;
|
|
46
|
+
let disposed = false;
|
|
47
|
+
let origin: HTMLElement | null = null;
|
|
48
|
+
function close() {
|
|
49
|
+
controller?.abort();
|
|
50
|
+
element.hidden = true;
|
|
51
|
+
origin?.focus();
|
|
52
|
+
}
|
|
53
|
+
async function open(term: BindingTerm) {
|
|
54
|
+
if (disposed || term.type !== 'uri') return;
|
|
55
|
+
if (element.hidden)
|
|
56
|
+
origin =
|
|
57
|
+
doc.activeElement instanceof HTMLElement ? doc.activeElement : null;
|
|
58
|
+
controller?.abort();
|
|
59
|
+
const current = new AbortController();
|
|
60
|
+
controller = current;
|
|
61
|
+
element.hidden = false;
|
|
62
|
+
const heading = doc.createElement('h3');
|
|
63
|
+
heading.textContent = term.value;
|
|
64
|
+
heading.style.cssText = 'font-size:13px;line-height:1.5;margin:0 0 8px';
|
|
65
|
+
const closeButton = doc.createElement('button');
|
|
66
|
+
closeButton.type = 'button';
|
|
67
|
+
closeButton.style.fontSize = 'inherit';
|
|
68
|
+
closeButton.textContent = nl ? 'Sluiten' : 'Close';
|
|
69
|
+
closeButton.onclick = close;
|
|
70
|
+
const content = doc.createElement('div');
|
|
71
|
+
content.setAttribute('role', 'status');
|
|
72
|
+
content.textContent = nl ? 'Laden…' : 'Loading…';
|
|
73
|
+
element.replaceChildren(heading, closeButton, content);
|
|
74
|
+
if (/^https?:\/\//i.test(term.value)) {
|
|
75
|
+
const link = doc.createElement('a');
|
|
76
|
+
link.href = term.value;
|
|
77
|
+
link.target = '_blank';
|
|
78
|
+
link.rel = 'noopener noreferrer';
|
|
79
|
+
link.textContent = nl ? 'Open resource' : 'Open resource';
|
|
80
|
+
element.append(link);
|
|
81
|
+
}
|
|
82
|
+
element.focus();
|
|
83
|
+
try {
|
|
84
|
+
const matches = (triple: { subject: BindingTerm; object: BindingTerm }) =>
|
|
85
|
+
(triple.subject.type === 'uri' &&
|
|
86
|
+
triple.subject.value === term.value) ||
|
|
87
|
+
(triple.object.type === 'uri' && triple.object.value === term.value);
|
|
88
|
+
const local = options.graph?.triples.filter(matches);
|
|
89
|
+
const result = local?.length
|
|
90
|
+
? { kind: 'graph' as const, triples: local }
|
|
91
|
+
: await options.loadResource?.(term.value, current.signal);
|
|
92
|
+
if (disposed || current.signal.aborted) return;
|
|
93
|
+
content.replaceChildren();
|
|
94
|
+
const triples =
|
|
95
|
+
result?.kind === 'graph' ? result.triples.filter(matches) : [];
|
|
96
|
+
if (!triples.length) {
|
|
97
|
+
content.textContent = nl
|
|
98
|
+
? 'Geen eigenschappen beschikbaar in deze gegevens.'
|
|
99
|
+
: 'No properties available in this data.';
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const list = doc.createElement('dl');
|
|
103
|
+
for (const triple of triples) {
|
|
104
|
+
const incoming = triple.subject.value !== term.value;
|
|
105
|
+
const name = doc.createElement('dt');
|
|
106
|
+
name.textContent = `${incoming ? '← ' : ''}${triple.predicate.value}`;
|
|
107
|
+
const value = incoming ? triple.subject : triple.object;
|
|
108
|
+
const description = doc.createElement('dd');
|
|
109
|
+
if (value.type === 'uri') {
|
|
110
|
+
const button = doc.createElement('button');
|
|
111
|
+
button.type = 'button';
|
|
112
|
+
button.style.fontSize = 'inherit';
|
|
113
|
+
button.textContent = value.value;
|
|
114
|
+
button.style.overflowWrap = 'anywhere';
|
|
115
|
+
button.onclick = () => {
|
|
116
|
+
void open(value);
|
|
117
|
+
};
|
|
118
|
+
description.append(button);
|
|
119
|
+
} else description.textContent = value.value;
|
|
120
|
+
description.title = value['xml:lang'] ?? value.datatype ?? value.type;
|
|
121
|
+
list.append(name, description);
|
|
122
|
+
}
|
|
123
|
+
content.append(list);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
if (!disposed && !current.signal.aborted)
|
|
126
|
+
content.textContent = `${nl ? 'Laden mislukt' : 'Loading failed'}: ${error instanceof Error ? error.message : String(error)}`;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
element.onkeydown = (event) => {
|
|
130
|
+
if (event.key === 'Escape') close();
|
|
131
|
+
};
|
|
132
|
+
return {
|
|
133
|
+
element,
|
|
134
|
+
open,
|
|
135
|
+
close,
|
|
136
|
+
destroy() {
|
|
137
|
+
disposed = true;
|
|
138
|
+
controller?.abort();
|
|
139
|
+
element.remove();
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Percentage widths only: never interpolate arbitrary query strings into CSS. */
|
|
2
|
+
export function validColumnWidths(widths: readonly number[]): boolean {
|
|
3
|
+
return (
|
|
4
|
+
widths.length > 0 &&
|
|
5
|
+
widths.every(
|
|
6
|
+
(width) => Number.isFinite(width) && width > 0 && width <= 100,
|
|
7
|
+
) &&
|
|
8
|
+
Math.abs(widths.reduce((sum, width) => sum + width, 0) - 100) < 0.000001
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
export function parseColumnWidths(value: string): number[] | undefined {
|
|
12
|
+
const parts = value.split(',').map((part) => part.trim());
|
|
13
|
+
if (parts.some((part) => !/^\d+(?:\.\d+)?%$/.test(part))) return undefined;
|
|
14
|
+
const widths = parts.map((part) => Number(part.slice(0, -1)));
|
|
15
|
+
return validColumnWidths(widths) ? widths : undefined;
|
|
16
|
+
}
|