sol-components 2.1.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 +7 -0
- package/core/activate.js +27 -0
- package/core/adopt.js +71 -0
- package/core/auth-core.js +73 -0
- package/core/auth-fetch.js +154 -0
- package/core/component-mount.js +110 -0
- package/core/defaults.js +48 -0
- package/core/define.js +15 -0
- package/core/display-target.js +166 -0
- package/core/edit-placements.js +28 -0
- package/core/editor-self.js +127 -0
- package/core/editor.js +162 -0
- package/core/events.js +27 -0
- package/core/extension-points.js +189 -0
- package/core/form-utils.js +210 -0
- package/core/from-query.js +138 -0
- package/core/from-rdf.js +52 -0
- package/core/here.js +33 -0
- package/core/include-core.js +73 -0
- package/core/inrupt-global.js +18 -0
- package/core/menu-consumer.js +41 -0
- package/core/menu-rdf.js +154 -0
- package/core/pod-ops.js +392 -0
- package/core/pod-registry.js +82 -0
- package/core/popup-proxy.js +255 -0
- package/core/rdf-core.js +280 -0
- package/core/rdf-render.js +136 -0
- package/core/rdf-utils.js +411 -0
- package/core/rdf.js +154 -0
- package/core/services.js +106 -0
- package/core/shape-to-form.js +741 -0
- package/core/sparql-safety.js +20 -0
- package/core/utils.js +196 -0
- package/dist/importmap-cdn.json +49 -0
- package/dist/importmap-local.json +49 -0
- package/dist/sol-loader.manifest.json +140 -0
- package/dist/vendor/@comunica-query-sparql.js +137851 -0
- package/dist/vendor/@inrupt-solid-client-authn-browser.js +7503 -0
- package/dist/vendor/dompurify.js +1476 -0
- package/dist/vendor/ical.js.js +9739 -0
- package/dist/vendor/marked.js +85 -0
- package/dist/vendor/n3.js +14670 -0
- package/dist/vendor/rdf-validate-shacl.js +6970 -0
- package/dist/vendor/rdflib.js +35172 -0
- package/dist/vendor/solid-logic.js +6819 -0
- package/dist/vendor/solid-ui.js +21945 -0
- package/node/sol-form.js +133 -0
- package/node/sol-include.js +55 -0
- package/node/sol-login.js +632 -0
- package/node/sol-menu.js +639 -0
- package/node/sol-query.js +116 -0
- package/package.json +133 -0
- package/web/menu-from-rdf.js +23 -0
- package/web/scripts/prefs.js +25 -0
- package/web/sol-accordion.js +114 -0
- package/web/sol-basic.js +50 -0
- package/web/sol-breadcrumb.js +131 -0
- package/web/sol-button.js +244 -0
- package/web/sol-calendar.js +465 -0
- package/web/sol-default.js +118 -0
- package/web/sol-dropdown-button.js +222 -0
- package/web/sol-feed.js +1336 -0
- package/web/sol-form.js +949 -0
- package/web/sol-full.js +43 -0
- package/web/sol-gallery.js +303 -0
- package/web/sol-include.js +246 -0
- package/web/sol-live-edit.js +415 -0
- package/web/sol-login.js +856 -0
- package/web/sol-menu.js +593 -0
- package/web/sol-modal.js +377 -0
- package/web/sol-pod-extras.js +17 -0
- package/web/sol-pod-ops.js +680 -0
- package/web/sol-pod.js +1039 -0
- package/web/sol-query.js +546 -0
- package/web/sol-rolodex.js +95 -0
- package/web/sol-search.js +402 -0
- package/web/sol-settings.js +199 -0
- package/web/sol-solidos.js +93 -0
- package/web/sol-tabs.js +445 -0
- package/web/sol-time.js +194 -0
- package/web/sol-tree-edit.js +492 -0
- package/web/sol-wac.js +456 -0
- package/web/sol-weather.js +337 -0
- package/web/sol-window.js +142 -0
- package/web/styles/buttons-css.js +108 -0
- package/web/styles/help.css +242 -0
- package/web/styles/root.css +112 -0
- package/web/styles/sol-accordion-css.js +97 -0
- package/web/styles/sol-calendar-css.js +154 -0
- package/web/styles/sol-feed-css.js +475 -0
- package/web/styles/sol-form-css.js +471 -0
- package/web/styles/sol-gallery-css.js +181 -0
- package/web/styles/sol-include-css.js +95 -0
- package/web/styles/sol-live-edit-css.js +84 -0
- package/web/styles/sol-live-edit.css +101 -0
- package/web/styles/sol-login-css.js +116 -0
- package/web/styles/sol-menu-css.js +145 -0
- package/web/styles/sol-modal-css.js +134 -0
- package/web/styles/sol-pod-css.js +187 -0
- package/web/styles/sol-pod-modal-css.js +203 -0
- package/web/styles/sol-query-css.js +140 -0
- package/web/styles/sol-query-help.css +267 -0
- package/web/styles/sol-query-one-pager.css +67 -0
- package/web/styles/sol-search-css.js +157 -0
- package/web/styles/sol-solidos-css.js +7 -0
- package/web/styles/sol-tabs-css.js +114 -0
- package/web/styles/sol-time-css.js +30 -0
- package/web/styles/sol-wac-css.js +73 -0
- package/web/styles/sol-weather-css.js +59 -0
- package/web/styles/solid-logo.svg +9 -0
- package/web/styles/view-accordion-css.js +66 -0
- package/web/styles/view-anchorlist-css.js +22 -0
- package/web/styles/view-autocomplete-css.js +59 -0
- package/web/styles/view-rolodex-css.js +102 -0
- package/web/styles/view-select-css.js +21 -0
- package/web/utils/calendar-fetch.js +388 -0
- package/web/utils/code-mirror-editor.js +82 -0
- package/web/utils/commons-fetch.js +108 -0
- package/web/utils/feed-edit.js +159 -0
- package/web/utils/feed-edit.smoke.mjs +74 -0
- package/web/utils/feed-fetch.js +573 -0
- package/web/utils/live-edit-help/csv.js +64 -0
- package/web/utils/live-edit-help/graphviz.js +41 -0
- package/web/utils/live-edit-help/jsonld.js +55 -0
- package/web/utils/live-edit-help/markdown.js +52 -0
- package/web/utils/live-edit-help/mermaid.js +48 -0
- package/web/utils/live-edit-help/turtle.js +85 -0
- package/web/utils/rdf-config.js +125 -0
- package/web/utils/renderers/csv.js +124 -0
- package/web/utils/renderers/d3-force.js +82 -0
- package/web/utils/renderers/graphviz.js +13 -0
- package/web/utils/renderers/html.js +10 -0
- package/web/utils/renderers/jsonld.js +63 -0
- package/web/utils/renderers/markdown.js +19 -0
- package/web/utils/renderers/mermaid.js +54 -0
- package/web/utils/renderers/turtle.js +51 -0
- package/web/utils/sol-query-triple-patterns.js +151 -0
- package/web/utils/sol-query-ui.js +250 -0
- package/web/utils/sol-query-views.js +32 -0
- package/web/views/_helpers.js +34 -0
- package/web/views/accordion.js +133 -0
- package/web/views/anchorlist.js +59 -0
- package/web/views/auto-complete.js +183 -0
- package/web/views/dl.js +38 -0
- package/web/views/list.js +19 -0
- package/web/views/menu.js +56 -0
- package/web/views/rolodex.js +126 -0
- package/web/views/select.js +79 -0
- package/web/views/table.js +73 -0
- package/web/views/tabs.js +57 -0
package/node/sol-form.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// Node.js programmatic API for sol-form — loads a ui:Form definition,
|
|
2
|
+
// populates an rdflib store from a plain JS data object, and serializes
|
|
3
|
+
// the result as Turtle.
|
|
4
|
+
//
|
|
5
|
+
// Usage:
|
|
6
|
+
// import { solForm } from 'sol-components/form';
|
|
7
|
+
// const { turtle } = await solForm({
|
|
8
|
+
// source: 'data/menu-form.ttl',
|
|
9
|
+
// data: { label: 'My Menu', orientation: 'horizontal', parts: [...] },
|
|
10
|
+
// });
|
|
11
|
+
|
|
12
|
+
import * as $rdf from 'rdflib';
|
|
13
|
+
import { readFileSync } from 'node:fs';
|
|
14
|
+
import { resolve as resolvePath } from 'node:path';
|
|
15
|
+
import { pathToFileURL } from 'node:url';
|
|
16
|
+
import {
|
|
17
|
+
UI, RDF, findForm, populateStore, setDefaults, readFormParts,
|
|
18
|
+
} from '../core/form-utils.js';
|
|
19
|
+
|
|
20
|
+
// ─── store loading ──────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
function loadLocal(filePath) {
|
|
23
|
+
const abs = resolvePath(filePath);
|
|
24
|
+
const text = readFileSync(abs, 'utf-8');
|
|
25
|
+
const store = $rdf.graph();
|
|
26
|
+
const base = pathToFileURL(abs).href;
|
|
27
|
+
$rdf.parse(text, store, base, 'text/turtle');
|
|
28
|
+
return { store, base };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function loadRemote(url) {
|
|
32
|
+
const resp = await fetch(url, {
|
|
33
|
+
headers: { Accept: 'text/turtle, application/rdf+xml;q=0.9, */*;q=0.1' },
|
|
34
|
+
});
|
|
35
|
+
if (!resp.ok) throw new Error(`HTTP ${resp.status} fetching ${url}`);
|
|
36
|
+
const text = await resp.text();
|
|
37
|
+
const store = $rdf.graph();
|
|
38
|
+
const ct = (resp.headers.get('content-type') || '').split(';')[0].trim();
|
|
39
|
+
const mime = ct === 'application/rdf+xml' ? 'application/rdf+xml' : 'text/turtle';
|
|
40
|
+
$rdf.parse(text, store, url, mime);
|
|
41
|
+
return { store, base: url };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function loadStore(source) {
|
|
45
|
+
if (/^https?:\/\//i.test(source)) return loadRemote(source);
|
|
46
|
+
return loadLocal(source);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ─── public API ─────────────────────────────────────────────────────
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Load a ui:Form definition and populate it with data.
|
|
53
|
+
*
|
|
54
|
+
* @param {object} opts
|
|
55
|
+
* @param {string} opts.source — path or URL to a Turtle file with a ui:Form
|
|
56
|
+
* @param {object} [opts.data] — values keyed by property local name
|
|
57
|
+
* @param {string} [opts.subject] — URI for the root subject (blank node if omitted)
|
|
58
|
+
* @param {string} [opts.shape] — path or URL to a SHACL shapes file (optional)
|
|
59
|
+
* @returns {Promise<{ turtle: string, store: object, subject: object }>}
|
|
60
|
+
*/
|
|
61
|
+
export async function solForm({ source, data, subject: subjectUri, shape } = {}) {
|
|
62
|
+
if (!source) throw new Error('source is required');
|
|
63
|
+
|
|
64
|
+
const { store: formStore, base: formBase } = await loadStore(source);
|
|
65
|
+
const formRoot = findForm(formStore, formBase);
|
|
66
|
+
if (!formRoot) throw new Error('No ui:Form found in ' + source);
|
|
67
|
+
|
|
68
|
+
const dataStore = $rdf.graph();
|
|
69
|
+
const docBase = subjectUri ? subjectUri.split('#')[0] : formBase.replace(/[^/]*$/, '_output.ttl');
|
|
70
|
+
const doc = $rdf.sym(docBase);
|
|
71
|
+
const subjectNode = subjectUri ? $rdf.sym(subjectUri) : $rdf.blankNode();
|
|
72
|
+
|
|
73
|
+
// Merge form definitions into the data store so populateStore can
|
|
74
|
+
// read field metadata (ui:parts, ui:property, ui:default, etc.)
|
|
75
|
+
for (const st of formStore.statements || formStore.match(null, null, null) || []) {
|
|
76
|
+
if (!dataStore.holds(st.subject, st.predicate, st.object, st.why)) {
|
|
77
|
+
dataStore.add(st.subject, st.predicate, st.object, st.why);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Set top-level defaults, then overlay caller-supplied data
|
|
82
|
+
setDefaults(dataStore, formRoot, subjectNode, doc);
|
|
83
|
+
if (data) {
|
|
84
|
+
populateStore(dataStore, formRoot, subjectNode, doc, data, 0);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Validate if a SHACL shape was provided
|
|
88
|
+
let validation = null;
|
|
89
|
+
if (shape) {
|
|
90
|
+
validation = await validateShape(dataStore, doc, shape);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const turtle = $rdf.serialize(doc, dataStore, docBase, 'text/turtle') || '';
|
|
94
|
+
|
|
95
|
+
return { turtle, store: dataStore, subject: subjectNode, validation };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ─── SHACL validation (lazy-loaded) ─────────────────────────────────
|
|
99
|
+
|
|
100
|
+
async function validateShape(dataStore, doc, shapePath) {
|
|
101
|
+
try {
|
|
102
|
+
const { Parser, Store } = await import('n3');
|
|
103
|
+
const SHACLValidator = (await import('rdf-validate-shacl')).default;
|
|
104
|
+
|
|
105
|
+
const parseToN3 = (text, baseIRI) => {
|
|
106
|
+
const parser = new Parser({ baseIRI });
|
|
107
|
+
const store = new Store();
|
|
108
|
+
store.addQuads(parser.parse(text));
|
|
109
|
+
return store;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const dataTurtle = $rdf.serialize(doc, dataStore, doc.value, 'text/turtle') || '';
|
|
113
|
+
if (!dataTurtle) return { conforms: false, results: [{ message: 'No data to validate' }] };
|
|
114
|
+
|
|
115
|
+
let shapeText;
|
|
116
|
+
if (/^https?:\/\//i.test(shapePath)) {
|
|
117
|
+
const resp = await fetch(shapePath);
|
|
118
|
+
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
|
|
119
|
+
shapeText = await resp.text();
|
|
120
|
+
} else {
|
|
121
|
+
shapeText = readFileSync(resolvePath(shapePath), 'utf-8');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const shapesStore = parseToN3(shapeText, shapePath);
|
|
125
|
+
const dataN3 = parseToN3(dataTurtle, doc.value);
|
|
126
|
+
const validator = new SHACLValidator(shapesStore);
|
|
127
|
+
return validator.validate(dataN3);
|
|
128
|
+
} catch (err) {
|
|
129
|
+
return { conforms: true, results: [], error: err.message };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export default solForm;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Node.js version of sol-include — same options as the web component,
|
|
2
|
+
// returns processed content as a string instead of rendering DOM.
|
|
3
|
+
//
|
|
4
|
+
// Usage:
|
|
5
|
+
// import { solInclude } from 'solid-components/include-node';
|
|
6
|
+
// const { type, content } = await solInclude('https://example.org/readme.md');
|
|
7
|
+
// const { type, content } = await solInclude('page.html', { selector: 'article' });
|
|
8
|
+
|
|
9
|
+
import { JSDOM } from 'jsdom';
|
|
10
|
+
import { fetchIncludeContent, filterWithSelector } from '../core/include-core.js';
|
|
11
|
+
|
|
12
|
+
let _purify = null;
|
|
13
|
+
|
|
14
|
+
async function nodeSanitize(html) {
|
|
15
|
+
if (!_purify) {
|
|
16
|
+
const mod = await import('dompurify');
|
|
17
|
+
const DOMPurify = mod.default ?? mod;
|
|
18
|
+
_purify = DOMPurify(new JSDOM('').window);
|
|
19
|
+
}
|
|
20
|
+
return _purify.sanitize(html);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function nodeContainer(html) {
|
|
24
|
+
return new JSDOM(html).window.document.body;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Fetch and return remote content (Node.js equivalent of <sol-include>).
|
|
29
|
+
* @param {string} source - URL to fetch
|
|
30
|
+
* @param {object} [opts]
|
|
31
|
+
* @param {string} [opts.selector] - CSS selector to filter content
|
|
32
|
+
* @param {boolean} [opts.raw] - return raw text without processing
|
|
33
|
+
* @param {boolean} [opts.trusted] - skip DOMPurify sanitization
|
|
34
|
+
* @param {function} [opts.fetchFn] - custom fetch implementation
|
|
35
|
+
* @returns {Promise<{type: 'html'|'raw', content: string}>}
|
|
36
|
+
*/
|
|
37
|
+
export async function solInclude(source, { selector, raw, trusted, fetchFn } = {}) {
|
|
38
|
+
// When a selector is present, defer sanitization so the selector can
|
|
39
|
+
// match attributes (e.g. RDFa typeof/rel) that DOMPurify would strip.
|
|
40
|
+
const result = await fetchIncludeContent(source, {
|
|
41
|
+
raw,
|
|
42
|
+
trusted: trusted || !!selector,
|
|
43
|
+
sanitize: nodeSanitize,
|
|
44
|
+
fetchFn,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (result.type === 'html' && selector) {
|
|
48
|
+
const filtered = filterWithSelector(result.content, selector, nodeContainer);
|
|
49
|
+
if (filtered === null) return { type: 'html', content: '' };
|
|
50
|
+
const safe = trusted ? filtered : await nodeSanitize(filtered);
|
|
51
|
+
return { type: 'html', content: safe };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return result;
|
|
55
|
+
}
|