web-signature 0.2.8 → 0.2.9
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 +5 -0
- package/bundle/d/index.d.ts +21 -2
- package/bundle/index.js +15 -1
- package/bundle/index.min.js +1 -1
- package/dist/Plugin.js +0 -1
- package/dist/Signature.js +14 -0
- package/dist/d/Plugin.d.ts +8 -0
- package/dist/d/Signature.d.ts +6 -0
- package/dist/d/html.d.ts +6 -2
- package/dist/d/types/Component.d.ts +3 -0
- package/dist/html.js +13 -0
- package/package.json +1 -1
- package/src/Plugin.ts +8 -1
- package/src/Signature.ts +16 -1
- package/src/html.ts +25 -4
- package/src/types/Component.ts +4 -1
package/README.MD
CHANGED
|
@@ -31,12 +31,17 @@ npm run dev
|
|
|
31
31
|
|
|
32
32
|
* [Signature](#signature)
|
|
33
33
|
* [Quick Start](#quick-start)
|
|
34
|
+
* [Try online](#try-online)
|
|
34
35
|
* [Introduction](#introduction)
|
|
35
36
|
* [Briefly about Signature](#briefly-about-signature)
|
|
36
37
|
* [About Component](#about-component)
|
|
37
38
|
* [Quick about the Library](#quick-about-the-library)
|
|
38
39
|
* [See more here](#see-more-here)
|
|
39
40
|
|
|
41
|
+
## Try online
|
|
42
|
+
|
|
43
|
+
You can also try Signature online using [StackBlitz](https://stackblitz.com/fork/signature-starter)
|
|
44
|
+
|
|
40
45
|
# Introduction
|
|
41
46
|
|
|
42
47
|
Signature uses four classes as its basis:
|
package/bundle/d/index.d.ts
CHANGED
|
@@ -78,6 +78,9 @@ interface Component$1 {
|
|
|
78
78
|
* The properties of the component.
|
|
79
79
|
*/
|
|
80
80
|
data: Record<string, string | number | boolean | null>;
|
|
81
|
+
/**
|
|
82
|
+
* Plugins are stored here.
|
|
83
|
+
*/
|
|
81
84
|
$: Record<string, unknown>;
|
|
82
85
|
/**
|
|
83
86
|
* Returns the component as a string (template).
|
|
@@ -188,7 +191,15 @@ declare class Library {
|
|
|
188
191
|
}
|
|
189
192
|
|
|
190
193
|
declare abstract class Plugin {
|
|
194
|
+
/**
|
|
195
|
+
* Modules are mini plugins that are required for the plugin to work, they are processed and stored before the plugin itself is installed and stored in a safe place.
|
|
196
|
+
*/
|
|
191
197
|
readonly abstract modules: Record<string, () => Record<string, unknown>>;
|
|
198
|
+
/**
|
|
199
|
+
* The function returns an object that will be installed as a plugin in Signature.$
|
|
200
|
+
* @param modules
|
|
201
|
+
* @returns {Record<string, unknown>} The object that will be installed as a plugin
|
|
202
|
+
*/
|
|
192
203
|
abstract define(modules: Record<string, Record<string, unknown>>): Record<string, unknown>;
|
|
193
204
|
}
|
|
194
205
|
|
|
@@ -228,6 +239,12 @@ declare class Signature {
|
|
|
228
239
|
* @return {Record<string, ResolvedLib>} A object of formatted libraries with their components and dependencies.
|
|
229
240
|
*/
|
|
230
241
|
libraries(): Record<string, ResolvedLib>;
|
|
242
|
+
/**
|
|
243
|
+
* Registers a plugin in the signature.
|
|
244
|
+
* @import {Plugin} from "./Plugin.js";
|
|
245
|
+
* @param {string} name The name of the plugin.
|
|
246
|
+
* @param {Plugin} plugin The plugin to register.
|
|
247
|
+
*/
|
|
231
248
|
use(name: string, plugin: Plugin): void;
|
|
232
249
|
/**
|
|
233
250
|
* Contacts the Component.onContact method through its reference.
|
|
@@ -267,14 +284,16 @@ declare class Prop<T extends keyof TypesMap> implements Prop$1 {
|
|
|
267
284
|
isValid(value: TypesMap[keyof TypesMap]): boolean;
|
|
268
285
|
}
|
|
269
286
|
|
|
270
|
-
|
|
287
|
+
type HTMLTemplate = {
|
|
271
288
|
strings: TemplateStringsArray;
|
|
272
289
|
values: any[];
|
|
273
290
|
};
|
|
274
|
-
declare function
|
|
291
|
+
declare function html(strings: TemplateStringsArray, ...values: any[]): HTMLTemplate;
|
|
292
|
+
type unsafeHTMLTemplate = {
|
|
275
293
|
type: "unsafeHTML";
|
|
276
294
|
value: any;
|
|
277
295
|
};
|
|
296
|
+
declare function unsafeHTML(value: any): unsafeHTMLTemplate;
|
|
278
297
|
|
|
279
298
|
declare function export_default(): Signature;
|
|
280
299
|
|
package/bundle/index.js
CHANGED
|
@@ -101,6 +101,12 @@ class Signature {
|
|
|
101
101
|
};
|
|
102
102
|
return resolve(this.libs);
|
|
103
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Registers a plugin in the signature.
|
|
106
|
+
* @import {Plugin} from "./Plugin.js";
|
|
107
|
+
* @param {string} name The name of the plugin.
|
|
108
|
+
* @param {Plugin} plugin The plugin to register.
|
|
109
|
+
*/
|
|
104
110
|
use(name, plugin) {
|
|
105
111
|
if (this.$[name]) {
|
|
106
112
|
throw new Error(`Plugin with name ${name} already exists.`);
|
|
@@ -464,6 +470,14 @@ class Signature {
|
|
|
464
470
|
update: () => this.updateRef(refName)
|
|
465
471
|
};
|
|
466
472
|
}
|
|
473
|
+
// Copying another attributes from the original element to the new one, with exceptions
|
|
474
|
+
for (const attr of Array.from(el.attributes)) {
|
|
475
|
+
const name = attr.name;
|
|
476
|
+
if (renderer.props[name] !== undefined || name === "ref" || name === "si-component" || name === "si-group")
|
|
477
|
+
continue;
|
|
478
|
+
if (!mountEl.hasAttribute(name))
|
|
479
|
+
mountEl.setAttribute(name, attr.value);
|
|
480
|
+
}
|
|
467
481
|
el.replaceWith(body.firstElementChild);
|
|
468
482
|
renderer.onMount?.(mountEl); // lifecycle hook
|
|
469
483
|
});
|
|
@@ -619,8 +633,8 @@ function html(strings, ...values) {
|
|
|
619
633
|
function unsafeHTML(value) {
|
|
620
634
|
return { type: "unsafeHTML", value: value };
|
|
621
635
|
}
|
|
636
|
+
// todo: make a loop function
|
|
622
637
|
|
|
623
|
-
// todo: make description
|
|
624
638
|
class Plugin {
|
|
625
639
|
}
|
|
626
640
|
|
package/bundle/index.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class e{element;instance;constructor(e,t){this.instance=e,this.element=t}}const t={"element-not-found":"Element not found for selector: #selector","prop-is-required":"Property '#prop' in component '#component' is required but not provided.","unsupported-type-for-property":"Unsupported type for property '#prop' in component '#component': #type","invalid-value-for-property":"Invalid value for property '#prop' in component '#component': #value (value: #attr)","multiple-root-elements":"Component '#component' must render a single root element. \n\t#elements","ref-collision":"Ref collision detected for ref '#ref' in component '#component'.",unknown:"An unknown error occurred.","unknown-from":"An unknown error occurred in component '#from'.","stack-overflow":"Stack Overflow detected: possible recursive component rendering.","render-async-failed":"Error during asynchronous rendering of the component #component."};let n=0;class r{components={};refs={};libs={};bank=new Map;$={};$g={};constructor(){}add(e,t){const n="string"==typeof t?t:e.name;this.components[n]&&console.warn(new Error(`Component with name ${n} already exists.`)),this.components[n]=e}register(e,...t){this.libs[e.name]&&console.warn(new Error(`Library with name ${e.name} already exists.`));const n=e.list().filter(e=>!(e.name in t));this.libs[e.name]={name:e.name,version:e.version,author:e.author,components:n.map(e=>e.name),dependencies:e.libs};for(const t of n)this.add(t.component,`${e.name}-${t.name}`)}lib(e){return this.libs[e]}libraries(){const e=e=>{let t=e.name;return e.version&&(t+=`@${e.version}`),e.author&&(t+=`#${e.author}`),t},t=(n,r=new Set)=>{const o={};for(const[s,i]of Object.entries(n)){const n=e(i);r.has(n)||(r.add(n),o[n]={components:i.components,dependencies:t(i.dependencies,r)})}return o};return t(this.libs)}use(e,t){if(this.$[e])throw new Error(`Plugin with name ${e} already exists.`);let n={};Object.keys(t.modules).forEach(e=>{n[e]=t.modules[e]()}),this.$[e]={plugin:t.define(n),modules:n},this.$g[e]=this.$[e].plugin}contactWith(e,...t){const n=this.refs[e];if(!n)throw new Error(`Ref with name ${e} does not exist.`);const r=n.instance;return r.onContact?.(...t)}updateRef(e){const t=this.refs[e];if(!t)throw new Error(`Ref with name ${e} does not exist.`);const n=t.instance;let r={strings:Object.assign([],{raw:[]}),values:[]};try{r=n.render()}catch(e){if(e instanceof Error)throw{id:"unknown-from",from:n.name,err:e}}const o=document.createElement("template");(e=>{r instanceof Promise?r.then(t=>{o.content.appendChild(this.templateToElement(t,n.name)),e()}).catch(e=>{throw{id:"unknown-from",from:n.name,err:e}}):"object"==typeof r&&(o.content.appendChild(this.templateToElement(r,n.name)),e())})(()=>{if(1!==o.content.children.length)throw new Error(`Component '${n.name}' must render a single root element.`);const e=o.content.firstElementChild;let r=t.element.getAttribute("ref");r&&e.setAttribute("ref",r),n.groups.length>0&&e.setAttribute("si-group",n.groups.join(" ")),this.render(o.content),n.onRender?.(),t.element.replaceWith(e),t.element=e,n.onMount?.(e)})}contact(e,n){new Promise((t,r)=>{try{const t=document.querySelector(e);if(!t)return void r({id:"element-not-found",selector:e});const o=document.createElement("div");o.innerHTML=t.innerHTML,this.render(o),t.replaceChildren(...Array.from(o.childNodes)),n&&n()}catch(e){e instanceof Error?e instanceof RangeError&&e.message.includes("stack")?r({id:"stack-overflow",err:e}):r({id:"unknown",err:e}):r(e)}}).catch(e=>{let n=t[e.id];throw Object.keys(e).filter(e=>!(e in["id","err"])).forEach(t=>{n=n.replace(new RegExp(`#${t}`,"gm"),String(e[t]))}),window.SIGNATURE?.DEV_MODE&&console.log(e),e.id in["unknown","unknown-from","render-async-failed"]?console.error(`[${e.id}] ${n}`,e.err):console.error(`[${e.id}] ${n}`),"Page rendering was interrupted by Signature due to the above error."})}templateToString(e){let t="";for(let n=0;n<e.strings.length;n++)t+=e.strings[n],n<e.values.length&&(t+=`\x3c!--si-mark-${n}--\x3e`);return t}fillTemplate(e,t){let n;return this.bank.has(e.strings.join("@@"))?n=this.bank.get(e.strings.join("@@"))?.cloneNode(!0):(n=document.createElement("template"),n.innerHTML=t,this.bank.set(e.strings.join("@@"),n.cloneNode(!0))),(()=>{let t,r=document.createTreeWalker(n.content,NodeFilter.SHOW_COMMENT),o=[];for(;t=r.nextNode();)/si-mark-\d+/gm.test(t.nodeValue??"")&&o.push(t);for(const t of o){const n=e.values[Number((t.nodeValue??"").match(/si-mark-(\d+)/m)[1])];if("object"==typeof n&&"unsafeHTML"===n.type){let e=document.createElement("div");for(e.innerHTML=n.value;e.firstChild;)t.parentNode?.insertBefore(e.firstChild,t);t.remove()}else t.replaceWith(document.createTextNode(String(n)))}})(),(()=>{let t,r=document.createTreeWalker(n.content,NodeFilter.SHOW_ELEMENT);for(;t=r.nextNode();)for(const n of Array.from(t.attributes))if(/<!--si-mark-\d+-->/gm.test(n.value)){const r=n.value.match(/si-mark-(\d+)/m);if(r){const o=e.values[Number(r[1])];t.setAttribute(n.name,String(o))}}})(),n}templateToElement(e,t){const n=this.templateToString(e),r=this.fillTemplate(e,n);if(1!==r.content.children.length)throw{id:"multiple-root-elements",elements:r.innerHTML,component:t};return r.content.firstElementChild}render(t){for(const r of Object.keys(this.components)){const o=this.components[r];for(const s of Array.from(t.querySelectorAll(r)).concat(Array.from(t.querySelectorAll(`[si-component="${r}"]`)))){const t=new o;if(t.$=this.$g,Object.freeze(t.$),t.onInit?.(),s instanceof HTMLElement){t.content=s.innerHTML.trim();for(const e of Object.keys(t.props)){const n=s.getAttribute(e);if(null===n){if(t.props[e].required)throw{id:"prop-is-required",component:r,prop:e};t.data[e]=null}else if(""===n){if(t.props[e].required)throw{id:"prop-is-required",component:r,prop:e};t.props[e].isValid(n)&&(t.data[e]=null)}else{let o;switch(t.props[e].type){case"boolean":o=Boolean(n);break;case"number":o=Number(n);break;case"string":o=String(n);break;case"array":try{o=JSON.parse(n)}catch(t){throw{id:"invalid-value-for-property",component:r,prop:e,value:n,attr:n}}break;default:if(t.props[e].required)throw{id:"unsupported-type-for-property",component:r,prop:e,type:t.props[e].type}}if(void 0!==o){if(!t.props[e].isValid(o))throw{id:"invalid-value-for-property",component:r,prop:e,value:o,attr:n};if(t.props[e].validate&&!t.props[e].validate(o))throw{id:"invalid-value-for-property",component:r,prop:e,value:o,attr:n};t.data[e]=o,t.onPropParsed?.(t.props[e],o)}}}t.onPropsParsed?.()}const i=document.createElement("template");let a={strings:Object.assign([],{raw:[]}),values:[]};try{a=t.render()}catch(e){if(e instanceof Error)throw{id:"unknown-from",from:t.name,err:e}}(e=>{if(a instanceof Promise)try{a.then(t=>{i.appendChild(this.templateToElement(t,r)),e()}).catch(e=>{throw{id:"unknown-from",from:t.name,err:e}})}catch(e){throw{id:"render-async-failed",component:r,err:e}}else"object"==typeof a&&(i.appendChild(this.templateToElement(a,r)),e())})(()=>{this.render(i.content),t.onRender?.();const o=i.firstElementChild;if(t?.groups.length>0&&o.setAttribute("si-group",t.groups.join(" ")),s.hasAttribute("ref")||t.options.generateRefIfNotSpecified){let i=s.getAttribute("ref");if(null===i&&(i=""),n++,""===i&&(i=`r${n}${Math.random().toString(36).substring(2,15)}${n}`),this.refs[i])throw{id:"ref-collision",ref:i,component:r};this.refs[i]=new e(t,o),o.setAttribute("ref",i),t.ref={id:i,contact:(...e)=>this.contactWith(i,...e),update:()=>this.updateRef(i)}}s.replaceWith(i.firstElementChild),t.onMount?.(o)})}}}}class o{content;groups=[];options={generateRefIfNotSpecified:!1};ref;props={};data={};$={};onInit(){}onRender(){}onMount(e){}onContact(...e){}onPropsParsed(){}onPropParsed(e,t){}}class s{type;required=!0;validate;constructor(e,t=!0,n){this.type=e,this.required=t,this.validate=n||(()=>!0)}isValid(e){switch(this.type){case"boolean":return"boolean"==typeof e;case"number":return"number"==typeof e&&!isNaN(e);case"string":return"string"==typeof e;case"array":return Array.isArray(e);case"null":return null===e;default:return!1}}}class i{name;version;author;libs={};components={};constructor(e,t,n){this.name=e,this.author=t,this.version=n}add(e,t){const n="string"==typeof t?t:e.name;this.components[n]&&console.warn(new Error(`Component with name ${n} already exists.`)),this.components[n]=e}register(e,...t){this.libs[e.name]&&console.warn(new Error(`Library with name ${e.name} already exists in ${this.name}.`));const n=e.list().filter(e=>!(e.name in t));this.libs[e.name]={name:e.name,version:e.version,author:e.author,components:n.map(e=>e.name),dependencies:e.libs};for(const t of n)this.add(t.component,`${e.name}-${t.name}`)}get(e){return this.components[e]}lib(e){return this.libs[e]}list(){return Object.entries(this.components).map(([e,t])=>({component:t,name:e}))}}function a(e,...t){return{strings:e,values:t}}function c(e){return{type:"unsafeHTML",value:e}}class l{}function p(){return new r}export{o as Component,i as Library,l as Plugin,s as Prop,r as Signature,p as default,a as html,c as unsafeHTML};
|
|
1
|
+
class e{element;instance;constructor(e,t){this.instance=e,this.element=t}}const t={"element-not-found":"Element not found for selector: #selector","prop-is-required":"Property '#prop' in component '#component' is required but not provided.","unsupported-type-for-property":"Unsupported type for property '#prop' in component '#component': #type","invalid-value-for-property":"Invalid value for property '#prop' in component '#component': #value (value: #attr)","multiple-root-elements":"Component '#component' must render a single root element. \n\t#elements","ref-collision":"Ref collision detected for ref '#ref' in component '#component'.",unknown:"An unknown error occurred.","unknown-from":"An unknown error occurred in component '#from'.","stack-overflow":"Stack Overflow detected: possible recursive component rendering.","render-async-failed":"Error during asynchronous rendering of the component #component."};let n=0;class r{components={};refs={};libs={};bank=new Map;$={};$g={};constructor(){}add(e,t){const n="string"==typeof t?t:e.name;this.components[n]&&console.warn(new Error(`Component with name ${n} already exists.`)),this.components[n]=e}register(e,...t){this.libs[e.name]&&console.warn(new Error(`Library with name ${e.name} already exists.`));const n=e.list().filter(e=>!(e.name in t));this.libs[e.name]={name:e.name,version:e.version,author:e.author,components:n.map(e=>e.name),dependencies:e.libs};for(const t of n)this.add(t.component,`${e.name}-${t.name}`)}lib(e){return this.libs[e]}libraries(){const e=e=>{let t=e.name;return e.version&&(t+=`@${e.version}`),e.author&&(t+=`#${e.author}`),t},t=(n,r=new Set)=>{const o={};for(const[s,i]of Object.entries(n)){const n=e(i);r.has(n)||(r.add(n),o[n]={components:i.components,dependencies:t(i.dependencies,r)})}return o};return t(this.libs)}use(e,t){if(this.$[e])throw new Error(`Plugin with name ${e} already exists.`);let n={};Object.keys(t.modules).forEach(e=>{n[e]=t.modules[e]()}),this.$[e]={plugin:t.define(n),modules:n},this.$g[e]=this.$[e].plugin}contactWith(e,...t){const n=this.refs[e];if(!n)throw new Error(`Ref with name ${e} does not exist.`);const r=n.instance;return r.onContact?.(...t)}updateRef(e){const t=this.refs[e];if(!t)throw new Error(`Ref with name ${e} does not exist.`);const n=t.instance;let r={strings:Object.assign([],{raw:[]}),values:[]};try{r=n.render()}catch(e){if(e instanceof Error)throw{id:"unknown-from",from:n.name,err:e}}const o=document.createElement("template");(e=>{r instanceof Promise?r.then(t=>{o.content.appendChild(this.templateToElement(t,n.name)),e()}).catch(e=>{throw{id:"unknown-from",from:n.name,err:e}}):"object"==typeof r&&(o.content.appendChild(this.templateToElement(r,n.name)),e())})(()=>{if(1!==o.content.children.length)throw new Error(`Component '${n.name}' must render a single root element.`);const e=o.content.firstElementChild;let r=t.element.getAttribute("ref");r&&e.setAttribute("ref",r),n.groups.length>0&&e.setAttribute("si-group",n.groups.join(" ")),this.render(o.content),n.onRender?.(),t.element.replaceWith(e),t.element=e,n.onMount?.(e)})}contact(e,n){new Promise((t,r)=>{try{const t=document.querySelector(e);if(!t)return void r({id:"element-not-found",selector:e});const o=document.createElement("div");o.innerHTML=t.innerHTML,this.render(o),t.replaceChildren(...Array.from(o.childNodes)),n&&n()}catch(e){e instanceof Error?e instanceof RangeError&&e.message.includes("stack")?r({id:"stack-overflow",err:e}):r({id:"unknown",err:e}):r(e)}}).catch(e=>{let n=t[e.id];throw Object.keys(e).filter(e=>!(e in["id","err"])).forEach(t=>{n=n.replace(new RegExp(`#${t}`,"gm"),String(e[t]))}),window.SIGNATURE?.DEV_MODE&&console.log(e),e.id in["unknown","unknown-from","render-async-failed"]?console.error(`[${e.id}] ${n}`,e.err):console.error(`[${e.id}] ${n}`),"Page rendering was interrupted by Signature due to the above error."})}templateToString(e){let t="";for(let n=0;n<e.strings.length;n++)t+=e.strings[n],n<e.values.length&&(t+=`\x3c!--si-mark-${n}--\x3e`);return t}fillTemplate(e,t){let n;return this.bank.has(e.strings.join("@@"))?n=this.bank.get(e.strings.join("@@"))?.cloneNode(!0):(n=document.createElement("template"),n.innerHTML=t,this.bank.set(e.strings.join("@@"),n.cloneNode(!0))),(()=>{let t,r=document.createTreeWalker(n.content,NodeFilter.SHOW_COMMENT),o=[];for(;t=r.nextNode();)/si-mark-\d+/gm.test(t.nodeValue??"")&&o.push(t);for(const t of o){const n=e.values[Number((t.nodeValue??"").match(/si-mark-(\d+)/m)[1])];if("object"==typeof n&&"unsafeHTML"===n.type){let e=document.createElement("div");for(e.innerHTML=n.value;e.firstChild;)t.parentNode?.insertBefore(e.firstChild,t);t.remove()}else t.replaceWith(document.createTextNode(String(n)))}})(),(()=>{let t,r=document.createTreeWalker(n.content,NodeFilter.SHOW_ELEMENT);for(;t=r.nextNode();)for(const n of Array.from(t.attributes))if(/<!--si-mark-\d+-->/gm.test(n.value)){const r=n.value.match(/si-mark-(\d+)/m);if(r){const o=e.values[Number(r[1])];t.setAttribute(n.name,String(o))}}})(),n}templateToElement(e,t){const n=this.templateToString(e),r=this.fillTemplate(e,n);if(1!==r.content.children.length)throw{id:"multiple-root-elements",elements:r.innerHTML,component:t};return r.content.firstElementChild}render(t){for(const r of Object.keys(this.components)){const o=this.components[r];for(const s of Array.from(t.querySelectorAll(r)).concat(Array.from(t.querySelectorAll(`[si-component="${r}"]`)))){const t=new o;if(t.$=this.$g,Object.freeze(t.$),t.onInit?.(),s instanceof HTMLElement){t.content=s.innerHTML.trim();for(const e of Object.keys(t.props)){const n=s.getAttribute(e);if(null===n){if(t.props[e].required)throw{id:"prop-is-required",component:r,prop:e};t.data[e]=null}else if(""===n){if(t.props[e].required)throw{id:"prop-is-required",component:r,prop:e};t.props[e].isValid(n)&&(t.data[e]=null)}else{let o;switch(t.props[e].type){case"boolean":o=Boolean(n);break;case"number":o=Number(n);break;case"string":o=String(n);break;case"array":try{o=JSON.parse(n)}catch(t){throw{id:"invalid-value-for-property",component:r,prop:e,value:n,attr:n}}break;default:if(t.props[e].required)throw{id:"unsupported-type-for-property",component:r,prop:e,type:t.props[e].type}}if(void 0!==o){if(!t.props[e].isValid(o))throw{id:"invalid-value-for-property",component:r,prop:e,value:o,attr:n};if(t.props[e].validate&&!t.props[e].validate(o))throw{id:"invalid-value-for-property",component:r,prop:e,value:o,attr:n};t.data[e]=o,t.onPropParsed?.(t.props[e],o)}}}t.onPropsParsed?.()}const i=document.createElement("template");let a={strings:Object.assign([],{raw:[]}),values:[]};try{a=t.render()}catch(e){if(e instanceof Error)throw{id:"unknown-from",from:t.name,err:e}}(e=>{if(a instanceof Promise)try{a.then(t=>{i.appendChild(this.templateToElement(t,r)),e()}).catch(e=>{throw{id:"unknown-from",from:t.name,err:e}})}catch(e){throw{id:"render-async-failed",component:r,err:e}}else"object"==typeof a&&(i.appendChild(this.templateToElement(a,r)),e())})(()=>{this.render(i.content),t.onRender?.();const o=i.firstElementChild;if(t?.groups.length>0&&o.setAttribute("si-group",t.groups.join(" ")),s.hasAttribute("ref")||t.options.generateRefIfNotSpecified){let i=s.getAttribute("ref");if(null===i&&(i=""),n++,""===i&&(i=`r${n}${Math.random().toString(36).substring(2,15)}${n}`),this.refs[i])throw{id:"ref-collision",ref:i,component:r};this.refs[i]=new e(t,o),o.setAttribute("ref",i),t.ref={id:i,contact:(...e)=>this.contactWith(i,...e),update:()=>this.updateRef(i)}}for(const e of Array.from(s.attributes)){const n=e.name;void 0===t.props[n]&&"ref"!==n&&"si-component"!==n&&"si-group"!==n&&(o.hasAttribute(n)||o.setAttribute(n,e.value))}s.replaceWith(i.firstElementChild),t.onMount?.(o)})}}}}class o{content;groups=[];options={generateRefIfNotSpecified:!1};ref;props={};data={};$={};onInit(){}onRender(){}onMount(e){}onContact(...e){}onPropsParsed(){}onPropParsed(e,t){}}class s{type;required=!0;validate;constructor(e,t=!0,n){this.type=e,this.required=t,this.validate=n||(()=>!0)}isValid(e){switch(this.type){case"boolean":return"boolean"==typeof e;case"number":return"number"==typeof e&&!isNaN(e);case"string":return"string"==typeof e;case"array":return Array.isArray(e);case"null":return null===e;default:return!1}}}class i{name;version;author;libs={};components={};constructor(e,t,n){this.name=e,this.author=t,this.version=n}add(e,t){const n="string"==typeof t?t:e.name;this.components[n]&&console.warn(new Error(`Component with name ${n} already exists.`)),this.components[n]=e}register(e,...t){this.libs[e.name]&&console.warn(new Error(`Library with name ${e.name} already exists in ${this.name}.`));const n=e.list().filter(e=>!(e.name in t));this.libs[e.name]={name:e.name,version:e.version,author:e.author,components:n.map(e=>e.name),dependencies:e.libs};for(const t of n)this.add(t.component,`${e.name}-${t.name}`)}get(e){return this.components[e]}lib(e){return this.libs[e]}list(){return Object.entries(this.components).map(([e,t])=>({component:t,name:e}))}}function a(e,...t){return{strings:e,values:t}}function c(e){return{type:"unsafeHTML",value:e}}class l{}function p(){return new r}export{o as Component,i as Library,l as Plugin,s as Prop,r as Signature,p as default,a as html,c as unsafeHTML};
|
package/dist/Plugin.js
CHANGED
package/dist/Signature.js
CHANGED
|
@@ -81,6 +81,12 @@ export default class Signature {
|
|
|
81
81
|
};
|
|
82
82
|
return resolve(this.libs);
|
|
83
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Registers a plugin in the signature.
|
|
86
|
+
* @import {Plugin} from "./Plugin.js";
|
|
87
|
+
* @param {string} name The name of the plugin.
|
|
88
|
+
* @param {Plugin} plugin The plugin to register.
|
|
89
|
+
*/
|
|
84
90
|
use(name, plugin) {
|
|
85
91
|
if (this.$[name]) {
|
|
86
92
|
throw new Error(`Plugin with name ${name} already exists.`);
|
|
@@ -444,6 +450,14 @@ export default class Signature {
|
|
|
444
450
|
update: () => this.updateRef(refName)
|
|
445
451
|
};
|
|
446
452
|
}
|
|
453
|
+
// Copying another attributes from the original element to the new one, with exceptions
|
|
454
|
+
for (const attr of Array.from(el.attributes)) {
|
|
455
|
+
const name = attr.name;
|
|
456
|
+
if (renderer.props[name] !== undefined || name === "ref" || name === "si-component" || name === "si-group")
|
|
457
|
+
continue;
|
|
458
|
+
if (!mountEl.hasAttribute(name))
|
|
459
|
+
mountEl.setAttribute(name, attr.value);
|
|
460
|
+
}
|
|
447
461
|
el.replaceWith(body.firstElementChild);
|
|
448
462
|
renderer.onMount?.(mountEl); // lifecycle hook
|
|
449
463
|
});
|
package/dist/d/Plugin.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
export default abstract class Plugin {
|
|
2
|
+
/**
|
|
3
|
+
* Modules are mini plugins that are required for the plugin to work, they are processed and stored before the plugin itself is installed and stored in a safe place.
|
|
4
|
+
*/
|
|
2
5
|
readonly abstract modules: Record<string, () => Record<string, unknown>>;
|
|
6
|
+
/**
|
|
7
|
+
* The function returns an object that will be installed as a plugin in Signature.$
|
|
8
|
+
* @param modules
|
|
9
|
+
* @returns {Record<string, unknown>} The object that will be installed as a plugin
|
|
10
|
+
*/
|
|
3
11
|
abstract define(modules: Record<string, Record<string, unknown>>): Record<string, unknown>;
|
|
4
12
|
}
|
package/dist/d/Signature.d.ts
CHANGED
|
@@ -37,6 +37,12 @@ export default class Signature {
|
|
|
37
37
|
* @return {Record<string, ResolvedLib>} A object of formatted libraries with their components and dependencies.
|
|
38
38
|
*/
|
|
39
39
|
libraries(): Record<string, ResolvedLib>;
|
|
40
|
+
/**
|
|
41
|
+
* Registers a plugin in the signature.
|
|
42
|
+
* @import {Plugin} from "./Plugin.js";
|
|
43
|
+
* @param {string} name The name of the plugin.
|
|
44
|
+
* @param {Plugin} plugin The plugin to register.
|
|
45
|
+
*/
|
|
40
46
|
use(name: string, plugin: Plugin): void;
|
|
41
47
|
/**
|
|
42
48
|
* Contacts the Component.onContact method through its reference.
|
package/dist/d/html.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
type HTMLTemplate = {
|
|
2
2
|
strings: TemplateStringsArray;
|
|
3
3
|
values: any[];
|
|
4
4
|
};
|
|
5
|
-
export
|
|
5
|
+
export default function html(strings: TemplateStringsArray, ...values: any[]): HTMLTemplate;
|
|
6
|
+
type unsafeHTMLTemplate = {
|
|
6
7
|
type: "unsafeHTML";
|
|
7
8
|
value: any;
|
|
8
9
|
};
|
|
10
|
+
export declare function unsafeHTML(value: any): unsafeHTMLTemplate;
|
|
11
|
+
export declare function joinTemplates(...templates: HTMLTemplate[]): HTMLTemplate;
|
|
12
|
+
export {};
|
package/dist/html.js
CHANGED
|
@@ -4,3 +4,16 @@ export default function html(strings, ...values) {
|
|
|
4
4
|
export function unsafeHTML(value) {
|
|
5
5
|
return { type: "unsafeHTML", value: value };
|
|
6
6
|
}
|
|
7
|
+
export function joinTemplates(...templates) {
|
|
8
|
+
let strings = [];
|
|
9
|
+
let values = [];
|
|
10
|
+
templates.forEach((t) => {
|
|
11
|
+
strings.push(...t.strings);
|
|
12
|
+
values.push(...t.values);
|
|
13
|
+
});
|
|
14
|
+
return {
|
|
15
|
+
strings: strings,
|
|
16
|
+
values: values
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
// todo: make a loop function
|
package/package.json
CHANGED
package/src/Plugin.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
// todo: make description
|
|
2
1
|
export default abstract class Plugin {
|
|
2
|
+
/**
|
|
3
|
+
* Modules are mini plugins that are required for the plugin to work, they are processed and stored before the plugin itself is installed and stored in a safe place.
|
|
4
|
+
*/
|
|
3
5
|
readonly abstract modules: Record<string, () => Record<string, unknown>>;
|
|
4
6
|
|
|
7
|
+
/**
|
|
8
|
+
* The function returns an object that will be installed as a plugin in Signature.$
|
|
9
|
+
* @param modules
|
|
10
|
+
* @returns {Record<string, unknown>} The object that will be installed as a plugin
|
|
11
|
+
*/
|
|
5
12
|
public abstract define(modules: Record<string, Record<string, unknown>>): Record<string, unknown>;
|
|
6
13
|
}
|
package/src/Signature.ts
CHANGED
|
@@ -114,6 +114,12 @@ export default class Signature {
|
|
|
114
114
|
return resolve(this.libs);
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Registers a plugin in the signature.
|
|
119
|
+
* @import {Plugin} from "./Plugin.js";
|
|
120
|
+
* @param {string} name The name of the plugin.
|
|
121
|
+
* @param {Plugin} plugin The plugin to register.
|
|
122
|
+
*/
|
|
117
123
|
public use(name: string, plugin: Plugin): void {
|
|
118
124
|
if (this.$[name]) {
|
|
119
125
|
throw new Error(`Plugin with name ${name} already exists.`);
|
|
@@ -379,7 +385,7 @@ export default class Signature {
|
|
|
379
385
|
|
|
380
386
|
renderer.$ = this.$g; // injecting plugins
|
|
381
387
|
Object.freeze(renderer.$); // prevent plugins from being modified by components
|
|
382
|
-
|
|
388
|
+
|
|
383
389
|
renderer.onInit?.(); // lifecycle hook
|
|
384
390
|
|
|
385
391
|
if (el instanceof HTMLElement) {
|
|
@@ -550,6 +556,15 @@ export default class Signature {
|
|
|
550
556
|
};
|
|
551
557
|
}
|
|
552
558
|
|
|
559
|
+
// Copying another attributes from the original element to the new one, with exceptions
|
|
560
|
+
for (const attr of Array.from(el.attributes)) {
|
|
561
|
+
const name: string = attr.name;
|
|
562
|
+
|
|
563
|
+
if (renderer.props[name] !== undefined || name === "ref" || name === "si-component" || name === "si-group") continue;
|
|
564
|
+
|
|
565
|
+
if (!mountEl.hasAttribute(name)) mountEl.setAttribute(name, attr.value);
|
|
566
|
+
}
|
|
567
|
+
|
|
553
568
|
el.replaceWith(body.firstElementChild as Element);
|
|
554
569
|
|
|
555
570
|
renderer.onMount?.(mountEl); // lifecycle hook
|
package/src/html.ts
CHANGED
|
@@ -1,10 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
type HTMLTemplate = {
|
|
2
2
|
strings: TemplateStringsArray,
|
|
3
3
|
values: any[]
|
|
4
|
-
}
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export default function html(strings: TemplateStringsArray, ...values: any[]): HTMLTemplate {
|
|
5
7
|
return {strings, values};
|
|
6
8
|
}
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
type unsafeHTMLTemplate = { type: "unsafeHTML", value: any };
|
|
11
|
+
|
|
12
|
+
export function unsafeHTML(value: any): unsafeHTMLTemplate {
|
|
9
13
|
return {type: "unsafeHTML", value: value};
|
|
10
|
-
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function joinTemplates(...templates: HTMLTemplate[]): HTMLTemplate {
|
|
17
|
+
let strings: string[] = [];
|
|
18
|
+
let values: any[] = [];
|
|
19
|
+
|
|
20
|
+
templates.forEach((t) => {
|
|
21
|
+
strings.push(...t.strings);
|
|
22
|
+
values.push(...t.values);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
strings: strings as unknown as TemplateStringsArray,
|
|
27
|
+
values: values
|
|
28
|
+
} as HTMLTemplate;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// todo: make a loop function
|
package/src/types/Component.ts
CHANGED