@ai-ecoverse/slicc-spectrum 1.110.0 → 1.111.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 +25 -5
- package/dist/slicc-dummy.js +47 -0
- package/dist/slicc-dummy.js.map +3 -3
- package/dist/slicc-ui.js +461 -173
- package/dist/slicc-ui.js.map +3 -3
- package/dist/types/app/sprinkle.d.ts +8 -2
- package/dist/types/dummy/sprinkles.d.ts +1 -0
- package/dist/types/model/types.d.ts +19 -1
- package/package.json +2 -2
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import '@adobe/spectrum-wc/components/action-button/swc-action-button.js';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
-
import type { SliccModel } from '../model/types.js';
|
|
3
|
+
import type { SliccModel, SprinkleCgiReply, SprinkleCgiRequest } from '../model/types.js';
|
|
4
4
|
import { type Color, ThemedElement } from './base.js';
|
|
5
5
|
import { type FontFile } from './fonts.js';
|
|
6
|
-
export declare const bridge = "(() => {\n const post = (message) => parent.postMessage(message, '*');\n window.slicc = {\n name: document.currentScript.dataset.name,\n lick(event) {\n const value = typeof event === 'string' ? { action: event } : event || {};\n post({ type: 'slicc-lick', action: String(value.action || ''), data: value.data ?? null, target: value.target ?? null });\n },\n };\n const wanted = new Set();\n let timer = 0;\n window.LucideIcons = {\n render() {\n for (const node of document.querySelectorAll('i[data-lucide]')) wanted.add(node.dataset.lucide);\n clearTimeout(timer);\n timer = setTimeout(() => post({ type: 'slicc-icons', names: [...wanted] }));\n },\n };\n const swap = (found) => {\n for (const node of document.querySelectorAll('i[data-lucide]')) {\n const markup = found[node.dataset.lucide];\n if (!markup) continue;\n const template = document.createElement('template');\n template.innerHTML = markup;\n const svg = template.content.firstElementChild;\n for (const { name, value } of node.attributes) {\n if (name === 'class') svg.setAttribute('class', svg.getAttribute('class') + ' ' + value);\n else if (name !== 'data-lucide') svg.setAttribute(name, value);\n }\n node.replaceWith(svg);\n }\n size();\n };\n const fonts = (list) => {\n for (const font of list) {\n const face = new FontFace(font.family, font.data, { weight: String(font.weight) });\n document.fonts.add(face);\n face.load().then(size, () => {});\n }\n };\n addEventListener('message', (event) => {\n if (event.source !== parent) return;\n const message = event.data || {};\n if (message.type === 'slicc-icons') swap(message.icons);\n if (message.type === 'slicc-fonts') fonts(message.fonts);\n if (message.type === 'slicc-theme') document.documentElement.classList.toggle('theme-light', message.color === 'light');\n });\n const size = () => {\n const style = getComputedStyle(document.body);\n post({ type: 'slicc-size', height: Math.ceil(document.body.offsetHeight + parseFloat(style.marginTop) + parseFloat(style.marginBottom)) });\n };\n document.addEventListener('DOMContentLoaded', () => {\n window.LucideIcons.render();\n size();\n new ResizeObserver(size).observe(document.body);\n });\n post({ type: 'slicc-ready' });\n})();";
|
|
6
|
+
export declare const bridge = "(() => {\n const post = (message) => parent.postMessage(message, '*');\n window.slicc = {\n name: document.currentScript.dataset.name,\n lick(event) {\n const value = typeof event === 'string' ? { action: event } : event || {};\n post({ type: 'slicc-lick', action: String(value.action || ''), data: value.data ?? null, target: value.target ?? null });\n },\n };\n const wanted = new Set();\n let timer = 0;\n window.LucideIcons = {\n render() {\n for (const node of document.querySelectorAll('i[data-lucide]')) wanted.add(node.dataset.lucide);\n clearTimeout(timer);\n timer = setTimeout(() => post({ type: 'slicc-icons', names: [...wanted] }));\n },\n };\n const swap = (found) => {\n for (const node of document.querySelectorAll('i[data-lucide]')) {\n const markup = found[node.dataset.lucide];\n if (!markup) continue;\n const template = document.createElement('template');\n template.innerHTML = markup;\n const svg = template.content.firstElementChild;\n for (const { name, value } of node.attributes) {\n if (name === 'class') svg.setAttribute('class', svg.getAttribute('class') + ' ' + value);\n else if (name !== 'data-lucide') svg.setAttribute(name, value);\n }\n node.replaceWith(svg);\n }\n size();\n };\n const fonts = (list) => {\n for (const font of list) {\n const face = new FontFace(font.family, font.data, { weight: String(font.weight) });\n document.fonts.add(face);\n face.load().then(size, () => {});\n }\n };\n const runs = new Map();\n addEventListener('message', (event) => {\n if (event.source !== parent) return;\n const message = event.data || {};\n if (message.type === 'slicc-icons') swap(message.icons);\n if (message.type === 'slicc-fonts') fonts(message.fonts);\n if (message.type === 'slicc-theme') document.documentElement.classList.toggle('theme-light', message.color === 'light');\n const run = runs.get(message.id);\n if (run && message.type === 'slicc-cgi-head') run.head(message);\n if (run && message.type === 'slicc-cgi-chunk') run.chunk(message);\n });\n const native = window.fetch;\n const tag = Math.random().toString(36).slice(2);\n let count = 0;\n const empty = new Set([101, 103, 204, 205, 304]);\n const moved = new Set([301, 302, 303, 307, 308]);\n const decode = (text) => Uint8Array.from(atob(text || ''), (char) => char.charCodeAt(0));\n const encode = (bytes) => {\n let text = '';\n for (let at = 0; at < bytes.length; at += 32768) text += String.fromCharCode(...bytes.subarray(at, at + 32768));\n return btoa(text);\n };\n const scope = (input) => {\n try {\n const href = input instanceof Request ? input.url : new URL(input, document.baseURI).href;\n const base = new URL('cgi-bin/', document.baseURI);\n return href.startsWith(base.href) ? base : null;\n } catch {\n return null;\n }\n };\n const send = (input, init, hops) => {\n const base = scope(input);\n if (!base) return native.call(window, input, init);\n let request;\n try {\n request = new Request(input, init);\n } catch (error) {\n return Promise.reject(error);\n }\n const payload = request.body ? request.arrayBuffer() : Promise.resolve(null);\n return payload.then((bytes) => exchange(request, base, bytes, hops));\n };\n const redirect = (request, payload, status, location, hops) => {\n if (request.redirect === 'error') throw new TypeError('fetch: the response redirects and redirect is error');\n if (hops >= 20) throw new TypeError('fetch: more than 20 redirects');\n const get = (status === 303 && request.method !== 'GET' && request.method !== 'HEAD') || ((status === 301 || status === 302) && request.method === 'POST');\n const headers = new Headers(request.headers);\n if (get) for (const name of ['content-encoding', 'content-language', 'content-location', 'content-type']) headers.delete(name);\n const init = { method: get ? 'GET' : request.method, headers, body: get ? null : payload, signal: request.signal, redirect: request.redirect };\n return send(new URL(location, request.url).href, init, hops + 1).then((response) => Object.defineProperty(response, 'redirected', { value: true }));\n };\n const exchange = (request, base, payload, hops) => new Promise((resolve, reject) => {\n const { signal } = request;\n if (signal.aborted) return reject(signal.reason);\n const id = tag + ':' + ++count;\n const url = new URL(request.url);\n const headers = new Headers(request.headers);\n if (!headers.has('accept')) headers.set('accept', '*/*');\n const language = navigator.languages.join(',') || navigator.language;\n if (language && !headers.has('accept-language')) headers.set('accept-language', language);\n let stream = null;\n const finish = () => {\n runs.delete(id);\n signal.removeEventListener('abort', abort);\n };\n const close = () => {\n finish();\n post({ type: 'slicc-cgi-close', id });\n };\n const abort = () => {\n close();\n reject(signal.reason);\n if (stream) stream.error(signal.reason);\n };\n signal.addEventListener('abort', abort);\n runs.set(id, {\n head(message) {\n if (typeof message.error === 'string') {\n finish();\n return reject(new TypeError(message.error));\n }\n const head = message.head;\n let response;\n let follow = false;\n try {\n const fields = new Headers(head.headers);\n follow = moved.has(head.status) && fields.has('location') && request.redirect !== 'manual';\n const drop = follow || request.method === 'HEAD' || empty.has(head.status);\n const body = drop ? null : new ReadableStream({\n start(controller) {\n const first = decode(head.body);\n if (first.length) controller.enqueue(first);\n if (head.done) controller.close();\n else stream = controller;\n },\n cancel() {\n if (runs.has(id)) close();\n },\n });\n response = new Response(body, { status: head.status, statusText: head.statusText, headers: fields });\n } catch (error) {\n close();\n return reject(new TypeError(error.message));\n }\n if (head.done) finish();\n url.hash = '';\n Object.defineProperty(response, 'url', { value: url.href });\n if (!follow) return resolve(response);\n try {\n resolve(redirect(request, payload, head.status, response.headers.get('location'), hops));\n } catch (error) {\n reject(error);\n }\n },\n chunk(message) {\n if (typeof message.error === 'string') {\n finish();\n if (stream) stream.error(new TypeError(message.error));\n return;\n }\n const bytes = decode(message.body);\n if (stream && bytes.length) stream.enqueue(bytes);\n if (!message.done) return;\n finish();\n if (stream) stream.close();\n },\n });\n post({\n type: 'slicc-cgi',\n id,\n request: {\n method: request.method,\n path: url.pathname.slice(base.pathname.length),\n query: url.search.slice(1),\n headers: [...headers],\n body: payload && payload.byteLength ? encode(new Uint8Array(payload)) : null,\n },\n });\n });\n window.fetch = function fetch(input, init) {\n return send(input, init, 0);\n };\n const formOf = (form, submitter) => {\n const own = (name) => !!submitter && submitter.hasAttribute('form' + name);\n return {\n action: (own('action') ? submitter.getAttribute('formaction') : form.getAttribute('action')) || '',\n method: own('method') ? submitter.formMethod : form.method,\n enctype: own('enctype') ? submitter.formEnctype : form.enctype,\n };\n };\n const submitted = (form, submitter) => {\n const { action, method, enctype } = formOf(form, submitter);\n if (!action || !scope(action)) return;\n const url = new URL(action, document.baseURI);\n const data = new FormData(form, submitter || null);\n const entries = [...data].map(([name, value]) => [name, typeof value === 'string' ? value : value.name]);\n const init = { method: method === 'post' ? 'POST' : 'GET', redirect: 'manual', headers: {} };\n if (init.method === 'GET') url.search = new URLSearchParams(entries).toString();\n else if (enctype === 'multipart/form-data') init.body = data;\n else if (enctype === 'text/plain') {\n init.body = entries.map(([name, value]) => name + '=' + value + '\\r\\n').join('');\n init.headers['content-type'] = 'text/plain';\n } else {\n init.body = new URLSearchParams(entries).toString();\n init.headers['content-type'] = 'application/x-www-form-urlencoded';\n }\n const tell = (detail) => form.dispatchEvent(new CustomEvent('slicc-cgi', { bubbles: true, cancelable: true, detail }));\n send(url.href, init, 0).then(\n (response) => {\n if (tell({ response }) && response.headers.has('location')) post({ type: 'slicc-reload' });\n },\n (error) => tell({ error }),\n );\n };\n const copies = new WeakSet();\n addEventListener('submit', (event) => {\n if (copies.has(event)) return;\n const form = event.composedPath()[0];\n if (!(form instanceof HTMLFormElement) || formOf(form, event.submitter).method === 'dialog') return;\n event.preventDefault();\n event.stopImmediatePropagation();\n const copy = new SubmitEvent('submit', { bubbles: true, cancelable: true, submitter: event.submitter });\n copies.add(copy);\n if (form.dispatchEvent(copy)) submitted(form, event.submitter);\n }, true);\n const submit = HTMLFormElement.prototype.submit;\n HTMLFormElement.prototype.submit = function () {\n if (formOf(this, null).method === 'dialog') return submit.call(this);\n submitted(this, null);\n };\n const size = () => {\n const style = getComputedStyle(document.body);\n post({ type: 'slicc-size', height: Math.ceil(document.body.offsetHeight + parseFloat(style.marginTop) + parseFloat(style.marginBottom)) });\n };\n document.addEventListener('DOMContentLoaded', () => {\n window.LucideIcons.render();\n size();\n new ResizeObserver(size).observe(document.body);\n });\n post({ type: 'slicc-ready' });\n})();";
|
|
7
7
|
export declare function literal(value: unknown): string;
|
|
8
8
|
export declare function store(state: unknown): string;
|
|
9
9
|
export declare function frameDocument(source: string, color: Color, name: string, state?: {
|
|
@@ -15,7 +15,13 @@ export declare function frameFonts(files: readonly FontFile[], base: string): Pr
|
|
|
15
15
|
weight: number | string;
|
|
16
16
|
data: ArrayBuffer;
|
|
17
17
|
}>>;
|
|
18
|
+
export declare const cgiMethods: ReadonlySet<string>;
|
|
18
19
|
export declare const sprinkleMethods: ReadonlySet<string>;
|
|
20
|
+
export declare function cgiRequest(value: unknown): SprinkleCgiRequest;
|
|
21
|
+
export declare function cgiRefusal(status: 403 | 404, text: string): SprinkleCgiReply;
|
|
22
|
+
export declare const cgiGuest = "A guest seat has no cgi-bin/.";
|
|
23
|
+
export declare const cgiReadOnly = "This sprinkle is read-only here, so its cgi-bin/ only answers GET and HEAD.";
|
|
24
|
+
export declare const cgiMissing = "This sprinkle has no cgi-bin/ here.";
|
|
19
25
|
export declare class SliccSprinkle extends ThemedElement {
|
|
20
26
|
#private;
|
|
21
27
|
static properties: {
|
|
@@ -2,6 +2,7 @@ import { Emitter } from '../model/emitter.js';
|
|
|
2
2
|
import type { FilePort, Sprinkle, SprinkleEvents, SprinkleMethod, SprinklePort } from '../model/types.js';
|
|
3
3
|
import type { DummyAgent } from './agent.js';
|
|
4
4
|
export declare function homePath(path: unknown): string;
|
|
5
|
+
export declare function cannedCgi(request: unknown): string;
|
|
5
6
|
export declare class DummySprinkles extends Emitter<SprinkleEvents> implements SprinklePort {
|
|
6
7
|
#private;
|
|
7
8
|
constructor(sprinkles: readonly Sprinkle[], agent: DummyAgent, files: FilePort);
|
|
@@ -655,7 +655,25 @@ export interface Sprinkle {
|
|
|
655
655
|
export interface SprinkleEvents {
|
|
656
656
|
sprinkles: readonly Sprinkle[];
|
|
657
657
|
}
|
|
658
|
-
export type SprinkleMethod = 'readFile' | 'exists' | 'getState' | 'setState';
|
|
658
|
+
export type SprinkleMethod = 'readFile' | 'exists' | 'getState' | 'setState' | 'cgi' | 'cgiRead' | 'cgiClose';
|
|
659
|
+
export type SprinkleCgiHeaders = Array<[string, string]>;
|
|
660
|
+
export interface SprinkleCgiRequest {
|
|
661
|
+
method: string;
|
|
662
|
+
path: string;
|
|
663
|
+
query: string;
|
|
664
|
+
headers: SprinkleCgiHeaders;
|
|
665
|
+
body: string | null;
|
|
666
|
+
}
|
|
667
|
+
export interface SprinkleCgiChunk {
|
|
668
|
+
body: string;
|
|
669
|
+
done: boolean;
|
|
670
|
+
}
|
|
671
|
+
export interface SprinkleCgiReply extends SprinkleCgiChunk {
|
|
672
|
+
status: number;
|
|
673
|
+
statusText: string;
|
|
674
|
+
headers: SprinkleCgiHeaders;
|
|
675
|
+
stream: string | null;
|
|
676
|
+
}
|
|
659
677
|
export interface SprinklePort extends Subscribable<SprinkleEvents> {
|
|
660
678
|
list(): readonly Sprinkle[];
|
|
661
679
|
send(id: string, payload: unknown): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-spectrum",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.111.0",
|
|
4
4
|
"description": "Web components for SLICC on Spectrum Web Components: the terminal, the app shell and its surfaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"@adobe/spectrum-wc": "2.0.0-beta.6",
|
|
64
64
|
"@adobe/spectrum-wc-icons": "2.0.0-beta.6",
|
|
65
65
|
"@ai-ecoverse/slicc-cdp": "1.45.0",
|
|
66
|
-
"@ai-ecoverse/slicc-kernel": "1.173.
|
|
66
|
+
"@ai-ecoverse/slicc-kernel": "1.173.3",
|
|
67
67
|
"@ai-ecoverse/slicc-shared-web": "2.13.10",
|
|
68
68
|
"@ai-ecoverse/slicc-vault": "1.21.2",
|
|
69
69
|
"@ai-ecoverse/wasm-bash": "5.3.0-23",
|