arrmatura 6.3.2 → 6.5.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 +59 -25
- package/dist/index.cjs +4 -0
- package/dist/index.js +4 -2
- package/docs/architecture.md +151 -0
- package/docs/built-ins.md +223 -0
- package/docs/cml.md +342 -0
- package/index.ts +1 -22
- package/package.json +18 -16
- package/src/{registry → compiler}/index.ts +23 -22
- package/src/controls/Iterative.ts +127 -0
- package/src/controls/block.ts +25 -0
- package/src/{registry → controls}/composition.ts +9 -15
- package/src/controls/conditionals.ts +79 -0
- package/src/controls/connector.ts +75 -0
- package/src/{registry → controls}/elementary.ts +3 -6
- package/src/{registry → controls}/fragment.ts +3 -4
- package/src/controls/index.ts +10 -0
- package/src/controls/root.ts +47 -0
- package/src/controls/routing.ts +45 -0
- package/src/{registry → controls}/selection.ts +4 -9
- package/src/{registry → controls}/slot.ts +12 -10
- package/src/core/Arrmatron.ts +648 -411
- package/src/core/Component.ts +108 -53
- package/src/core/ManifestNode.ts +295 -141
- package/src/core/NativeElement.ts +89 -0
- package/src/core/Platform.ts +116 -0
- package/src/core/Registry.ts +162 -0
- package/src/core/consts.ts +3 -0
- package/src/core/launch.ts +18 -0
- package/src/expr/Expression.ts +59 -0
- package/src/expr/ExpressionParser.ts +216 -0
- package/src/expr/ExpressionParserBase.ts +120 -0
- package/src/expr/ParserContext.ts +17 -0
- package/src/expr/compileEmitterExpression.ts +54 -0
- package/src/expr/compilePlaceholder.ts +14 -0
- package/src/expr/operations.ts +53 -0
- package/src/expr/prepareConnectedProps.ts +16 -0
- package/src/expr/resolveExpression.ts +66 -0
- package/src/index.ts +8 -0
- package/src/types.ts +168 -0
- package/src/utils/applyStateChangedToImpl.ts +2 -9
- package/src/utils/applyTemplate.ts +20 -0
- package/src/utils/asyncValueCall.ts +11 -0
- package/src/utils/capitalize.ts +7 -0
- package/src/utils/createRegisterTypes.ts +67 -0
- package/src/utils/defineCalculatedProperty.ts +48 -0
- package/src/utils/defineObjectRef.ts +18 -0
- package/src/utils/hashCodeOf.ts +147 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/isEquals.ts +74 -0
- package/src/utils/mapEntries.ts +9 -0
- package/src/utils/mergeObject.ts +25 -0
- package/src/utils/narrowData.ts +30 -0
- package/src/utils/scalarParse.ts +41 -0
- package/src/utils/splitTopLevel.ts +28 -0
- package/src/utils/stringify.ts +4 -3
- package/src/utils/toNativeTree.ts +21 -0
- package/src/utils/xmlParse.ts +120 -0
- package/dist/index.js.map +0 -7
- package/docs/glossary.md +0 -19
- package/docs/hello.md +0 -46
- package/docs/manual.md +0 -312
- package/src/core/resolveExpression.ts +0 -25
- package/src/registry/conditionals.ts +0 -77
- package/src/registry/connector.ts +0 -47
- package/src/registry/iterations.ts +0 -134
- package/src/registry/root.ts +0 -48
- package/src/registry/routing.ts +0 -32
- package/src/utils/FingerprintMashine.ts +0 -128
- package/src/utils/compileExpression.ts +0 -215
- package/src/utils/objectFingerprint.spec.ts +0 -70
- package/types.ts +0 -82
package/README.md
CHANGED
|
@@ -1,41 +1,75 @@
|
|
|
1
1
|
# Arrmatura
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## What is Arrmatura?
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Arrmatura** is a lightweight framework designed to facilitate the creation of applications by allowing developers to compose components and to specify how they are interconnected with data.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
This component composition is achieved through a declarative syntax,
|
|
8
|
+
which describes how data flows between components and how it is propagated across the composition.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
- type system and runtime enabling development of applications of any kind.
|
|
11
|
-
- `IPlatform` implementation for web client applications.
|
|
12
|
-
- Web UI kits with plenty of components, services, forms, editors etc.
|
|
10
|
+
This streamlines the development process and makes it easier for developers to create complex and dynamic applications that can respond to changes in data in real-time.
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
Overall, the framework aims to provide a flexible and intuitive way
|
|
13
|
+
to build web applications that are scalable, maintainable, and easy to use.
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
by allowing developers to define components and specify how they are composed and connected.
|
|
15
|
+
> Arrmatura is ideal for developers seeking simplicity and power in building applications.
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
which describes how data flows between components and how it is propagated across the composition.
|
|
17
|
+
## Key features
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
to create complex and dynamic applications that can respond to changes in data in real-time.
|
|
19
|
+
### Declarative Component Composition with Reactive data flow
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
to build web applications that are scalable, maintainable, and responsive.
|
|
21
|
+
Define reusable components using pure declarative **CML(Component Markup Language) notation** syntax.
|
|
27
22
|
|
|
28
|
-
|
|
23
|
+
Arrmatura allows you to write complex logic directly in your templates without the typical boilerplate of "hooks" or "state
|
|
24
|
+
management" libraries:
|
|
25
|
+
|
|
26
|
+
- Inline Actions: click="-> count = count + 1"
|
|
27
|
+
- Pipes: {@api.data | upper | slice:0:10}
|
|
28
|
+
- Reactive References: Using @ref allows components to communicate effortlessly (e.g., `<Consumer data="{@api.result}" />`).
|
|
29
|
+
|
|
30
|
+
### AI-Friendly Design
|
|
31
|
+
|
|
32
|
+
The framework is built from the ground up to be "AI-friendly".
|
|
33
|
+
Its declarative CML syntax is specifically designed to be easily generated, read, and modified by Large Language Models (LLMs).
|
|
34
|
+
|
|
35
|
+
By treating the application definition as a clear specification (XML-like templates), it bridges the gap between human requirements and executable code.
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
- [Glossary](docs/glossary.md)
|
|
37
|
+
Arrmatura is exciting because it feels like a glimpse into a future where code is written for both humans and AI, stripped of unnecessary complexity, and focused on pure architectural elegance.
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
### Performance
|
|
34
40
|
|
|
35
|
-
|
|
41
|
+
What Makes It Fast
|
|
36
42
|
|
|
37
|
-
|
|
43
|
+
1. **No Virtual DOM**: Direct DOM updates, no diffing overhead
|
|
44
|
+
2. **Cached Expressions**: Expressions compiled once, reused
|
|
45
|
+
3. **Selective Updates**: Only changed components redraw
|
|
46
|
+
4. **Lazy Property Resolution**: Properties resolved on-demand
|
|
47
|
+
5. **Manifest Node Caching**: Template compilation cached
|
|
48
|
+
|
|
49
|
+
Unlike React, Arrmatura rejects the Virtual DOM diffing process. Instead, it uses a direct-update mechanism.
|
|
50
|
+
|
|
51
|
+
- No VDOM overhead: It doesn't need to rebuild a virtual tree on every change.
|
|
52
|
+
- Selective Redraws: It tracks dependencies and updates only the specific parts of the real DOM that need to change.
|
|
53
|
+
- Runtime Interpretation: The "Runtime Engine" evaluates templates at runtime, allowing for dynamic component composition that is often faster and lighter than complex build-time transpilation.
|
|
54
|
+
|
|
55
|
+
### Unopinionated
|
|
56
|
+
|
|
57
|
+
Arrmatura doesn't force you into a specific architectural pattern.
|
|
58
|
+
|
|
59
|
+
- Flexible State Management: You can choose to manage state locally within components or use external stores without any framework-imposed structure.
|
|
60
|
+
- Pluggable Ecosystem: It can integrate with various libraries and tools for routing, data fetching, and more, without being tied to a specific way of doing things.
|
|
61
|
+
- Component Autonomy: Each component is an independent unit that can manage its own state and logic, making it easy to reuse and compose without worrying about global state or context.
|
|
62
|
+
|
|
63
|
+
### Extreme Minimalism
|
|
64
|
+
|
|
65
|
+
It strips away the "toolchain bloat" of modern JavaScript.
|
|
66
|
+
|
|
67
|
+
- Lightweight Runtime: The core engine is small and efficient.
|
|
68
|
+
- Platform Abstraction: It separates logic from the DOM, meaning the "Soul" (Arrmatura logic) can theoretically be ported to other "Bodies" (Native, Console, etc.).
|
|
69
|
+
- "Excellence through simplicity,": focusing on doing more with less code.
|
|
70
|
+
|
|
71
|
+
## Documentation
|
|
38
72
|
|
|
39
|
-
- [
|
|
40
|
-
- [
|
|
41
|
-
-
|
|
73
|
+
- the runtime model [architecture.md](./architecture.md).
|
|
74
|
+
- the CML syntax reference [cml.md](./cml.md);
|
|
75
|
+
- the semantics of each built-in element [built-ins.md](./built-ins.md);
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";var G=Object.defineProperty;var ne=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var oe=Object.prototype.hasOwnProperty;var i=(r,t)=>G(r,"name",{value:t,configurable:!0});var Tt=(r,t)=>{for(var e in t)G(r,e,{get:t[e],enumerable:!0})},ie=(r,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of se(t))!oe.call(r,s)&&s!==e&&G(r,s,{get:()=>t[s],enumerable:!(n=ne(t,s))||n.enumerable});return r};var ae=r=>ie(G({},"__esModule",{value:!0}),r);var Ye={};Tt(Ye,{CRootNode:()=>$,Component:()=>A,Platform:()=>q,applyTemplate:()=>Ke,compileManifestNode:()=>tt,compileManifestNodes:()=>et,createRegisterTypes:()=>Rt,launch:()=>Be});module.exports=ae(Ye);function bt(r,t){t.__stateChanged?t.__stateChanged(r):r.forEach((e,n)=>{t[n]=e})}i(bt,"applyStateChangedToImpl");var Ot=i(r=>typeof r=="object"?Array.isArray(r)?r.length?`[${Ot(r[0])??""} x${String(r.length)}]`:"[]":`{${Object.keys(r).toString()}}`:r??"","attributesToString"),pe=i(r=>{if(!r)return"";let t=[];return Object.entries(r).forEach(([e,n])=>{n!=null&&e[0]!=="$"&&t.push(` ${e}="${Ot(n)}"`)}),t.length?t.join(""):""},"stringifyState"),ot=i((r,t="")=>{let{uid:e,displayName:n=e,$component:s,children:o}=r,a=o?.size?[...o.values()].map(p=>ot(p,` ${t}`)).join(`
|
|
2
|
+
`):"";return`${t}<${n}${pe(s)}${a?`>
|
|
3
|
+
${a}
|
|
4
|
+
${t}</${n}>`:"/>"}`},"stringify");var ft={};Tt(ft,{HASH_SYMBOL:()=>y,asyncValueCall:()=>_,capitalize:()=>K,createStringInterpolator:()=>it,defineObjectHashCodeProperty:()=>P,defineObjectRef:()=>at,hashCodeOf:()=>C,isEquals:()=>w,mapEntries:()=>I,mergeObject:()=>b,scalarParse:()=>O,stringHashCode:()=>h,xmlParse:()=>D});function _(r,t){return r instanceof Promise?r.then(t):t(r)}i(_,"asyncValueCall");var ce=i(r=>r==null?"":String(r),"str");function K(r){let t=ce(r);return t.length?t[0].toUpperCase()+t.slice(1):""}i(K,"capitalize");var fe=i(r=>r==null?"":String(r),"str"),le=/\{([^}]+)\}/g,Dt="{$$$}";function it(r,t){let e=[],n=r.replace(le,(a,p)=>(e.push(t(p.trim())),Dt));if(!e.length)return()=>n;let s=n.split(Dt),o=s.pop();return(...a)=>s.map((p,c)=>`${p}${fe(e[c](...a))}`).join("")+o}i(it,"createStringInterpolator");function at(r,t,e){return Object.defineProperty(r,t,{get(){return e},enumerable:!1,configurable:!1}),r}i(at,"defineObjectRef");var E=i(()=>Math.floor((1+Math.random())*65536).toString(16).substring(1),"s4"),me=i(()=>`${E()}${E()}-${E()}-${E()}-${E()}-${E()}${E()}${E()}`,"guid"),y=Symbol("HASH_SYMBOL"),Xt=new Map([["",pt("__empty__")]]),kt=new Map([[void 0,h("__undefined__")],[null,h("__null__")],["",h("__empty__")],[NaN,h("__NaN__")],[!1,h("__false__")],[!0,h("__true__")]]),x={Object:h("__Object__"),Date:h("__Date__"),Array:h("__Array__"),Map:h("__Map__"),Set:h("__Set__")};function pt(r){let t=-2128831035;for(let e=0;e<r.length;e++)t^=r.charCodeAt(e),t=Math.imul(t,16777619);return t|0}i(pt,"__stringHashCode");function g(r,t){return Math.imul(t^r,16777619)|0}i(g,"numberHashCode");function h(r){let t=Xt.get(r);if(t)return t;let e=pt(r);return Xt.set(r,e),e}i(h,"stringHashCode");function P(r,t){if(!r||Object.hasOwn(r,y))return r;let e=t??pt(me());return Object.defineProperty(r,y,{get(){return e},configurable:!1,enumerable:!1}),r}i(P,"defineObjectHashCodeProperty");function ue(r,t){if(t>10)return-1;let e=t+1,n=0;if(r instanceof Map){n=g(x.Map,n);for(let[s,o]of r)n=g(h(s),n),n=g(x.Map,n),n=g(C(o,e),n)}else if(r instanceof Set){n=g(x.Set,n);for(let s of r)n=g(C(s,e),n)}else if(Array.isArray(r)){n=g(x.Array,n);for(let s of r)n=g(C(s,e),n)}else{n=g(x.Object,n);for(let s in r)Object.hasOwn(r,s)&&s[0]!=="$"&&(n=g(h(s),n),n=g(x.Object,n),n=g(C(r[s],e),n))}return n}i(ue,"containerHashCode");var C=i((r,t=0)=>kt.has(r)?kt.get(r):typeof r=="string"?h(r):typeof r=="number"?r:typeof r=="bigint"?h(r.toString(16)):typeof r=="symbol"?h(r.description??r.toString()):typeof r=="function"?P(r)[y]:y in r?r[y]:r instanceof Date?g(r.getTime(),x.Date):r instanceof Promise?P(r)[y]:ue(r,t),"hashCodeOf");function w(r,t,e=0){if(Number.isNaN(r))return!1;if(r===null||typeof r!="object")return r===t;if(t===null||typeof t!="object")return!1;if(y in r&&y in t)return r[y]===t[y];if(e>10)return!0;let n=e+1;if(Array.isArray(r)){if(!Array.isArray(t)||r.length!==t.length)return!1;for(let o=0;o<r.length;o++)if(!w(r[o],t[o],n))return!1;return!0}if(r instanceof Map){if(!(t instanceof Map)||r.size!==t.size)return!1;for(let[o,a]of r){let p=t.get(o);if(p===void 0&&!t.has(o)||!w(a,p,n))return!1}return!0}if(r instanceof Set){if(!(t instanceof Set)||r.size!==t.size)return!1;for(let o of r)if(!t.has(o))return!1;return!0}if(Array.isArray(t)||t instanceof Map||t instanceof Set)return!1;if(r instanceof Date||t instanceof Date)return r instanceof Date&&t instanceof Date&&r.getTime()===t.getTime();let s=0;for(let o in r)if(!(o[0]==="$"||!Object.hasOwn(r,o))&&(s++,!Object.hasOwn(t,o)||!w(r[o],t[o],n)))return!1;for(let o in t)if(o[0]!=="$"&&Object.hasOwn(t,o)&&--s<0)return!1;return s===0}i(w,"isEquals");var he=i((r,t)=>({id:r,value:t}),"DEFAULT_ENTRY_HANDLER"),I=i((r,t=he)=>r?Object.entries(r).map(([e,n])=>t(e,n)):[],"mapEntries");var b=i((r,t)=>{if(!r||typeof r!="object")return t;if(!t||typeof t!="object")return r;for(let[e,n]of Object.entries(t))typeof n=="object"&&typeof r[e]=="object"?Array.isArray(r[e])?r[e]=n:r[e]=b(r[e],n):r[e]=n;return r},"mergeObject");var O=i(r=>{if(r==="")return"";if(r==="true")return!0;if(r==="false")return!1;if(r==="0")return 0;if(r==="1")return 1;if(r&&"1234567890+-".includes(r[0])&&r.length<=17){let t=+r;return Number.isNaN(t)?r:t}if(r==="null")return null;if(r!=="undefined")return r},"scalarParse");var de=/&#?[0-9a-zA-Z]{2,5};/g,ge={amp:"&",gt:">",lt:"<",quot:'"',nbsp:" "},ye=i(r=>{let t=r.slice(1,-1);if(t[0]!=="#")return ge[t]||" ";let e=t.slice(1),n=e[0]==="x"||e[0]==="X"?parseInt(e.slice(1),16):parseInt(e,10);return Number.isFinite(n)?String.fromCharCode(n):" "},"FN_XML_ENTITY"),Ft=i(r=>String(r??"").replaceAll(de,ye),"decodeXmlEntities"),Ce=i((r,t='"',e=t)=>r[0]===t&&r[r.length-1]===e?r.slice(1,-1):r,"skipQuotes"),ct=/([a-zA-Z][a-zA-Z0-9-:$]*)(="[^"]*")?/g,Ht=/^\s*$/,_e=/<!--((?!-->)[\s\S])*-->/g,Y=/(<)(\/?)([a-z][a-z0-9\-_:.]*)((?:\s+[a-zA-Z][a-z0-9-:$]*(?:="[^"]*")?)*)\s*(\/?)>/gi,Ne={img:1,input:1,br:1,hr:1,col:1,source:1},Ae="Text",jt=i((r,t,e)=>{let n={tag:t,id:e};return(r.nodes??(r.nodes=[])).push(n),n},"addNode"),Ee=i((r,t)=>{if(t){r.attrs={},ct.lastIndex=0;for(let e=ct.exec(t);e;e=ct.exec(t)){let n=e[2]?O(Ft(Ce(e[2].slice(1)))):!0;r.attrs[e[1]]=n}}},"parseAttrs"),D=i(r=>{let t=0,e=[{tag:"#root",id:String(t)}],n=String(r).trim().replace(_e,""),s=0;Y.lastIndex=0;for(let o=Y.exec(n);o;o=Y.exec(n)){let a=o.index&&n.slice(s,o.index);if(o[2]){if(a&&!e[0].nodes?.length&&(a===" "||!a.match(Ht))&&(e[0].text=Ft(a.trim())),e[0].tag!==o[3])throw new Error(` XML Parse closing tag does not match at: ${String(o.index)} near ${o.input.slice(Math.max(o.index-150,0),o.index)}^^^^${o.input.slice(o.index,Math.min(o.index+150,o.input.length))}`);e.shift()}else{if(a&&!a.match(Ht)){let c=jt(e[0],Ae,`T${String(++t)}`);c.attrs={text:a}}let p=jt(e[0],o[3],`X${String(++t)}`);if(Ee(p,o[4].trim()),!(o[5]||o[3]in Ne)&&(e.unshift(p),e.length===1))throw new Error(`Parse error at: ${o[0]}`)}s=Y.lastIndex}return e[0].nodes??[]},"xmlParse");function vt(r,t,e,n){let s,o,a=0;Object.defineProperty(r,t,{get(){let p=n?.length?n.map(l=>r.get(l)):[],c=p.some(l=>l instanceof Promise),f=i(l=>{let N=l.map(d=>C(d));return(!s||N.some((d,T)=>d!==s[T]))&&(s=N,o=e.apply(r,l)),o},"functor");return c?(a++,new Promise((l,N)=>{Promise.all(p.map(d=>d instanceof Promise?d:Promise.resolve(d))).then(f).then((d=>T=>{d===a&&l(T)})(a)).catch(d=>{N(d)})})):f(p)}})}i(vt,"defineCalculatedProperty");var Z="$$$ARRMATURA";var A=class{static{i(this,"Component")}name;get $$(){return this[Z]}get $uid(){return this.$$.uid}get $parentComponent(){return this.$$.parent?.$component}get refId(){return this.$$.refId}get platform(){return this.$$.platform}__init(){}get(t){return this.$$.get(t)}up(t){return this.$$.up(t)}touch(){return this.$$.touch()}getComponentByRef(t){return this.$$.getByRef(t)?.$component}emit(t,e={}){return this.$$.emit(t,e)}subscribeTo(t,e){return this.$$.subscribeTo(t,e)}defer(t){this.$$.defer(t)}__defineCalculatedProperty(t,e,n){vt(this,t,e,n)}__defineCalculatedProperties(t){Object.entries(t).forEach(([e,n])=>{let[s,o]=e.split("("),a=o?.slice(0,-1).split(",").map(p=>p.trim());this.__defineCalculatedProperty(s,n,a)})}log(t,...e){return this.$$.log(t,...e),t}logError(t,...e){return this.$$.logError(t,...e),t}toString(){return`${this.$$.toString()}${this.name?`(${this.name})`:""}`}};var X="outer$",Lt=new Map,$e=[],lt=0,m=class{constructor(t,e,n,s){this.platform=t;this.manifest=e;this.__parent=n;P(this),this.scope=s??this,this.root=s?.root??this;let o=this.createComponent();P(o),at(o,Z,this),this.$component=o,this.refId&&this.scope.addReference(this.refId,this)}platform;manifest;__parent;static{i(this,"Arrmatron")}$component;root;scope;__children;__propCache;__localScope;__isDone=!1;__isInited=!1;__fprints={};__listeners;__defered=[];__propFnMap;#t;#e=10;#r;get parent(){return this.__parent}get uid(){return this.manifest.uid}get hashCode(){return C(this)}get refId(){return this.manifest.refId}get displayName(){return`\u{1F539}${this.manifest.tag}`}createComponent(){return new A}up(t,e=!1){if(!t||this.__isDone)return;if(this.#r){Object.assign(this.#r,t);return}if(t instanceof Promise){this.platform.applyAsyncValue(`${this.hashCode}:set`,t,s=>this.up(s));return}let n=new Map;Object.entries(t).forEach(([s,o])=>{if(o instanceof Promise){let a=!s||s.startsWith("...");this.platform.applyAsyncValue(`${this.hashCode}:set:${s}`,o,p=>{this.up(a?p:{[s]:p})});return}!s||s[0]==="$"||(!(s in this.__fprints)||!w(this.__fprints[s],o))&&(this.__fprints[s]=o,n.set(s,o),this.__propCache?.delete(s))}),(n.size||e)&&(bt(n,this.$component),this.#e&&(this.#e--,this.touch(),this.#e++))}get(t){if(!t)return null;let e,n;if(t.indexOf(".")===-1)e=t,n=$e;else{let l=Lt.get(t);l||(l=t.split("."),Lt.set(t,l)),[e,...n]=l}let s=n.length===0;if(s){if(this.__propCache?.has(t))return this.__propCache.get(t)}else this.log("ERROR: Nested key",t);let o=this.__propFnMap??(this.__propFnMap=new Map);if(o.has(t)){let l=o.get(t)();return s&&(this.__propCache??(this.__propCache=new Map)).set(t,l),l}let a=null,p=this.$component,c=p[t];if(c&&typeof c=="function"){let l=c.bind(p);a=i(()=>l,"fn")}else if(t==="This")a=i(()=>this.$component,"fn");else if(e==="R"){let l=this.platform.getResource(n)??null;a=i(()=>l,"fn")}else if(`get${K(e)}`in p){let l=p[`get${K(e)}`],N=typeof l=="function"?()=>l.call(p)??null:()=>p[e]??null;a=n.length?()=>n.reduce((d,T)=>d?.[T]??null,N()):N}else if(p.__getStateProperty)a=i(()=>p.__getStateProperty?.(t),"fn");else{let l=i(()=>p[e]??null,"fn0");a=n.length?()=>n.reduce((N,d)=>N?.[d]??null,l()):l}o.set(t,a);let f=a();return s&&(this.__propCache??(this.__propCache=new Map)).set(t,f),f}putInLocalScope(t,e){(this.__localScope??(this.__localScope=new Map)).set(t,e)}getFromScope(t){return t.startsWith(X)?this.__localScope?.get(t):this.scope.get(t)}notify(){this.__listeners?.forEach(t=>{try{t(this)}catch(e){this.logError("Notification:",e)}})}addListener(t){this.__listeners??=new Set;let e=this.__listeners;return e.add(t),()=>{e.delete(t)}}subscribeTo(t,e){let n=typeof t=="string"?this.getByRef(t):t;if(!n)throw new Error(`No such reference: ${t}`);this.defer(n.addListener(e))}emit(t,...e){if(!this.__isDone)try{if(t.endsWith(")")){let[n,s]=t.split("(")[0].split(".");s||(s=n,n="This");let o=this.getByRef(n);if(!o)throw new Error(`No such reference: ${n}`);let a=o.$component,p=a[s];if(typeof p!="function")throw new Error(`Not a method: ${n}.${s}()`);return e.length>1?p.apply(a,e):this.platform.applyAsyncValue(`${this.hashCode}:emit:${t}`,e[0],c=>p.call(a,c))}else{let n=e[0],[s,o]=t.split(".");o||(o=s||"*",s="this");let a=this.getByRef(s);if(!a)throw new Error(`No such reference: ${s}`);return a.up(o==="*"?n:{[o]:n})}}catch(n){this.logError(`emit ${t}:`,n)}}touch(){lt++;try{this.__propCache?.clear();let t=this.__isDone?null:this.contentManifests;if(t?.size||this.__children?.size)if(this.__children?.forEach(e=>{t?.has(e.uid)||e.done()}),t?.size){let e=this.__children;this.__children=new Map,t.forEach((n,s)=>{let o=e?.get(s),a=o&&!o?.__isDone?o:n.createArrmatron(this.platform,this,this.scopeForChildren);this.__children?.set(a.uid,a)});for(let n of this.__children.values())n.settle()}else this.__children=this.__children?.size===0?this.__children:new Map;this.__isDone?(this.__defered?.forEach(e=>e(this)),this.__defered=void 0,this.__parent=void 0,this.refId&&this.scope.#t&&delete this.scope.#t[this.refId],this.__listeners=void 0,this.__propFnMap=void 0,this.__propCache=void 0,this.__localScope=void 0):this.notify()}finally{lt--,lt||this.platform.redraw(this,this.root)}}done(){this.__isDone=!0,this.touch()}settle(){if(!this.__isDone)if(this.__isInited){let t=this.manifest.resolveProps(this);this.up(t,!!this.children?.size)}else{if(this.__isInited=!0,this.#r=this.manifest.resolveInitialProps(this),this.manifest.connectors)for(let[e,n]of this.manifest.connectors.entries()){let[s,o]=e.split("."),a=this.parent?.getByRef(s);if(!a){this.logError(`Connect: No such ref: ${s}`);continue}this.defer(a.addListener(()=>{this.platform.applyAsyncValue(`${this.hashCode}:connect:${e}`,a.get(o),p=>n(this,p))})),this.platform.applyAsyncValue(`${this.hashCode}:connect:${e}`,a.get(o),p=>n(this,p))}let t=this.#r;this.#r=null,this.up(t,!0),this.$component.__init?.()}}defer(t){t&&typeof t=="function"&&(this.__defered??=[],this.__defered.push(t))}get children(){return this.__children}get contentManifests(){return this.manifest.getSubNodes(this.platform)}get scopeForChildren(){return this.scope}getByRef(t){if(!t)return;if(t==="this"||t==="This")return this;let e=this.#t?.[t];return e||this.parent?.getByRef(t)}addReference(t,e){this.#t??={},this.#t[t]=e}log(t,...e){return this.platform.log({level:"log",source:`${this.displayName}:${this.uid}`,message:t,params:e}),t}logError(t,...e){return this.platform.log({level:"error",source:`${this.displayName}:${this.uid}`,error:t,message:`${String(t.message||t)}`,params:e}),t}toString(){return ot(this)}};function mt(r,t){let e=[],n=0,s=!1,o="",a=0;for(let c=0;c<r.length;c++){let f=r[c];s?f===o&&(s=!1):f==='"'||f==="'"?(s=!0,o=f):f==="("||f==="["?n++:f===")"||f==="]"?n--:f===t&&n===0&&(e.push(r.slice(a,c).trim()),a=c+1)}let p=r.slice(a).trim();return p&&e.push(p),e}i(mt,"splitTopLevel");var Gt=i(()=>!1,"fnFalse"),Kt=i(()=>!0,"fnTrue"),Yt=i(()=>null,"fnNull"),Ut=i((r,t)=>r&&t,"fnAnd"),Bt=i((r,t)=>r||t,"fnOr"),xe=i((r,t)=>r+t,"fnPlus"),Zt=i(()=>{},"fnUndefined"),Ie=i(r=>!r,"fnNot"),Pe=i((r,t)=>r===t,"fnEqual"),we=i((r,t)=>r!==t,"fnNotEqual"),Wt=i((r,t)=>r<t,"fnLessThan"),Se=i((r,t)=>r<=t,"fnLessThanOrEqual"),zt=i((r,t)=>r>t,"fnGreaterThan"),qt=i((r,t)=>r>=t,"fnGreaterThanOrEqual"),Me=i((r,t)=>r-t,"fnMinus"),Re=i((r,t)=>r*t,"fnMultiply"),Te=i((r,t)=>r/t,"fnDivide"),be=i((r,t)=>r%t,"fnModulo"),Oe=i((r,t)=>r**t,"fnExponent"),De=i((r,t)=>r===t,"fnStrictEqual"),Xe=i((r,t)=>r??t,"fnCoalesce");var Qt={"&&":Ut,AND:Ut,"||":Bt,OR:Bt,"!":Ie,"==":Pe,"===":De,"!=":we,"<":Wt,LT:Wt,">":zt,GT:zt,GTE:qt,"<=":Se,">=":qt,"+":xe,"-":Me,"*":Re,"/":Te,"%":be,"**":Oe,"??":Xe};var Q=class{constructor(t,e){this.ctx=e;this.input=t.trim(),this.length=this.input.length}ctx;static{i(this,"ExpressionParserBase")}input;position=0;length=0;checkIf(t){return this.input.startsWith(t,this.position)}checkIfNum(){return/[0-9+-]/.test(this.input[this.position])}checkExceeded(){this.position!==this.length&&this.throw("Unexpected end of expression")}consumeIf(t){return this.checkIf(t)?(this.position+=t.length,!0):!1}throw(t){throw new Error(`${t} in '${this.input.slice(0,this.position)}<<<<${this.input.slice(this.position)}'`)}consume(t){return this.consumeIf(t)||this.throw(`Expected expression '${t}' at position ${this.position}`),!0}consumeWhitespace(){for(;this.position<this.length&&/\s/.test(this.input[this.position]);)this.position++}parseLeftRight(t,e,n){let s=this[e]();for(let o=0;o<t.length;o++){let a=t[o];if(this.consumeWhitespace(),this.consumeIf(a)){this.consumeWhitespace();let p=this[n](),c=Qt[a];return{type:a,left:s,right:p,fn:i((f,l)=>c(s.fn(f,l),p.fn(f,l)),"fn")}}}return s}parseString(){let t=this.input[this.position],e="";for(this.position++;this.position<this.input.length&&this.input[this.position]!==t;)e+=this.input[this.position],this.position++;return this.input[this.position]===t&&this.position++,{type:"String",value:e,fn:i(()=>e,"fn")}}parseNumber(){let t="";for(this.position<this.input.length&&/[0-9.+-]/.test(this.input[this.position])&&(t+=this.input[this.position],this.position++);this.position<this.input.length&&/[0-9.]/.test(this.input[this.position]);)t+=this.input[this.position],this.position++;let e=parseFloat(t);return{type:"Number",value:e,fn:i(()=>e,"fn")}}parseIdentifier(){let t="";for(;this.position<this.input.length&&/[a-zA-Z0-9_$-]/.test(this.input[this.position]);)t+=this.input[this.position],this.position++;return t==="it"||t==="event"?{type:"Event",name:t,fn:i((e,n)=>n,"fn")}:t.startsWith("R.")?{type:"Resource",name:t,fn:i(e=>this.ctx.resolveIdentifier(e,t),"fn")}:(this.ctx.propNames.add(t),{type:"Identifier",name:t,fn:i(e=>this.ctx.resolveIdentifier(e,t),"fn")})}};var S=class extends Q{static{i(this,"ExpressionParser")}parse(){let t=this.parsePipesExpression(this.parseExpression());return this.checkExceeded(),t}parsePipesExpression(t){if(this.consumeIf("|")){this.consumeWhitespace();let e=this.parseIdentifier().name;this.consumeWhitespace();let n=[];for(;this.consumeIf(":");)this.consumeWhitespace(),n.push(this.parseExpression());return this.parsePipesExpression({type:"Pipe",args:n,pipeId:e,from:t,fn:i((s,o)=>{let a=this.ctx.getFunction(s,e);a||s.logError(`Undefined pipe function:${e}`);let p=t.fn(s,o);return _(p,c=>a?.call(s,c,...n.map(f=>f.fn(s,o))))},"fn")})}return t}parseExpression(){let t=this.parseTernary();return this.consumeWhitespace(),t}parseTernary(){let t=this.parseCoalesce();if(this.consumeIf("?")){this.consumeWhitespace();let e=this.parseExpression(),n;return this.consumeIf(":")&&(this.consumeWhitespace(),n=this.parseExpression()),{type:"Ternary",condition:t,trueExpr:e,falseExpr:n,fn:i((s,o)=>t.fn(s,o)?e.fn(s,o):n?n.fn(s,o):void 0,"fn")}}return t}parseCoalesce(){return this.parseLeftRight(["??"],"parseOr","parseCoalesce")}parseOr(){return this.parseLeftRight(["||","OR"],"parseAnd","parseOr")}parseAnd(){return this.parseLeftRight(["&&","AND"],"parseCompare","parseAnd")}parseCompare(){return this.parseLeftRight(["===","==","!="],"parseEquality","parseEquality")}parseEquality(){return this.parseLeftRight([">=",">","GTE","GT","<=","<","LT"],"parsePlus","parsePlus")}parsePlus(){return this.parseLeftRight(["+","-"],"parseMulti","parsePlus")}parseMulti(){return this.parseLeftRight(["*","/","%"],"parseUnary","parseMulti")}parseUnary(){if(this.consumeIf("!")){let t=this.parseUnary();return{type:"Not",expr:t,fn:i((e,n)=>!t.fn(e,n),"fn")}}return this.parsePrimary()}parsePrimary(){if(this.consumeIf("(")){this.consumeWhitespace();let t=this.parseExpression();return this.consume(")"),this.parsePropertyAccess(t)}return this.consumeIf("true")?{type:"Boolean",value:!0,fn:Kt}:this.consumeIf("false")?{type:"Boolean",value:!1,fn:Gt}:this.consumeIf("null")?{type:"Null",fn:Yt}:this.consumeIf("undefined")?{type:"Undefined",fn:Zt}:this.checkIf("'")||this.checkIf('"')?this.parseString():this.checkIfNum()?this.parseNumber():this.parsePropertyAccess(this.parseIdentifier())}parsePropertyAccess(t){if(this.consumeWhitespace(),this.consumeIf(".")){let e=this.parseIdentifier();return this.parsePropertyAccess({type:"PropertyAccess",object:t,property:e.name,fn:i((n,s)=>t.fn(n,s)?.[e.name],"fn")})}if(this.consumeIf("(")){this.consumeWhitespace();let e=t.name,n=[];if(!this.consumeIf(")")){for(n.push(this.parseExpression());this.consumeIf(",");)this.consumeWhitespace(),n.push(this.parseExpression());this.consumeWhitespace(),this.consume(")")}return this.parsePropertyAccess({type:"Function",args:n,pipeId:e,fn:i((s,o)=>{if(!e)return s.logError(`Empty pipe function: ${e}`),n[0]?.fn(s,o);let a=this.ctx.getFunction(s,e);return a||s.logError(`Undefined pipe function: ${e}`),a?.apply(s,n.map(p=>p.fn(s,o)))},"fn")})}if(this.consumeIf("[")){this.consumeWhitespace();let e=this.parseExpression();return this.consumeWhitespace(),this.consume("]"),this.parsePropertyAccess({type:"ComputedPropertyAccess",object:t,property:e,fn:i((n,s)=>t.fn(n,s)?.[e.fn(n,s)],"fn")})}return t}};var Jt=new Map,ke=1,He=i((r,t)=>t,"identityFunc"),je={$RefProp:i(r=>(t,e)=>r.getByRef(t)?.get(e),"$RefProp")},M=class r{static{i(this,"Expression")}static from(t){let e=Jt.get(t);if(e)return e;let n=new r,s=t.replaceAll(/@(\w+)\.(\w+)/g,o=>{let a=`${X}C${ke++}`;return n.connectedPropsNames.set(a,o.slice(1)),a});try{let o=new S(s,n).parse();n.functor=o.fn}catch(o){throw console.error(`Expression: ${t}`,o),o}return Jt.set(t,n),n}functor=He;connectedPropsNames=new Map;propNames=new Set;resolveIdentifier(t,e){return t.getFromScope(e)}getFunction(t,e){return e[0]==="$"?je[e](t):t.platform.getFunction(e)}};function R(r){let t=new M;try{let e=new S(r,t).parse();t.functor=e.fn}catch(e){throw console.error(`Expression: ${r}`,e),e}return t}i(R,"compilePlaceholder");function Vt(r,t){r.startsWith("@")&&(r=r.slice(1));let e=r.indexOf("="),n=r.indexOf("(");if(e>0&&(n===-1||e<n)){let s=r.slice(0,e).trim();r=r.slice(e+1).replaceAll(/@(\w+)\.(\w+)/g,(a,p,c)=>`$RefProp('${p}', '${c}')`);let o=R(r).functor;return a=>p=>a.scope?.emit(s,o(a,p))}if(n>0){let s=`${r.slice(0,n)}()`,o=r.slice(n+1,-1).trim();if(o=o.replaceAll(/@(\w+)\.(\w+)/g,(p,c,f)=>`$RefProp('${c}', '${f}')`),!o)return p=>c=>p.scope?.emit(s,c);let a=mt(o,",").map(p=>R(p).functor);return p=>c=>p.scope?.emit(s,...a.map(f=>f(p,c)))}return r=r.trim(),s=>o=>s.scope?.emit(r,o)}i(Vt,"compileSingleExpression");function te(r,t){let e=mt(r,";").filter(Boolean);if(e.length<=1)return Vt(e[0]??r,t);let n=e.map(s=>Vt(s,t));return s=>async o=>{for(let a of n)await a(s)(o)}}i(te,"compileEmitterExpression");var ut=new Map;function Fe(r){let t=O(r);return()=>t}i(Fe,"compileConstant");function ve(r){if(typeof r!="string")return()=>r;if(r.includes("{")){let t=r.slice(1,-1);return r[0]==="{"&&r.at(-1)==="}"&&!t.includes("{")?R(t).functor:it(r,e=>R(e).functor)}return Fe(r)}i(ve,"_resolveExpression");var J=i(r=>ut.has(r)?ut.get(r):ut.set(r,ve(r)).get(r),"resolveExpression");var Le=1;function V(r){let t={};return r=r.replaceAll(/@(\w+)\.(\w+)/g,n=>{let s=X+Le++;return t[s]=n.slice(1),s}),{expr:J(r),props:Object.entries(t)}}i(V,"prepareConnectedProps");var ee=1;var u=class{static{i(this,"ManifestNode")}$content;uid;refId;propertyResolvers=[];initialState={};connectors;tag;constructor(t){this.uid=`N${String(ee++)}:${t}`}createArrmatron(t,e,n){return new this.EntitronConstructor(t,this,e,n)}getSubNodes(t){return this.$content}bindExpression(t,e){let{functor:n,connectedPropsNames:s,propNames:o}=M.from(t);if(s?.size)for(let[a,p]of s.entries())this.addConnector(p,(c,f)=>{c.putInLocalScope(a,f),c.up(e(n(c)))});o?.size&&this.propertyResolvers.push((a,p)=>(Object.assign(p,e(n(a))),p))}addConnectedPropertyResolver(t,e){let{expr:n,props:s}=V(t);s.forEach(([o,a])=>{this.addConnector(a,(p,c)=>(p.putInLocalScope(o,c),_(n(p),f=>{p.up({[e]:f})})))}),this.propertyResolvers.push((o,a)=>(a[e]=n(o),a))}addConnectedDataPropertyResolver(t,e){if(typeof t!="string")this.addDataPropertyResolver(J(t),e);else{let{expr:n,props:s}=V(t);s.forEach(([o,a])=>{this.addConnector(a,(p,c)=>(p.putInLocalScope(o,c),_(n(p),f=>{p.up({data:{...p.get("data"),[e]:f}})})))}),this.addDataPropertyResolver(n,e)}}addDataPropertyResolver(t,e){this.propertyResolvers.push((n,s)=>{let o=t(n);return s.data=Object.assign(s.data||{},{[e]:o}),s})}addConnectedPropertiesResolver(t){let{expr:e,props:n}=V(t);n.forEach(([s,o])=>{this.addConnector(o,(a,p)=>(a.putInLocalScope(s,p),_(e(a),c=>{let f=a.$$propKeys??(a.$$propKeys={});Object.keys(c??{}).forEach(l=>f[l]=null),a.up({...f,...c})})))}),this.propertyResolvers.push((s,o)=>{let a=e(s);if(a&&typeof a=="object"){let p=s.$$propKeys??(s.$$propKeys={});Object.keys(p).forEach(c=>o[c]=null),Object.entries(a).forEach(([c,f])=>{p[c]=null,o[c]=f})}return o})}addConnector(t,e){let n=this.connectors??(this.connectors=new Map),[s,o]=t.trim().split("."),a=`${s}.${o||"This"}.${ee++}`;n.set(a,e)}resolveInitialProps(t){let e=Object.entries(this.initialState).reduce((n,[s,o])=>(n[s]=o(t),n),{});return this.resolveProps(t,e)}resolveProps(t,e={}){return this.propertyResolvers.reduce((n,s)=>s(t,n),e)}compileAttribute(t,e){if(t.startsWith("data-")&&t!=="data-theme")this.addConnectedDataPropertyResolver(e,t.slice(5));else if(t==="Ref")this.refId=String(e);else if(t==="Props")this.addConnectedPropertiesResolver(String(e));else if(typeof e!="string")this.initialState[t]=()=>e;else if(e[0]==="'"&&e.at(-1)==="'"){let n=e.slice(1,-1);this.initialState[t]=()=>n}else if(e.includes("{"))this.addConnectedPropertyResolver(e,t);else if(e.startsWith("@")){let[n,s]=e.slice(1).trim().split(".");s?this.bindExpression(e,o=>({[t]:o})):this.initialState[t]=o=>o.getByRef(n)?.$component}else e.startsWith("->")?this.initialState[t]=te(e.slice(2).trim(),this):this.initialState[t]=()=>e}compileAttributes(t){t&&Object.entries(t).forEach(e=>this.compileAttribute(...e))}};var ht=class extends m{static{i(this,"Block")}get displayName(){return`\u{1F4A0}${this.manifest.tag}`}get contentManifests(){let t=this.get("Nodes")??[];return this.platform.getCompiledNodes(t)}},k=class extends u{static{i(this,"CBlockNode")}constructor({id:t,attrs:e}){super(t+(e?.Ref?`:${e?.Ref}`:"")),this.compileAttributes(e)}get EntitronConstructor(){return ht}};var dt=class extends m{static{i(this,"Composite")}get displayName(){return`\u{1F4A0}${this.manifest.tag}`}get scopeForChildren(){return this}slotContent(t){return this.manifest.getSlotContent(this.platform,t)}createComponent(){return this.platform.createComponent(this.manifest.tag)}},H=class extends u{static{i(this,"CCompositeNode")}slotContent=null;tag;nodes;constructor({id:t,tag:e,attrs:n,nodes:s}){super(t+(n?.Ref?`:${n?.Ref}`:"")),this.tag=e,this.nodes=s,this.compileAttributes(n)}getSlotContent(t,e){if(!this.slotContent){let n=this.nodes?.reduce((s,o)=>{if(o){let a=String(o.attrs?.Slot??"default");s[a]=(s[a]||[]).concat(o)}return s},{});this.slotContent=Object.entries(n??{}).reduce((s,[o,a])=>(s[o]=t.getCompiledNodes(a),s),{})}return this.slotContent[e||"default"]??void 0}getSubNodes(t){return t.getCompiledNodes(this.tag)}get EntitronConstructor(){return dt}};var gt=class extends m{static{i(this,"Conditional")}get contentManifests(){return this.ifCondition?this.ifBranches.thenBlock:this.ifBranches.elseBlock}get ifCondition(){return this.$component.condition}get ifBranches(){return this.manifest.getBranches(this.platform)}get displayName(){return`\u{1F539}if:${this.manifest.expr}`}},j=class extends u{static{i(this,"CIfNode")}#t;#e;expr;constructor(t,e){super(t.id),this.#t=t,this.expr=e,this.compileCondition(e)}get EntitronConstructor(){return gt}getBranches(t){if(this.#e)return this.#e;this.#e={};let{nodes:e}=this.#t,n=[this.#t];if(e?.length){let s=e.find(a=>a.tag==="Else"),o=e.find(a=>a.tag==="Then");s?(this.#e.elseBlock=s.nodes?t.getCompiledNodes(s.nodes):void 0,n=o?o.nodes:[{...this.#t,nodes:e.filter(a=>a!==s)}]):o&&(n=o.nodes)}return this.#e.thenBlock=n?t.getCompiledNodes(n):void 0,this.#e}compileCondition(t){if(t.startsWith("Slot(")){let e=t.slice(5,-1);this.propertyResolvers.push((n,s)=>(s.condition=!!n.scope.slotContent?.(e)?.size,s))}else t[0]==="{"&&t[t.length-1]==="}"&&(t=t.slice(1,-1)),this.bindExpression(t,e=>({condition:!!e}))}};var yt=class extends A{static{i(this,"DataConnectorComponent")}_data;change;get data(){return this._data}set data(t){this._data=t,_(t,e=>{e!==void 0&&this.change?.(e)})}},Ct=class extends A{static{i(this,"TriggerConnectorComponent")}change;_trigger;data;get trigger(){return this._trigger}set trigger(t){this._trigger=t,_(t,e=>{e!==void 0&&_(this.data,n=>{this.change?.(n)})})}},_t=class extends m{static{i(this,"Connector")}createComponent(){let t=this.manifest.componentClass;return new t}get displayName(){return"\u{1F539}Connector"}},F=class extends u{static{i(this,"ConnectorNode")}componentClass;constructor({attrs:t,id:e}){super(e);let{trigger:n,change:s,...o}=t;this.compileAttributes(n?{change:s,...o,trigger:n}:{change:s,...o}),this.componentClass=n?Ct:yt}get EntitronConstructor(){return _t}};var Nt=class extends m{static{i(this,"NativeElementEntitron")}get displayName(){return this.manifest.tag}createComponent(){return this.platform.createComponent({tag:this.manifest.tag,native:!0})}},v=class extends u{static{i(this,"CElementNode")}#t;constructor({id:t,tag:e,attrs:n,nodes:s,text:o}){super(t),this.tag=e,this.compileAttributes(n),o&&this.compileAttribute("#text",o),this.#t=s}getSubNodes(t){return this.#t?t.getCompiledNodes(this.#t):void 0}get EntitronConstructor(){return Nt}};var L=class extends u{static{i(this,"CFragmentNode")}#t;constructor({id:t,nodes:e,attrs:n}){super(t),this.#t=e,this.compileAttributes(n)}getSubNodes(t){return this.#t?t.getCompiledNodes(this.#t):void 0}get EntitronConstructor(){return m}};var re=i(r=>r?typeof r=="string"?r.split(",").map(t=>t.trim()).map(t=>({id:t,name:t})):Array.isArray(r)?r.map(t=>typeof t=="object"?{...t,id:String(t.id??"")}:{id:String(t),name:String(t??"--")}):typeof r[Symbol.iterator]=="function"?[...r]:typeof r=="object"?I(r,(t,e)=>typeof e=="object"?{...e,id:t}:{id:t,name:String(e)}):[{id:String(r),name:String(r)}]:[],"narrowData");var At=class extends m{static{i(this,"Iterative")}pkHash={};get displayName(){return`\u{1F7EA}each:${this.manifest.itemName}`}get eachList(){return this.$component.each}get contentManifests(){let t=re(this.eachList),e=this.manifest.getItemCtxNode(this.platform),n=new Map;return this.pkHash={},t.forEach(s=>{let o=String(s.id||C(s));if(this.pkHash[o]){this.logError(`ERROR: duplicate item id : ${o} (skipped)`,s);return}this.pkHash[o]=s;let a=e.cloneWithDatum(s,this.platform);a.propertyResolvers.push((p,c)=>(c[e.itemName]=this.pkHash[o],c)),n.set(a.uid,a)}),n}},U=class extends u{static{i(this,"CForNode")}#t;itemName;#e;constructor(t,e,n){super(t.id),this.#e=t,this.itemName=e,this.bindExpression(n,s=>({each:s}))}getItemCtxNode(t){return this.#t??(this.#t=new $t(this.#e.id,this.itemName,t.getCompiledNodes([this.#e])))}get EntitronConstructor(){return At}},Et=class extends m{static{i(this,"IterativeItem")}get scopeForChildren(){return this}get displayName(){return`\u{1F7EA}each:item:${this.manifest.itemName}`}emit(t,...e){return this.scope.emit(t,...e)}get(t){let e=this.manifest.itemName;return t.startsWith(`${e}.`)||t===e?super.get(t):this.scope.get(t)}},$t=class r extends u{static{i(this,"CItemNode")}itemName;constructor(t,e,n){super(t),this.itemName=e,this.$content=n}cloneWithDatum(t,e){let n=`${String(this.uid)}#${t.id||C(t)}`,s=new r(n,this.itemName,this.getSubNodes(e));return s.uid=n,s}get EntitronConstructor(){return Et}};var xt=class extends m{static{i(this,"DynamicTag")}get displayName(){return"dynamics"}get _dynamicTag(){return this.$component._dynamicTag}get contentManifests(){let t=this._dynamicTag,e=`${this.uid}:${String(t??"")}`,n=this.manifest.getCompiledForTag(this.platform,t);return new Map([[e,Object.assign(n,{uid:e})]])}},B=class extends u{static{i(this,"CDynamicTagNode")}xml;#t=new Map;constructor(t,e){super(t.id),this.compileAttribute("_dynamicTag",e),this.xml=t}getCompiledForTag(t,e){let n=String(e??""),s=this.#t.get(n);return s||(s=t.getCompiledNodes({...this.xml,tag:e}),this.#t.set(n,s)),s}get EntitronConstructor(){return xt}};var It=class extends m{static{i(this,"Selector")}get displayName(){return"\u{1F4A0}Selector"}get contentManifests(){let t=this.manifest.getCases(this.platform),e=this.$component.On;return t?.[e]??t?.default}},W=class extends u{static{i(this,"CSelectorNode")}cases=null;key="";nodes;constructor({id:t,tag:e,attrs:n,nodes:s}){super(t),this.tag=e,this.nodes=s,this.compileAttributes(n)}getCases(t){return this.cases??(this.cases=(this.nodes??[]).reduce((e,n)=>(e[n.attrs?.When]=t.getCompiledNodes(n.nodes??[]),e),{}))}get EntitronConstructor(){return It}};var Pt=class extends m{static{i(this,"Slot")}get displayName(){return"\u{1F538}slot"}getByRef(t){return this.scope?.getByRef(t)}get slotContent(){return this.scope.slotContent(this.manifest.key)}get contentManifests(){return this.slotContent}get scopeForChildren(){return this.scope.scope}},z=class extends u{static{i(this,"CSlotNode")}key;constructor(t){super(t.id),this.key=t.attrs?.Key}get EntitronConstructor(){return Pt}};var wt=i((r,t)=>{let{[t]:e,...n}=r.attrs??{};return{text:r.text,tag:r.tag,id:r.id,attrs:n,nodes:r.nodes?.map(s=>s)}},"cloneNode"),Ue=i(r=>{let{tag:t="div",attrs:e}=r;if(e?.Each){let[n,,...s]=String(e.Each).trim().split(" ");return new U(wt(r,"Each"),n,s.join(" "))}return e?.If?new j(wt(r,"If"),String(e.If)):t==="div"||t?.[0]?.match(/[A-Z0-9]/)==null?new v(r):t==="Dynamic"?new B(wt(r,"As"),String(e?.As??"Error.Dynamic")):t==="Slot"?new z(r):t==="Selector"?new W(r):t==="Connector"?new F(r):t==="Fragment"||t==="Then"||t==="Else"?new L(r):t==="Block"?new k(r):new H(r)},"__compileManifestNode"),St=new Map,tt=i(r=>St.has(r)?St.get(r):St.set(r,Ue(r)).get(r),"compileManifestNode"),et=i(r=>new Map(r?.map(tt).map(t=>[t.uid,t])??[]),"compileManifestNodes");var Mt=class extends m{static{i(this,"RootCtx")}get displayName(){return"ROOT"}get scopeForChildren(){return this}slotContent(t){}createComponent(){return this.platform.createComponent({})}},$=class extends u{constructor(e){super("R0");this.template=e;this.slotContent={},this.parsed=D(this.template)}template;static{i(this,"CRootNode")}slotContent;nodes;parsed;getSubNodes(e){return e.getCompiledNodes(this.parsed)}getSlotContent(e,n){}get EntitronConstructor(){return Mt}};var Be=i((r,t)=>{let e=new $(t).createArrmatron(r);return e.touch(),e},"launch");var We=1;function ze(r,t){t({Ctor:r,tag:r.name??Ge(r)})}i(ze,"registerFromFunction");function qe(r,t){r.replaceAll(/<Component\s+id="([^"]+)"(?:[^>]*)>([\s\S]*?)<\/Component>/gm,(e,n,s)=>(s=s.replaceAll(/<Signature\b[^>]*?\/>/gm,"").replaceAll(/<Signature\b[^>]*?>[\s\S]*?<\/Signature>/gm,"").replaceAll(/<Subcomponent\s+id="([^"]+)"(?:[^>]*)>([\s\S]*?)<\/Subcomponent>/gm,(o,a,p)=>(p=p.replaceAll(/<(\/?)This-/gm,(c,f)=>`<${f}${n}-`).trim(),t({tag:`${n}-${a}`,template:p}),"")).replaceAll(/<(\/?)This-/gm,(o,a)=>`<${a}${n}-`).trim(),t({tag:n,template:s}),""))}i(qe,"registerFromString");var Ge=i(r=>(/^function\s+([\w$]+)\s*\(/.exec(r.toString())??[])[1]??`C${String(We++)}`,"fnName");function Rt(r){return t=>{if(!t)return;let e=i(n=>{Array.isArray(n)?n.filter(Boolean).forEach(e):typeof n=="string"?qe(n,r):typeof n=="function"?ze(n,r):n.tag||n.id?r({...n,tag:n.tag??n.id}):I(n,(s,o)=>r({tag:s,template:o}))},"registerType");e(t)}}i(Rt,"createRegisterTypes");var rt=class{constructor(t,e){this.tag=t}tag;static{i(this,"NativeElement")}nodes=[];attrs={};native=!0;__stateChanged(t){Object.assign(this.attrs,Object.fromEntries([...t.entries()]))}getName(){return this.tag}getAttribute(t,e=null){return this.attrs[t]??e}getRequiredAttribute(t){let e=this.getAttribute(t);if(!e)throw new Error(`Required attribute '${t}' missing for ${this.getName()}`);return e}getBooleanAttribute(t,e=!1){let n=this.getAttribute(t,e);return typeof n=="boolean"?n:["true","1","yes","on"].includes(String(n).toLowerCase())}getNumericAttribute(t,e=0){let n=this.getAttribute(t,e);return parseFloat(n)||e}getEnumAttribute(t,e,n){let s=this.getAttribute(t,n);return e.includes(s)?s:n}getTextContent(){return this.attrs["#text"]}getChildren(){return this.nodes}};var nt=class{static{i(this,"Registry")}typeRegistry=new Map;compiledTemplates=new Map;NativeElement=rt;registerTypes(t){Rt(e=>{let n=String(e.tag);this.compiledTemplates.delete(n),this.typeRegistry.set(n,e)})(t)}getByTag(t){let e=this.typeRegistry.get(t);if(e)return e;let n=t.split(".");for(n.pop();n.length;n.pop()){let s=this.typeRegistry.get(n.join("."));if(s)return s}return{tag:t,unknown:!0}}xmlParse(t){try{return D(t)}catch(e){return[{tag:"div",text:String(e),id:"error"}]}}getCompiledNodes(t){if(typeof t=="string"){let e=this.compiledTemplates;if(e.has(t))return e.get(t);let n=this.getByTag(t);if(!n?.template)return[];let s=n.template,o=typeof s=="string"?this.xmlParse(s):s,a=et(o);return e.set(t,a),a}return Array.isArray(t)?et(t):tt(t)}createComponent(t){if(typeof t=="string")return this.createComponent(this.getByTag(t));let e=this.NativeElement;try{let{Ctor:n,tag:s,unknown:o,native:a}=t;return a?new e(s??"div",this):n?new n:o?(this.log({level:"info",message:`<-- unknown tag: ${s} -->`,source:"registry"}),new e("div",this)):new A}catch(n){return this.log({level:"error",message:"createComponent failed",error:n,source:"registry"}),new e("div",this)}}log(t){typeof t=="string"?console.log(t):console.log(t.source??"",t.message??"",...t.params??[])}};var q=class extends nt{static{i(this,"Platform")}resources={};constructor(t){super(),this.updateResources(t)}redraw(t,e){}updateResources(t){I(t,(e,n)=>{if(e[0]==="$")return;if(e==="NativeElement"){this.NativeElement=n;return}if(e==="components"){this.registerTypes(n);return}let s=e.split(".");if(s.length>1){let o=s.pop()??"-",a=s.reduce((p,c)=>p[c]??(p[c]={}),this.resources);a[o]=b(a[o],n);return}this.resources[e]=b(this.resources[e],n)})}getResource(t){let[e,...n]=typeof t=="string"?t.split("."):t,{resources:s}=this,o=e?s[e]:s;return!o||n.length===0?o:n.length===1?o[n[0]]:n.reduce((a,p)=>a?a[p]:null,o)}getFunction(t){return ft[t]||this.resources.functions?.[t]}applyAsyncValue(t,e,n){return e instanceof Promise?e.then(s=>n(s)):n(e)}};function st(r,t){if(r)for(let e of r.values()){let n=e.$component;n.native?(st(e.children,n),t.nodes.push(n)):st(e.children,t)}}i(st,"toNativeTree");function Ke(r,{reflow:t=st,rootElement:e={tag:"root",nodes:[]},...n}){let s=new q(n),o=new $(r).createArrmatron(s);return s.redraw=()=>{t(o.children,e)},o.touch(),e}i(Ke,"applyTemplate");0&&(module.exports={CRootNode,Component,Platform,applyTemplate,compileManifestNode,compileManifestNodes,createRegisterTypes,launch});
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";var G=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var ne=Object.getOwnPropertyNames;var se=Object.prototype.hasOwnProperty;var i=(r,t)=>G(r,"name",{value:t,configurable:!0});var Rt=(r,t)=>{for(var e in t)G(r,e,{get:t[e],enumerable:!0})},oe=(r,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of ne(t))!se.call(r,s)&&s!==e&&G(r,s,{get:()=>t[s],enumerable:!(n=re(t,s))||n.enumerable});return r};var ie=r=>oe(G({},"__esModule",{value:!0}),r);var Ye={};Rt(Ye,{CRootNode:()=>$,Component:()=>A,Platform:()=>q,applyTemplate:()=>Ke,compileManifestNode:()=>tt,compileManifestNodes:()=>et,createRegisterTypes:()=>Mt,launch:()=>Be});module.exports=ie(Ye);function Tt(r,t){t.__stateChanged?t.__stateChanged(r):r.forEach((e,n)=>{t[n]=e})}i(Tt,"applyStateChangedToImpl");var bt=i(r=>typeof r=="object"?Array.isArray(r)?r.length?`[${bt(r[0])??""} x${String(r.length)}]`:"[]":`{${Object.keys(r).toString()}}`:r??"","attributesToString"),ae=i(r=>{if(!r)return"";let t=[];return Object.entries(r).forEach(([e,n])=>{n!=null&&e[0]!=="$"&&t.push(` ${e}="${bt(n)}"`)}),t.length?t.join(""):""},"stringifyState"),ot=i((r,t="")=>{let{uid:e,displayName:n=e,$component:s,children:o}=r,a=o?.size?[...o.values()].map(p=>ot(p,` ${t}`)).join(`
|
|
2
|
+
`):"";return`${t}<${n}${ae(s)}${a?`>
|
|
3
|
+
${a}
|
|
4
|
+
${t}</${n}>`:"/>"}`},"stringify");var ct={};Rt(ct,{HASH_SYMBOL:()=>y,asyncValueCall:()=>_,capitalize:()=>K,defineObjectHashCodeProperty:()=>P,defineObjectRef:()=>it,hashCodeOf:()=>C,isEquals:()=>w,mapEntries:()=>I,mergeObject:()=>b,scalarParse:()=>O,stringHashCode:()=>h,xmlParse:()=>D});function _(r,t){return r instanceof Promise?r.then(t):t(r)}i(_,"asyncValueCall");var pe=i(r=>r==null?"":String(r),"str");function K(r){let t=pe(r);return t.length?t[0].toUpperCase()+t.slice(1):""}i(K,"capitalize");function it(r,t,e){return Object.defineProperty(r,t,{get(){return e},enumerable:!1,configurable:!1}),r}i(it,"defineObjectRef");var E=i(()=>Math.floor((1+Math.random())*65536).toString(16).substring(1),"s4"),ce=i(()=>`${E()}${E()}-${E()}-${E()}-${E()}-${E()}${E()}${E()}`,"guid"),y=Symbol("HASH_SYMBOL"),Ot=new Map([["",at("__empty__")]]),Dt=new Map([[void 0,h("__undefined__")],[null,h("__null__")],["",h("__empty__")],[NaN,h("__NaN__")],[!1,h("__false__")],[!0,h("__true__")]]),x={Object:h("__Object__"),Date:h("__Date__"),Array:h("__Array__"),Map:h("__Map__"),Set:h("__Set__")};function at(r){let t=-2128831035;for(let e=0;e<r.length;e++)t^=r.charCodeAt(e),t=Math.imul(t,16777619);return t|0}i(at,"__stringHashCode");function g(r,t){return Math.imul(t^r,16777619)|0}i(g,"numberHashCode");function h(r){let t=Ot.get(r);if(t)return t;let e=at(r);return Ot.set(r,e),e}i(h,"stringHashCode");function P(r,t){if(!r||Object.hasOwn(r,y))return r;let e=t??at(ce());return Object.defineProperty(r,y,{get(){return e},configurable:!1,enumerable:!1}),r}i(P,"defineObjectHashCodeProperty");function fe(r,t){if(t>10)return-1;let e=t+1,n=0;if(r instanceof Map){n=g(x.Map,n);for(let[s,o]of r)n=g(h(s),n),n=g(x.Map,n),n=g(C(o,e),n)}else if(r instanceof Set){n=g(x.Set,n);for(let s of r)n=g(C(s,e),n)}else if(Array.isArray(r)){n=g(x.Array,n);for(let s of r)n=g(C(s,e),n)}else{n=g(x.Object,n);for(let s in r)Object.hasOwn(r,s)&&s[0]!=="$"&&(n=g(h(s),n),n=g(x.Object,n),n=g(C(r[s],e),n))}return n}i(fe,"containerHashCode");var C=i((r,t=0)=>Dt.has(r)?Dt.get(r):typeof r=="string"?h(r):typeof r=="number"?r:typeof r=="bigint"?h(r.toString(16)):typeof r=="symbol"?h(r.description??r.toString()):typeof r=="function"?P(r)[y]:y in r?r[y]:r instanceof Date?g(r.getTime(),x.Date):r instanceof Promise?P(r)[y]:fe(r,t),"hashCodeOf");function w(r,t,e=0){if(Number.isNaN(r))return!1;if(r===null||typeof r!="object")return r===t;if(t===null||typeof t!="object")return!1;if(y in r&&y in t)return r[y]===t[y];if(e>10)return!0;let n=e+1;if(Array.isArray(r)){if(!Array.isArray(t)||r.length!==t.length)return!1;for(let o=0;o<r.length;o++)if(!w(r[o],t[o],n))return!1;return!0}if(r instanceof Map){if(!(t instanceof Map)||r.size!==t.size)return!1;for(let[o,a]of r){let p=t.get(o);if(p===void 0&&!t.has(o)||!w(a,p,n))return!1}return!0}if(r instanceof Set){if(!(t instanceof Set)||r.size!==t.size)return!1;for(let o of r)if(!t.has(o))return!1;return!0}if(Array.isArray(t)||t instanceof Map||t instanceof Set)return!1;if(r instanceof Date||t instanceof Date)return r instanceof Date&&t instanceof Date&&r.getTime()===t.getTime();let s=0;for(let o in r)if(!(o[0]==="$"||!Object.hasOwn(r,o))&&(s++,!Object.hasOwn(t,o)||!w(r[o],t[o],n)))return!1;for(let o in t)if(o[0]!=="$"&&Object.hasOwn(t,o)&&--s<0)return!1;return s===0}i(w,"isEquals");var le=i((r,t)=>({id:r,value:t}),"DEFAULT_ENTRY_HANDLER"),I=i((r,t=le)=>r?Object.entries(r).map(([e,n])=>t(e,n)):[],"mapEntries");var b=i((r,t)=>{if(!r||typeof r!="object")return t;if(!t||typeof t!="object")return r;for(let[e,n]of Object.entries(t))typeof n=="object"&&typeof r[e]=="object"?Array.isArray(r[e])?r[e]=n:r[e]=b(r[e],n):r[e]=n;return r},"mergeObject");var O=i(r=>{if(r==="")return"";if(r==="true")return!0;if(r==="false")return!1;if(r==="0")return 0;if(r==="1")return 1;if(r&&"1234567890+-".includes(r[0])&&r.length<=17){let t=+r;return Number.isNaN(t)?r:t}if(r==="null")return null;if(r!=="undefined")return r},"scalarParse");var me=/&#?[0-9a-zA-Z]{2,5};/g,ue={amp:"&",gt:">",lt:"<",quot:'"',nbsp:" "},he=i(r=>{let t=r.slice(1,-1);if(t[0]!=="#")return ue[t]||" ";let e=t.slice(1),n=e[0]==="x"||e[0]==="X"?parseInt(e.slice(1),16):parseInt(e,10);return Number.isFinite(n)?String.fromCharCode(n):" "},"FN_XML_ENTITY"),Ht=i(r=>String(r??"").replaceAll(me,he),"decodeXmlEntities"),de=i((r,t='"',e=t)=>r[0]===t&&r[r.length-1]===e?r.slice(1,-1):r,"skipQuotes"),pt=/([a-zA-Z][a-zA-Z0-9-:$]*)(="[^"]*")?/g,Xt=/^\s*$/,ge=/<!--((?!-->)[\s\S])*-->/g,Y=/(<)(\/?)([a-z][a-z0-9\-_:.]*)((?:\s+[a-zA-Z][a-z0-9-:$]*(?:="[^"]*")?)*)\s*(\/?)>/gi,ye={img:1,input:1,br:1,hr:1,col:1,source:1},Ce="Text",kt=i((r,t,e)=>{let n={tag:t,id:e};return(r.nodes??=[]).push(n),n},"addNode"),_e=i((r,t)=>{if(t){r.attrs={},pt.lastIndex=0;for(let e=pt.exec(t);e;e=pt.exec(t)){let n=e[2]?O(Ht(de(e[2].slice(1)))):!0;r.attrs[e[1]]=n}}},"parseAttrs"),D=i(r=>{let t=0,e=[{tag:"#root",id:String(t)}],n=String(r).trim().replace(ge,""),s=0;Y.lastIndex=0;for(let o=Y.exec(n);o;o=Y.exec(n)){let a=o.index&&n.slice(s,o.index);if(o[2]){if(a&&!e[0].nodes?.length&&(a===" "||!a.match(Xt))&&(e[0].text=Ht(a.trim())),e[0].tag!==o[3])throw new Error(` XML Parse closing tag does not match at: ${String(o.index)} near ${o.input.slice(Math.max(o.index-150,0),o.index)}^^^^${o.input.slice(o.index,Math.min(o.index+150,o.input.length))}`);e.shift()}else{if(a&&!a.match(Xt)){let c=kt(e[0],Ce,`T${String(++t)}`);c.attrs={text:a}}let p=kt(e[0],o[3],`X${String(++t)}`);if(_e(p,o[4].trim()),!(o[5]||o[3]in ye)&&(e.unshift(p),e.length===1))throw new Error(`Parse error at: ${o[0]}`)}s=Y.lastIndex}return e[0].nodes??[]},"xmlParse");function jt(r,t,e,n){let s,o,a=0;Object.defineProperty(r,t,{get(){let p=n?.length?n.map(l=>r.get(l)):[],c=p.some(l=>l instanceof Promise),f=i(l=>{let N=l.map(d=>C(d));return(!s||N.some((d,T)=>d!==s[T]))&&(s=N,o=e.apply(r,l)),o},"functor");return c?(a++,new Promise((l,N)=>{Promise.all(p.map(d=>d instanceof Promise?d:Promise.resolve(d))).then(f).then((d=>T=>{d===a&&l(T)})(a)).catch(d=>{N(d)})})):f(p)}})}i(jt,"defineCalculatedProperty");var Z="$$$ARRMATURA";var A=class{static{i(this,"Component")}name;get $$(){return this[Z]}get $uid(){return this.$$.uid}get $parentComponent(){return this.$$.parent?.$component}get refId(){return this.$$.refId}get platform(){return this.$$.platform}__init(){}get(t){return this.$$.get(t)}up(t){return this.$$.up(t)}touch(){return this.$$.touch()}getComponentByRef(t){return this.$$.getByRef(t)?.$component}emit(t,e={}){return this.$$.emit(t,e)}subscribeTo(t,e){return this.$$.subscribeTo(t,e)}defer(t){this.$$.defer(t)}__defineCalculatedProperty(t,e,n){jt(this,t,e,n)}__defineCalculatedProperties(t){Object.entries(t).forEach(([e,n])=>{let[s,o]=e.split("("),a=o?.slice(0,-1).split(",").map(p=>p.trim());this.__defineCalculatedProperty(s,n,a)})}log(t,...e){return this.$$.log(t,...e),t}logError(t,...e){return this.$$.logError(t,...e),t}toString(){return`${this.$$.toString()}${this.name?`(${this.name})`:""}`}};var X="outer$",vt=new Map,Ne=[],ft=0,m=class{constructor(t,e,n,s){this.platform=t;this.manifest=e;this.__parent=n;P(this),this.scope=s??this,this.root=s?.root??this;let o=this.createComponent();P(o),it(o,Z,this),this.$component=o,this.refId&&this.scope.addReference(this.refId,this)}platform;manifest;__parent;static{i(this,"Arrmatron")}$component;root;scope;__children;__propCache;__localScope;__isDone=!1;__isInited=!1;__fprints={};__listeners;__defered=[];__propFnMap;#t;#e=10;#r;get parent(){return this.__parent}get uid(){return this.manifest.uid}get hashCode(){return C(this)}get refId(){return this.manifest.refId}get displayName(){return`\u{1F539}${this.manifest.tag}`}createComponent(){return new A}up(t,e=!1){if(!t||this.__isDone)return;if(this.#r){Object.assign(this.#r,t);return}if(t instanceof Promise){this.platform.applyAsyncValue(`${this.hashCode}:set`,t,s=>this.up(s));return}let n=new Map;Object.entries(t).forEach(([s,o])=>{if(o instanceof Promise){let a=!s||s.startsWith("...");this.platform.applyAsyncValue(`${this.hashCode}:set:${s}`,o,p=>{this.up(a?p:{[s]:p})});return}!s||s[0]==="$"||(!(s in this.__fprints)||!w(this.__fprints[s],o))&&(this.__fprints[s]=o,n.set(s,o),this.__propCache?.delete(s))}),(n.size||e)&&(Tt(n,this.$component),this.#e&&(this.#e--,this.touch(),this.#e++))}get(t){if(!t)return null;let e,n;if(t.indexOf(".")===-1)e=t,n=Ne;else{let l=vt.get(t);l||(l=t.split("."),vt.set(t,l)),[e,...n]=l}let s=n.length===0;if(s){if(this.__propCache?.has(t))return this.__propCache.get(t)}else this.log("ERROR: Nested key",t);let o=this.__propFnMap??=new Map;if(o.has(t)){let l=o.get(t)();return s&&(this.__propCache??=new Map).set(t,l),l}let a=null,p=this.$component,c=p[t];if(c&&typeof c=="function"){let l=c.bind(p);a=i(()=>l,"fn")}else if(t==="This")a=i(()=>this.$component,"fn");else if(e==="R"){let l=this.platform.getResource(n)??null;a=i(()=>l,"fn")}else if(`get${K(e)}`in p){let l=p[`get${K(e)}`],N=typeof l=="function"?()=>l.call(p)??null:()=>p[e]??null;a=n.length?()=>n.reduce((d,T)=>d?.[T]??null,N()):N}else if(p.__getStateProperty)a=i(()=>p.__getStateProperty?.(t),"fn");else{let l=i(()=>p[e]??null,"fn0");a=n.length?()=>n.reduce((N,d)=>N?.[d]??null,l()):l}o.set(t,a);let f=a();return s&&(this.__propCache??(this.__propCache=new Map)).set(t,f),f}putInLocalScope(t,e){(this.__localScope??(this.__localScope=new Map)).set(t,e)}getFromScope(t){return t.startsWith(X)?this.__localScope?.get(t):this.scope.get(t)}notify(){this.__listeners?.forEach(t=>{try{t(this)}catch(e){this.logError("Notification:",e)}})}addListener(t){this.__listeners??=new Set;let e=this.__listeners;return e.add(t),()=>{e.delete(t)}}subscribeTo(t,e){let n=typeof t=="string"?this.getByRef(t):t;if(!n)throw new Error(`No such reference: ${t}`);this.defer(n.addListener(e))}emit(t,...e){if(!this.__isDone)try{if(t.endsWith(")")){let[n,s]=t.split("(")[0].split(".");s||(s=n,n="This");let o=this.getByRef(n);if(!o)throw new Error(`No such reference: ${n}`);let a=o.$component,p=a[s];if(typeof p!="function")throw new Error(`Not a method: ${n}.${s}()`);return e.length>1?p.apply(a,e):this.platform.applyAsyncValue(`${this.hashCode}:emit:${t}`,e[0],c=>p.call(a,c))}else{let n=e[0],[s,o]=t.split(".");o||(o=s||"*",s="this");let a=this.getByRef(s);if(!a)throw new Error(`No such reference: ${s}`);return a.up(o==="*"?n:{[o]:n})}}catch(n){this.logError(`emit ${t}:`,n)}}touch(){ft++;try{this.__propCache?.clear();let t=this.__isDone?null:this.contentManifests;if(t?.size||this.__children?.size)if(this.__children?.forEach(e=>{t?.has(e.uid)||e.done()}),t?.size){let e=this.__children;this.__children=new Map,t.forEach((n,s)=>{let o=e?.get(s),a=o&&!o?.__isDone?o:n.createArrmatron(this.platform,this,this.scopeForChildren);this.__children?.set(a.uid,a)});for(let n of this.__children.values())n.settle()}else this.__children=this.__children?.size===0?this.__children:new Map;this.__isDone?(this.__defered?.forEach(e=>e(this)),this.__defered=void 0,this.__parent=void 0,this.refId&&this.scope.#t&&delete this.scope.#t[this.refId],this.__listeners=void 0,this.__propFnMap=void 0,this.__propCache=void 0,this.__localScope=void 0):this.notify()}finally{ft--,ft||this.platform.redraw(this,this.root)}}done(){this.__isDone=!0,this.touch()}settle(){if(!this.__isDone)if(this.__isInited){let t=this.manifest.resolveProps(this);this.up(t,!!this.children?.size)}else{if(this.__isInited=!0,this.#r=this.manifest.resolveInitialProps(this),this.manifest.connectors)for(let[e,n]of this.manifest.connectors.entries()){let[s,o]=e.split("."),a=this.parent?.getByRef(s);if(!a){this.logError(`Connect: No such ref: ${s}`);continue}this.defer(a.addListener(()=>{this.platform.applyAsyncValue(`${this.hashCode}:connect:${e}`,a.get(o),p=>n(this,p))})),this.platform.applyAsyncValue(`${this.hashCode}:connect:${e}`,a.get(o),p=>n(this,p))}let t=this.#r;this.#r=null,this.up(t,!0),this.$component.__init?.()}}defer(t){t&&typeof t=="function"&&(this.__defered??=[],this.__defered.push(t))}get children(){return this.__children}get contentManifests(){return this.manifest.getSubNodes(this.platform)}get scopeForChildren(){return this.scope}getByRef(t){if(!t)return;if(t==="this"||t==="This")return this;let e=this.#t?.[t];return e||this.parent?.getByRef(t)}addReference(t,e){this.#t??={},this.#t[t]=e}log(t,...e){return this.platform.log({level:"log",source:`${this.displayName}:${this.uid}`,message:t,params:e}),t}logError(t,...e){return this.platform.log({level:"error",source:`${this.displayName}:${this.uid}`,error:t,message:`${String(t.message||t)}`,params:e}),t}toString(){return ot(this)}};function lt(r,t){let e=[],n=0,s=!1,o="",a=0;for(let c=0;c<r.length;c++){let f=r[c];s?f===o&&(s=!1):f==='"'||f==="'"?(s=!0,o=f):f==="("||f==="["?n++:f===")"||f==="]"?n--:f===t&&n===0&&(e.push(r.slice(a,c).trim()),a=c+1)}let p=r.slice(a).trim();return p&&e.push(p),e}i(lt,"splitTopLevel");var zt=i(()=>!1,"fnFalse"),qt=i(()=>!0,"fnTrue"),Gt=i(()=>null,"fnNull"),Ft=i((r,t)=>r&&t,"fnAnd"),Lt=i((r,t)=>r||t,"fnOr"),Ae=i((r,t)=>r+t,"fnPlus"),Kt=i(()=>{},"fnUndefined"),Ee=i(r=>!r,"fnNot"),$e=i((r,t)=>r===t,"fnEqual"),xe=i((r,t)=>r!==t,"fnNotEqual"),Ut=i((r,t)=>r<t,"fnLessThan"),Ie=i((r,t)=>r<=t,"fnLessThanOrEqual"),Bt=i((r,t)=>r>t,"fnGreaterThan"),Wt=i((r,t)=>r>=t,"fnGreaterThanOrEqual"),Pe=i((r,t)=>r-t,"fnMinus"),we=i((r,t)=>r*t,"fnMultiply"),Se=i((r,t)=>r/t,"fnDivide"),Me=i((r,t)=>r%t,"fnModulo"),Re=i((r,t)=>r**t,"fnExponent"),Te=i((r,t)=>r===t,"fnStrictEqual"),be=i((r,t)=>r??t,"fnCoalesce");var Yt={"&&":Ft,AND:Ft,"||":Lt,OR:Lt,"!":Ee,"==":$e,"===":Te,"!=":xe,"<":Ut,LT:Ut,">":Bt,GT:Bt,GTE:Wt,"<=":Ie,">=":Wt,"+":Ae,"-":Pe,"*":we,"/":Se,"%":Me,"**":Re,"??":be};var Q=class{constructor(t,e){this.ctx=e;this.input=t.trim(),this.length=this.input.length}ctx;static{i(this,"ExpressionParserBase")}input;position=0;length=0;checkIf(t){return this.input.startsWith(t,this.position)}checkIfNum(){return/[0-9+-]/.test(this.input[this.position])}checkExceeded(){this.position!==this.length&&this.throw("Unexpected end of expression")}consumeIf(t){return this.checkIf(t)?(this.position+=t.length,!0):!1}throw(t){throw new Error(`${t} in '${this.input.slice(0,this.position)}<<<<${this.input.slice(this.position)}'`)}consume(t){return this.consumeIf(t)||this.throw(`Expected expression '${t}' at position ${this.position}`),!0}consumeWhitespace(){for(;this.position<this.length&&/\s/.test(this.input[this.position]);)this.position++}parseLeftRight(t,e,n){let s=this[e]();for(let o=0;o<t.length;o++){let a=t[o];if(this.consumeWhitespace(),this.consumeIf(a)){this.consumeWhitespace();let p=this[n](),c=Yt[a];return{type:a,left:s,right:p,fn:i((f,l)=>c(s.fn(f,l),p.fn(f,l)),"fn")}}}return s}parseString(){let t=this.input[this.position],e="";for(this.position++;this.position<this.input.length&&this.input[this.position]!==t;)e+=this.input[this.position],this.position++;return this.input[this.position]===t&&this.position++,{type:"String",value:e,fn:i(()=>e,"fn")}}parseNumber(){let t="";for(this.position<this.input.length&&/[0-9.+-]/.test(this.input[this.position])&&(t+=this.input[this.position],this.position++);this.position<this.input.length&&/[0-9.]/.test(this.input[this.position]);)t+=this.input[this.position],this.position++;let e=parseFloat(t);return{type:"Number",value:e,fn:i(()=>e,"fn")}}parseIdentifier(){let t="";for(;this.position<this.input.length&&/[a-zA-Z0-9_$-]/.test(this.input[this.position]);)t+=this.input[this.position],this.position++;return t==="it"||t==="event"?{type:"Event",name:t,fn:i((e,n)=>n,"fn")}:t.startsWith("R.")?{type:"Resource",name:t,fn:i(e=>this.ctx.resolveIdentifier(e,t),"fn")}:(this.ctx.propNames.add(t),{type:"Identifier",name:t,fn:i(e=>this.ctx.resolveIdentifier(e,t),"fn")})}};var S=class extends Q{static{i(this,"ExpressionParser")}parse(){let t=this.parsePipesExpression(this.parseExpression());return this.checkExceeded(),t}parsePipesExpression(t){if(this.consumeIf("|")){this.consumeWhitespace();let e=this.parseIdentifier().name;this.consumeWhitespace();let n=[];for(;this.consumeIf(":");)this.consumeWhitespace(),n.push(this.parseExpression());return this.parsePipesExpression({type:"Pipe",args:n,pipeId:e,from:t,fn:i((s,o)=>{let a=this.ctx.getFunction(s,e);a||s.logError(`Undefined pipe function:${e}`);let p=t.fn(s,o);return _(p,c=>a?.call(s,c,...n.map(f=>f.fn(s,o))))},"fn")})}return t}parseExpression(){let t=this.parseTernary();return this.consumeWhitespace(),t}parseTernary(){let t=this.parseCoalesce();if(this.consumeIf("?")){this.consumeWhitespace();let e=this.parseExpression(),n;return this.consumeIf(":")&&(this.consumeWhitespace(),n=this.parseExpression()),{type:"Ternary",condition:t,trueExpr:e,falseExpr:n,fn:i((s,o)=>t.fn(s,o)?e.fn(s,o):n?n.fn(s,o):void 0,"fn")}}return t}parseCoalesce(){return this.parseLeftRight(["??"],"parseOr","parseCoalesce")}parseOr(){return this.parseLeftRight(["||","OR"],"parseAnd","parseOr")}parseAnd(){return this.parseLeftRight(["&&","AND"],"parseCompare","parseAnd")}parseCompare(){return this.parseLeftRight(["===","==","!="],"parseEquality","parseEquality")}parseEquality(){return this.parseLeftRight([">=",">","GTE","GT","<=","<","LT"],"parsePlus","parsePlus")}parsePlus(){return this.parseLeftRight(["+","-"],"parseMulti","parsePlus")}parseMulti(){return this.parseLeftRight(["*","/","%"],"parseUnary","parseMulti")}parseUnary(){if(this.consumeIf("!")){let t=this.parseUnary();return{type:"Not",expr:t,fn:i((e,n)=>!t.fn(e,n),"fn")}}return this.parsePrimary()}parsePrimary(){if(this.consumeIf("(")){this.consumeWhitespace();let t=this.parseExpression();return this.consume(")"),this.parsePropertyAccess(t)}return this.consumeIf("true")?{type:"Boolean",value:!0,fn:qt}:this.consumeIf("false")?{type:"Boolean",value:!1,fn:zt}:this.consumeIf("null")?{type:"Null",fn:Gt}:this.consumeIf("undefined")?{type:"Undefined",fn:Kt}:this.checkIf("'")||this.checkIf('"')?this.parseString():this.checkIfNum()?this.parseNumber():this.parsePropertyAccess(this.parseIdentifier())}parsePropertyAccess(t){if(this.consumeWhitespace(),this.consumeIf(".")){let e=this.parseIdentifier();return this.parsePropertyAccess({type:"PropertyAccess",object:t,property:e.name,fn:i((n,s)=>t.fn(n,s)?.[e.name],"fn")})}if(this.consumeIf("(")){this.consumeWhitespace();let e=t.name,n=[];if(!this.consumeIf(")")){for(n.push(this.parseExpression());this.consumeIf(",");)this.consumeWhitespace(),n.push(this.parseExpression());this.consumeWhitespace(),this.consume(")")}return this.parsePropertyAccess({type:"Function",args:n,pipeId:e,fn:i((s,o)=>{if(!e)return s.logError(`Empty pipe function: ${e}`),n[0]?.fn(s,o);let a=this.ctx.getFunction(s,e);return a||s.logError(`Undefined pipe function: ${e}`),a?.apply(s,n.map(p=>p.fn(s,o)))},"fn")})}if(this.consumeIf("[")){this.consumeWhitespace();let e=this.parseExpression();return this.consumeWhitespace(),this.consume("]"),this.parsePropertyAccess({type:"ComputedPropertyAccess",object:t,property:e,fn:i((n,s)=>t.fn(n,s)?.[e.fn(n,s)],"fn")})}return t}};var Zt=new Map,Oe=1,De=i((r,t)=>t,"identityFunc"),Xe={$RefProp:i(r=>(t,e)=>r.getByRef(t)?.get(e),"$RefProp")},M=class r{static{i(this,"Expression")}static from(t){let e=Zt.get(t);if(e)return e;let n=new r,s=t.replaceAll(/@(\w+)\.(\w+)/g,o=>{let a=`${X}C${Oe++}`;return n.connectedPropsNames.set(a,o.slice(1)),a});try{let o=new S(s,n).parse();n.functor=o.fn}catch(o){throw console.error(`Expression: ${t}`,o),o}return Zt.set(t,n),n}functor=De;connectedPropsNames=new Map;propNames=new Set;resolveIdentifier(t,e){return t.getFromScope(e)}getFunction(t,e){return e[0]==="$"?Xe[e](t):t.platform.getFunction(e)}};function R(r){let t=new M;try{let e=new S(r,t).parse();t.functor=e.fn}catch(e){throw console.error(`Expression: ${r}`,e),e}return t}i(R,"compilePlaceholder");function Qt(r,t){r.startsWith("@")&&(r=r.slice(1));let e=r.indexOf("="),n=r.indexOf("(");if(e>0&&(n===-1||e<n)){let s=r.slice(0,e).trim();r=r.slice(e+1).replaceAll(/@(\w+)\.(\w+)/g,(a,p,c)=>`$RefProp('${p}', '${c}')`);let o=R(r).functor;return a=>p=>a.scope?.emit(s,o(a,p))}if(n>0){let s=`${r.slice(0,n)}()`,o=r.slice(n+1,-1).trim();if(o=o.replaceAll(/@(\w+)\.(\w+)/g,(p,c,f)=>`$RefProp('${c}', '${f}')`),!o)return p=>c=>p.scope?.emit(s,c);let a=lt(o,",").map(p=>R(p).functor);return p=>c=>p.scope?.emit(s,...a.map(f=>f(p,c)))}return r=r.trim(),s=>o=>s.scope?.emit(r,o)}i(Qt,"compileSingleExpression");function Jt(r,t){let e=lt(r,";").filter(Boolean);if(e.length<=1)return Qt(e[0]??r,t);let n=e.map(s=>Qt(s,t));return s=>async o=>{for(let a of n)await a(s)(o)}}i(Jt,"compileEmitterExpression");var ke=i(r=>r==null?"":String(r),"str"),He=/\{([^}]+)\}/g,Vt="{$$$}",mt=new Map;function je(r,t){let e=[],n=r.replace(He,(a,p)=>(e.push(t(p.trim())),Vt));if(!e.length)return()=>n;let s=n.split(Vt),o=s.pop();return(...a)=>s.map((p,c)=>`${p}${ke(e[c](...a))}`).join("")+o}i(je,"createStringInterpolator");function ve(r){let t=O(r);return()=>t}i(ve,"compileConstant");function Fe(r){if(typeof r!="string")return()=>r;if(r.includes("{")){let t=r.slice(1,-1);return r[0]==="{"&&r.at(-1)==="}"&&!t.includes("{")?R(t).functor:je(r,e=>R(e).functor)}return ve(r)}i(Fe,"_resolveExpression");var J=i(r=>mt.has(r)?mt.get(r):mt.set(r,Fe(r)).get(r),"resolveExpression");var Le=1;function V(r){let t={};return r=r.replaceAll(/@(\w+)\.(\w+)/g,n=>{let s=X+Le++;return t[s]=n.slice(1),s}),{expr:J(r),props:Object.entries(t)}}i(V,"prepareConnectedProps");var te=1;var u=class{static{i(this,"ManifestNode")}$content;uid;refId;propertyResolvers=[];initialState={};connectors;tag;constructor(t){this.uid=`N${String(te++)}:${t}`}createArrmatron(t,e,n){return new this.EntitronConstructor(t,this,e,n)}getSubNodes(t){return this.$content}bindExpression(t,e){let{functor:n,connectedPropsNames:s,propNames:o}=M.from(t);if(s?.size)for(let[a,p]of s.entries())this.addConnector(p,(c,f)=>{c.putInLocalScope(a,f),c.up(e(n(c)))});o?.size&&this.propertyResolvers.push((a,p)=>(Object.assign(p,e(n(a))),p))}addConnectedPropertyResolver(t,e){let{expr:n,props:s}=V(t);s.forEach(([o,a])=>{this.addConnector(a,(p,c)=>(p.putInLocalScope(o,c),_(n(p),f=>{p.up({[e]:f})})))}),this.propertyResolvers.push((o,a)=>(a[e]=n(o),a))}addConnectedDataPropertyResolver(t,e){if(typeof t!="string")this.addDataPropertyResolver(J(t),e);else{let{expr:n,props:s}=V(t);s.forEach(([o,a])=>{this.addConnector(a,(p,c)=>(p.putInLocalScope(o,c),_(n(p),f=>{p.up({data:{...p.get("data"),[e]:f}})})))}),this.addDataPropertyResolver(n,e)}}addDataPropertyResolver(t,e){this.propertyResolvers.push((n,s)=>{let o=t(n);return s.data=Object.assign(s.data||{},{[e]:o}),s})}addConnectedPropertiesResolver(t){let{expr:e,props:n}=V(t);n.forEach(([s,o])=>{this.addConnector(o,(a,p)=>(a.putInLocalScope(s,p),_(e(a),c=>{let f=a.$$propKeys??(a.$$propKeys={});Object.keys(c??{}).forEach(l=>f[l]=null),a.up({...f,...c})})))}),this.propertyResolvers.push((s,o)=>{let a=e(s);if(a&&typeof a=="object"){let p=s.$$propKeys??(s.$$propKeys={});Object.keys(p).forEach(c=>o[c]=null),Object.entries(a).forEach(([c,f])=>{p[c]=null,o[c]=f})}return o})}addConnector(t,e){let n=this.connectors??(this.connectors=new Map),[s,o]=t.trim().split("."),a=`${s}.${o||"This"}.${te++}`;n.set(a,e)}resolveInitialProps(t){let e=Object.entries(this.initialState).reduce((n,[s,o])=>(n[s]=o(t),n),{});return this.resolveProps(t,e)}resolveProps(t,e={}){return this.propertyResolvers.reduce((n,s)=>s(t,n),e)}compileAttribute(t,e){if(t.startsWith("data-")&&t!=="data-theme")this.addConnectedDataPropertyResolver(e,t.slice(5));else if(t==="Ref")this.refId=String(e);else if(t==="Props")this.addConnectedPropertiesResolver(String(e));else if(typeof e!="string")this.initialState[t]=()=>e;else if(e[0]==="'"&&e.at(-1)==="'"){let n=e.slice(1,-1);this.initialState[t]=()=>n}else if(e.includes("{"))this.addConnectedPropertyResolver(e,t);else if(e.startsWith("@")){let[n,s]=e.slice(1).trim().split(".");s?this.bindExpression(e,o=>({[t]:o})):this.initialState[t]=o=>o.getByRef(n)?.$component}else e.startsWith("->")?this.initialState[t]=Jt(e.slice(2).trim(),this):this.initialState[t]=()=>e}compileAttributes(t){t&&Object.entries(t).forEach(e=>this.compileAttribute(...e))}};var ut=class extends m{static{i(this,"Block")}get displayName(){return`\u{1F4A0}${this.manifest.tag}`}get contentManifests(){let t=this.get("Nodes")??[];return this.platform.getCompiledNodes(t)}},k=class extends u{static{i(this,"CBlockNode")}constructor({id:t,attrs:e}){super(t+(e?.Ref?`:${e?.Ref}`:"")),this.compileAttributes(e)}get EntitronConstructor(){return ut}};var ht=class extends m{static{i(this,"Composite")}get displayName(){return`\u{1F4A0}${this.manifest.tag}`}get scopeForChildren(){return this}slotContent(t){return this.manifest.getSlotContent(this.platform,t)}createComponent(){return this.platform.createComponent(this.manifest.tag)}},H=class extends u{static{i(this,"CCompositeNode")}slotContent=null;tag;nodes;constructor({id:t,tag:e,attrs:n,nodes:s}){super(t+(n?.Ref?`:${n?.Ref}`:"")),this.tag=e,this.nodes=s,this.compileAttributes(n)}getSlotContent(t,e){if(!this.slotContent){let n=this.nodes?.reduce((s,o)=>{if(o){let a=String(o.attrs?.Slot??"default");s[a]=(s[a]||[]).concat(o)}return s},{});this.slotContent=Object.entries(n??{}).reduce((s,[o,a])=>(s[o]=t.getCompiledNodes(a),s),{})}return this.slotContent[e||"default"]??void 0}getSubNodes(t){return t.getCompiledNodes(this.tag)}get EntitronConstructor(){return ht}};var dt=class extends m{static{i(this,"Conditional")}get contentManifests(){return this.ifCondition?this.ifBranches.thenBlock:this.ifBranches.elseBlock}get ifCondition(){return this.$component.condition}get ifBranches(){return this.manifest.getBranches(this.platform)}get displayName(){return`\u{1F539}if:${this.manifest.expr}`}},j=class extends u{static{i(this,"CIfNode")}#t;#e;expr;constructor(t,e){super(t.id),this.#t=t,this.expr=e,this.compileCondition(e)}get EntitronConstructor(){return dt}getBranches(t){if(this.#e)return this.#e;this.#e={};let{nodes:e}=this.#t,n=[this.#t];if(e?.length){let s=e.find(a=>a.tag==="Else"),o=e.find(a=>a.tag==="Then");s?(this.#e.elseBlock=s.nodes?t.getCompiledNodes(s.nodes):void 0,n=o?o.nodes:[{...this.#t,nodes:e.filter(a=>a!==s)}]):o&&(n=o.nodes)}return this.#e.thenBlock=n?t.getCompiledNodes(n):void 0,this.#e}compileCondition(t){if(t.startsWith("Slot(")){let e=t.slice(5,-1);this.propertyResolvers.push((n,s)=>(s.condition=!!n.scope.slotContent?.(e)?.size,s))}else t[0]==="{"&&t[t.length-1]==="}"&&(t=t.slice(1,-1)),this.bindExpression(t,e=>({condition:!!e}))}};var gt=class extends A{static{i(this,"DataConnectorComponent")}_data;change;get data(){return this._data}set data(t){this._data=t,_(t,e=>{e!==void 0&&this.change?.(e)})}},yt=class extends A{static{i(this,"TriggerConnectorComponent")}change;_trigger;data;get trigger(){return this._trigger}set trigger(t){this._trigger=t,_(t,e=>{e!==void 0&&_(this.data,n=>{this.change?.(n)})})}},Ct=class extends m{static{i(this,"Connector")}createComponent(){let t=this.manifest.componentClass;return new t}get displayName(){return"\u{1F539}Connector"}},v=class extends u{static{i(this,"ConnectorNode")}componentClass;constructor({attrs:t,id:e}){super(e);let{trigger:n,change:s,...o}=t;this.compileAttributes(n?{change:s,...o,trigger:n}:{change:s,...o}),this.componentClass=n?yt:gt}get EntitronConstructor(){return Ct}};var _t=class extends m{static{i(this,"NativeElementEntitron")}get displayName(){return this.manifest.tag}createComponent(){return this.platform.createComponent({tag:this.manifest.tag,native:!0})}},F=class extends u{static{i(this,"CElementNode")}#t;constructor({id:t,tag:e,attrs:n,nodes:s,text:o}){super(t),this.tag=e,this.compileAttributes(n),o&&this.compileAttribute("#text",o),this.#t=s}getSubNodes(t){return this.#t?t.getCompiledNodes(this.#t):void 0}get EntitronConstructor(){return _t}};var L=class extends u{static{i(this,"CFragmentNode")}#t;constructor({id:t,nodes:e,attrs:n}){super(t),this.#t=e,this.compileAttributes(n)}getSubNodes(t){return this.#t?t.getCompiledNodes(this.#t):void 0}get EntitronConstructor(){return m}};var ee=i(r=>r?typeof r=="string"?r.split(",").map(t=>t.trim()).map(t=>({id:t,name:t})):Array.isArray(r)?r.map(t=>typeof t=="object"?{...t,id:String(t.id??"")}:{id:String(t),name:String(t??"--")}):typeof r[Symbol.iterator]=="function"?[...r]:typeof r=="object"?I(r,(t,e)=>typeof e=="object"?{...e,id:t}:{id:t,name:String(e)}):[{id:String(r),name:String(r)}]:[],"narrowData");var Nt=class extends m{static{i(this,"Iterative")}pkHash={};get displayName(){return`\u{1F7EA}each:${this.manifest.itemName}`}get eachList(){return this.$component.each}get contentManifests(){let t=ee(this.eachList),e=this.manifest.getItemCtxNode(this.platform),n=new Map;return this.pkHash={},t.forEach(s=>{let o=String(s.id||C(s));if(this.pkHash[o]){this.logError(`ERROR: duplicate item id : ${o} (skipped)`,s);return}this.pkHash[o]=s;let a=e.cloneWithDatum(s,this.platform);a.propertyResolvers.push((p,c)=>(c[e.itemName]=this.pkHash[o],c)),n.set(a.uid,a)}),n}},U=class extends u{static{i(this,"CForNode")}#t;itemName;#e;constructor(t,e,n){super(t.id),this.#e=t,this.itemName=e,this.bindExpression(n,s=>({each:s}))}getItemCtxNode(t){return this.#t??=new Et(this.#e.id,this.itemName,t.getCompiledNodes([this.#e])),this.#t}get EntitronConstructor(){return Nt}},At=class extends m{static{i(this,"IterativeItem")}get scopeForChildren(){return this}get displayName(){return`\u{1F7EA}each:item:${this.manifest.itemName}`}emit(t,...e){return this.scope.emit(t,...e)}get(t){let e=this.manifest.itemName;return t.startsWith(`${e}.`)||t===e?super.get(t):this.scope.get(t)}},Et=class r extends u{static{i(this,"CItemNode")}itemName;constructor(t,e,n){super(t),this.itemName=e,this.$content=n}cloneWithDatum(t,e){let n=`${String(this.uid)}#${t.id||C(t)}`,s=new r(n,this.itemName,this.getSubNodes(e));return s.uid=n,s}get EntitronConstructor(){return At}};var $t=class extends m{static{i(this,"DynamicTag")}get displayName(){return"dynamics"}get _dynamicTag(){return this.$component._dynamicTag}get contentManifests(){let t=this._dynamicTag,e=`${this.uid}:${String(t??"")}`,n=this.manifest.getCompiledForTag(this.platform,t);return new Map([[e,Object.assign(n,{uid:e})]])}},B=class extends u{static{i(this,"CDynamicTagNode")}xml;#t=new Map;constructor(t,e){super(t.id),this.compileAttribute("_dynamicTag",e),this.xml=t}getCompiledForTag(t,e){let n=String(e??""),s=this.#t.get(n);return s||(s=t.getCompiledNodes({...this.xml,tag:e}),this.#t.set(n,s)),s}get EntitronConstructor(){return $t}};var xt=class extends m{static{i(this,"Selector")}get displayName(){return"\u{1F4A0}Selector"}get contentManifests(){let t=this.manifest.getCases(this.platform),e=this.$component.On;return t?.[e]??t?.default}},W=class extends u{static{i(this,"CSelectorNode")}cases=null;key="";nodes;constructor({id:t,tag:e,attrs:n,nodes:s}){super(t),this.tag=e,this.nodes=s,this.compileAttributes(n)}getCases(t){return this.cases??(this.cases=(this.nodes??[]).reduce((e,n)=>(e[n.attrs?.When]=t.getCompiledNodes(n.nodes??[]),e),{}))}get EntitronConstructor(){return xt}};var It=class extends m{static{i(this,"Slot")}get displayName(){return"\u{1F538}slot"}getByRef(t){return this.scope?.getByRef(t)}get slotContent(){return this.scope.slotContent(this.manifest.key)}get contentManifests(){return this.slotContent}get scopeForChildren(){return this.scope.scope}},z=class extends u{static{i(this,"CSlotNode")}key;constructor(t){super(t.id),this.key=t.attrs?.Key}get EntitronConstructor(){return It}};var Pt=i((r,t)=>{let{[t]:e,...n}=r.attrs??{};return{text:r.text,tag:r.tag,id:r.id,attrs:n,nodes:r.nodes?.map(s=>s)}},"cloneNode"),Ue=i(r=>{let{tag:t="div",attrs:e}=r;if(e?.Each){let[n,,...s]=String(e.Each).trim().split(" ");return new U(Pt(r,"Each"),n,s.join(" "))}return e?.If?new j(Pt(r,"If"),String(e.If)):t==="div"||t?.[0]?.match(/[A-Z0-9]/)==null?new F(r):t==="Dynamic"?new B(Pt(r,"As"),String(e?.As??"Error.Dynamic")):t==="Slot"?new z(r):t==="Selector"?new W(r):t==="Connector"?new v(r):t==="Fragment"||t==="Then"||t==="Else"?new L(r):t==="Block"?new k(r):new H(r)},"__compileManifestNode"),wt=new Map,tt=i(r=>wt.has(r)?wt.get(r):wt.set(r,Ue(r)).get(r),"compileManifestNode"),et=i(r=>new Map(r?.map(tt).map(t=>[t.uid,t])??[]),"compileManifestNodes");var St=class extends m{static{i(this,"RootCtx")}get displayName(){return"ROOT"}get scopeForChildren(){return this}slotContent(t){}createComponent(){return this.platform.createComponent({})}},$=class extends u{constructor(e){super("R0");this.template=e;this.slotContent={},this.parsed=D(this.template)}template;static{i(this,"CRootNode")}slotContent;nodes;parsed;getSubNodes(e){return e.getCompiledNodes(this.parsed)}getSlotContent(e,n){}get EntitronConstructor(){return St}};var Be=i((r,t)=>{let e=new $(t).createArrmatron(r);return e.touch(),e},"launch");var We=1;function ze(r,t){t({Ctor:r,tag:r.name??Ge(r)})}i(ze,"registerFromFunction");function qe(r,t){r.replaceAll(/<Component\s+id="([^"]+)"(?:[^>]*)>([\s\S]*?)<\/Component>/gm,(e,n,s)=>(s=s.replaceAll(/<Signature\b[^>]*?\/>/gm,"").replaceAll(/<Signature\b[^>]*?>[\s\S]*?<\/Signature>/gm,"").replaceAll(/<Subcomponent\s+id="([^"]+)"(?:[^>]*)>([\s\S]*?)<\/Subcomponent>/gm,(o,a,p)=>(p=p.replaceAll(/<(\/?)This-/gm,(c,f)=>`<${f}${n}-`).trim(),t({tag:`${n}-${a}`,template:p}),"")).replaceAll(/<(\/?)This-/gm,(o,a)=>`<${a}${n}-`).trim(),t({tag:n,template:s}),""))}i(qe,"registerFromString");var Ge=i(r=>(/^function\s+([\w$]+)\s*\(/.exec(r.toString())??[])[1]??`C${String(We++)}`,"fnName");function Mt(r){return t=>{if(!t)return;let e=i(n=>{Array.isArray(n)?n.filter(Boolean).forEach(e):typeof n=="string"?qe(n,r):typeof n=="function"?ze(n,r):n.tag||n.id?r({...n,tag:n.tag??n.id}):I(n,(s,o)=>r({tag:s,template:o}))},"registerType");e(t)}}i(Mt,"createRegisterTypes");var rt=class{constructor(t,e){this.tag=t}tag;static{i(this,"NativeElement")}nodes=[];attrs={};native=!0;__stateChanged(t){Object.assign(this.attrs,Object.fromEntries([...t.entries()]))}getName(){return this.tag}getAttribute(t,e=null){return this.attrs[t]??e}getRequiredAttribute(t){let e=this.getAttribute(t);if(!e)throw new Error(`Required attribute '${t}' missing for ${this.getName()}`);return e}getBooleanAttribute(t,e=!1){let n=this.getAttribute(t,e);return typeof n=="boolean"?n:["true","1","yes","on"].includes(String(n).toLowerCase())}getNumericAttribute(t,e=0){let n=this.getAttribute(t,e);return parseFloat(n)||e}getEnumAttribute(t,e,n){let s=this.getAttribute(t,n);return e.includes(s)?s:n}getTextContent(){return this.attrs["#text"]}getChildren(){return this.nodes}};var nt=class{static{i(this,"Registry")}typeRegistry=new Map;compiledTemplates=new Map;NativeElement=rt;registerTypes(t){Mt(e=>{let n=String(e.tag);this.compiledTemplates.delete(n),this.typeRegistry.set(n,e)})(t)}getByTag(t){let e=this.typeRegistry.get(t);if(e)return e;let n=t.split(".");for(n.pop();n.length;n.pop()){let s=this.typeRegistry.get(n.join("."));if(s)return s}return{tag:t,unknown:!0}}xmlParse(t){try{return D(t)}catch(e){return[{tag:"div",text:String(e),id:"error"}]}}getCompiledNodes(t){if(typeof t=="string"){let e=this.compiledTemplates;if(e.has(t))return e.get(t);let n=this.getByTag(t);if(!n?.template)return[];let s=n.template,o=typeof s=="string"?this.xmlParse(s):s,a=et(o);return e.set(t,a),a}return Array.isArray(t)?et(t):tt(t)}createComponent(t){if(typeof t=="string")return this.createComponent(this.getByTag(t));let e=this.NativeElement;try{let{Ctor:n,tag:s,unknown:o,native:a}=t;return a?new e(s??"div",this):n?new n:o?(this.log({level:"info",message:`<-- unknown tag: ${s} -->`,source:"registry"}),new e("div",this)):new A}catch(n){return this.log({level:"error",message:"createComponent failed",error:n,source:"registry"}),new e("div",this)}}log(t){typeof t=="string"?console.log(t):console.log(t.source??"",t.message??"",...t.params??[])}};var q=class extends nt{static{i(this,"Platform")}resources={};constructor(t){super(),this.updateResources(t)}redraw(t,e){}updateResources(t){I(t,(e,n)=>{if(e[0]==="$")return;if(e==="NativeElement"){this.NativeElement=n;return}if(e==="components"){this.registerTypes(n);return}let s=e.split(".");if(s.length>1){let o=s.pop()??"-",a=s.reduce((p,c)=>p[c]??(p[c]={}),this.resources);a[o]=b(a[o],n);return}this.resources[e]=b(this.resources[e],n)})}getResource(t){let[e,...n]=typeof t=="string"?t.split("."):t,{resources:s}=this,o=e?s[e]:s;return!o||n.length===0?o:n.length===1?o[n[0]]:n.reduce((a,p)=>a?a[p]:null,o)}getFunction(t){return ct[t]||this.resources.functions?.[t]}applyAsyncValue(t,e,n){return e instanceof Promise?e.then(s=>n(s)):n(e)}};function st(r,t){if(r)for(let e of r.values()){let n=e.$component;n.native?(st(e.children,n),t.nodes.push(n)):st(e.children,t)}}i(st,"toNativeTree");function Ke(r,{reflow:t=st,rootElement:e={tag:"root",nodes:[]},...n}){let s=new q(n),o=new $(r).createArrmatron(s);return s.redraw=()=>{t(o.children,e)},o.touch(),e}i(Ke,"applyTemplate");0&&(module.exports={CRootNode,Component,Platform,applyTemplate,compileManifestNode,compileManifestNodes,createRegisterTypes,launch});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Arrmatura Architecture"
|
|
3
|
+
description: "This document outlines the key architectural and design considerations that guided the development of the Arrmatura framework."
|
|
4
|
+
keywords: [arrmatura, architecture]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Arrmatura is a **runtime-based framework** that enables building complex, dynamic reactive applications with minimal boilerplate and excellent performance.
|
|
8
|
+
|
|
9
|
+
## Design Principles
|
|
10
|
+
|
|
11
|
+
Arrmatura comes with unique architectural patterns, demonstrates sophisticated design:
|
|
12
|
+
|
|
13
|
+
- Well-structured core architecture with clear separation of concerns
|
|
14
|
+
- manifest-based component compilation.
|
|
15
|
+
- Sophisticated component lifecycle management
|
|
16
|
+
- Dynamic component composition
|
|
17
|
+
- Runtime template evaluation
|
|
18
|
+
- Lightweight bundle sizes
|
|
19
|
+
- Reactive state management and data flow
|
|
20
|
+
- Memory management considerations (cleanup on done())
|
|
21
|
+
- Fingerprinting for change detection - Clever optimization
|
|
22
|
+
- Comprehensive expression parser with extensive test coverage
|
|
23
|
+
- Extend functionality with TypeScript custom service components for complex business logic and integrations.
|
|
24
|
+
|
|
25
|
+
### Architectural choices
|
|
26
|
+
|
|
27
|
+
**Declarative-first**: should use for implementation the [Arrmatura](../libs/arrmatura/README.md) framework.
|
|
28
|
+
**Testing-driven**: Vitest with globals API (no imports needed)
|
|
29
|
+
**AI-native** integrate with LangChain
|
|
30
|
+
**GCP as target platform** rely on GCP ecosystem services: Auth, Firestore, Functions, Hosting
|
|
31
|
+
**Unified Code Style** see `biome.json` for default convention.
|
|
32
|
+
|
|
33
|
+
## Abstraction Layers
|
|
34
|
+
|
|
35
|
+
Arrmatura ecosystems separates concerns into three layers: framework, platform, application.
|
|
36
|
+
|
|
37
|
+
- a Arrmatura is a **Runtime Engine** to perform component lifecycle, state management, data flow, event handling.
|
|
38
|
+
- Particular **IPlatform** implementations (e.g.Web DOM manipulation, rendering) use it in specific *tech stack*.
|
|
39
|
+
- Components and Services are built on top and carries *application-level* business logic and UI.
|
|
40
|
+
|
|
41
|
+
## Runtime Engine core concepts
|
|
42
|
+
|
|
43
|
+
- **Arrmatron**: framework core object that wrapping a component. Has `uid`, `parent`, `children`, `get()`, `up()` (update state), `emit()`.
|
|
44
|
+
- **Component** (`IComponent`): Plain TS class/object with optional lifecycle hooks: `__init()`, `__stateChanged()`.
|
|
45
|
+
- **CML template** (`.xml`): Declarative XML that defines component trees. Loaded as text, parsed into `ManifestNode` trees.
|
|
46
|
+
- **Platform**: Bridges the Arrmatura runtime to the DOM (or other targets). Handles rendering via `redraw`.
|
|
47
|
+
- **Registry**: Maps tag names to component implementations. Apps register their components in `src/components.ts`.
|
|
48
|
+
- **Expression system**: Powerful parser for dynamic bindings in templates (e.g. `{data | upper}`).
|
|
49
|
+
|
|
50
|
+
### Platform
|
|
51
|
+
|
|
52
|
+
**Platform Interface** (`IPlatform`):
|
|
53
|
+
|
|
54
|
+
- Component creation and lifecycle
|
|
55
|
+
- DOM manipulation and updates
|
|
56
|
+
- Resource and function registries
|
|
57
|
+
- Logging and debugging
|
|
58
|
+
|
|
59
|
+
> This abstraction allows Arrmatura to theoretically target different platforms (Web, Native, etc.) by providing different platform implementations.
|
|
60
|
+
|
|
61
|
+
### Built-In Components
|
|
62
|
+
|
|
63
|
+
Before creating Arrmatrons, XML templates are compiled into **Manifest Nodes** (`IManifestNode`):
|
|
64
|
+
|
|
65
|
+
Manifest nodes are cached and reused, containing the logic for:
|
|
66
|
+
|
|
67
|
+
- Resolving properties with expressions
|
|
68
|
+
- Creating Arrmatron instances
|
|
69
|
+
- Managing sub-nodes
|
|
70
|
+
|
|
71
|
+
## Data Flow
|
|
72
|
+
|
|
73
|
+
### One-Way Binding
|
|
74
|
+
|
|
75
|
+
Arrmatura uses **one-way data binding** from parent to child:
|
|
76
|
+
|
|
77
|
+
```xml
|
|
78
|
+
<Component id="Parent">
|
|
79
|
+
<Child data="{parentData}" />
|
|
80
|
+
</Component>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
1. Parent's `parentData` changes
|
|
84
|
+
2. Parent's Arrmatron calls `touch()` to redraw
|
|
85
|
+
3. Platform resolves `{parentData}` expression
|
|
86
|
+
4. Child receives updated property
|
|
87
|
+
5. Child redraws if needed
|
|
88
|
+
|
|
89
|
+
### Reactive Updates
|
|
90
|
+
|
|
91
|
+
When component state changes:
|
|
92
|
+
|
|
93
|
+
1. Component calls `up(delta)` with state changes
|
|
94
|
+
2. Async values (Promises) are handled automatically
|
|
95
|
+
3. Connected properties (`@ref.prop`) are tracked
|
|
96
|
+
4. Platform schedules a redraw
|
|
97
|
+
5. Only affected components redraw
|
|
98
|
+
|
|
99
|
+
## Component Lifecycle
|
|
100
|
+
|
|
101
|
+
### Initialization Phase
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
1. Platform.getCompiledNodes(template)
|
|
105
|
+
↓
|
|
106
|
+
2. ManifestNode.createArrmatron(platform, parent, scope)
|
|
107
|
+
↓
|
|
108
|
+
3. Platform.createComponent(descriptor)
|
|
109
|
+
↓
|
|
110
|
+
4. Component.__init() [if defined]
|
|
111
|
+
↓
|
|
112
|
+
5. ManifestNode.resolveInitialProps(arrmatron)
|
|
113
|
+
↓
|
|
114
|
+
6. Create child Arrmatrons recursively
|
|
115
|
+
↓
|
|
116
|
+
7. arrmatron.touch() - first render
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Update Phase
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
1. Component.up(delta) or external state change
|
|
123
|
+
↓
|
|
124
|
+
2. Apply state changes to component
|
|
125
|
+
↓
|
|
126
|
+
3. Handle async values (Promises)
|
|
127
|
+
↓
|
|
128
|
+
4. Call Component.__stateChanged(changes) [if defined]
|
|
129
|
+
↓
|
|
130
|
+
5. arrmatron.touch()
|
|
131
|
+
↓
|
|
132
|
+
6. Platform.redraw(arrmatron, root)
|
|
133
|
+
↓
|
|
134
|
+
7. Resolve properties for all children
|
|
135
|
+
↓
|
|
136
|
+
8. Update DOM (native elements)
|
|
137
|
+
↓
|
|
138
|
+
9. Recursively update affected children
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Cleanup Phase
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
1. root.done()
|
|
145
|
+
↓
|
|
146
|
+
2. Execute deferred cleanup functions
|
|
147
|
+
↓
|
|
148
|
+
3. Remove event listeners
|
|
149
|
+
↓
|
|
150
|
+
4. Cleanup child Arrmatrons
|
|
151
|
+
```
|