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.
Files changed (72) hide show
  1. package/README.md +59 -25
  2. package/dist/index.cjs +4 -0
  3. package/dist/index.js +4 -2
  4. package/docs/architecture.md +151 -0
  5. package/docs/built-ins.md +223 -0
  6. package/docs/cml.md +342 -0
  7. package/index.ts +1 -22
  8. package/package.json +18 -16
  9. package/src/{registry → compiler}/index.ts +23 -22
  10. package/src/controls/Iterative.ts +127 -0
  11. package/src/controls/block.ts +25 -0
  12. package/src/{registry → controls}/composition.ts +9 -15
  13. package/src/controls/conditionals.ts +79 -0
  14. package/src/controls/connector.ts +75 -0
  15. package/src/{registry → controls}/elementary.ts +3 -6
  16. package/src/{registry → controls}/fragment.ts +3 -4
  17. package/src/controls/index.ts +10 -0
  18. package/src/controls/root.ts +47 -0
  19. package/src/controls/routing.ts +45 -0
  20. package/src/{registry → controls}/selection.ts +4 -9
  21. package/src/{registry → controls}/slot.ts +12 -10
  22. package/src/core/Arrmatron.ts +648 -411
  23. package/src/core/Component.ts +108 -53
  24. package/src/core/ManifestNode.ts +295 -141
  25. package/src/core/NativeElement.ts +89 -0
  26. package/src/core/Platform.ts +116 -0
  27. package/src/core/Registry.ts +162 -0
  28. package/src/core/consts.ts +3 -0
  29. package/src/core/launch.ts +18 -0
  30. package/src/expr/Expression.ts +59 -0
  31. package/src/expr/ExpressionParser.ts +216 -0
  32. package/src/expr/ExpressionParserBase.ts +120 -0
  33. package/src/expr/ParserContext.ts +17 -0
  34. package/src/expr/compileEmitterExpression.ts +54 -0
  35. package/src/expr/compilePlaceholder.ts +14 -0
  36. package/src/expr/operations.ts +53 -0
  37. package/src/expr/prepareConnectedProps.ts +16 -0
  38. package/src/expr/resolveExpression.ts +66 -0
  39. package/src/index.ts +8 -0
  40. package/src/types.ts +168 -0
  41. package/src/utils/applyStateChangedToImpl.ts +2 -9
  42. package/src/utils/applyTemplate.ts +20 -0
  43. package/src/utils/asyncValueCall.ts +11 -0
  44. package/src/utils/capitalize.ts +7 -0
  45. package/src/utils/createRegisterTypes.ts +67 -0
  46. package/src/utils/defineCalculatedProperty.ts +48 -0
  47. package/src/utils/defineObjectRef.ts +18 -0
  48. package/src/utils/hashCodeOf.ts +147 -0
  49. package/src/utils/index.ts +9 -0
  50. package/src/utils/isEquals.ts +74 -0
  51. package/src/utils/mapEntries.ts +9 -0
  52. package/src/utils/mergeObject.ts +25 -0
  53. package/src/utils/narrowData.ts +30 -0
  54. package/src/utils/scalarParse.ts +41 -0
  55. package/src/utils/splitTopLevel.ts +28 -0
  56. package/src/utils/stringify.ts +4 -3
  57. package/src/utils/toNativeTree.ts +21 -0
  58. package/src/utils/xmlParse.ts +120 -0
  59. package/dist/index.js.map +0 -7
  60. package/docs/glossary.md +0 -19
  61. package/docs/hello.md +0 -46
  62. package/docs/manual.md +0 -312
  63. package/src/core/resolveExpression.ts +0 -25
  64. package/src/registry/conditionals.ts +0 -77
  65. package/src/registry/connector.ts +0 -47
  66. package/src/registry/iterations.ts +0 -134
  67. package/src/registry/root.ts +0 -48
  68. package/src/registry/routing.ts +0 -32
  69. package/src/utils/FingerprintMashine.ts +0 -128
  70. package/src/utils/compileExpression.ts +0 -215
  71. package/src/utils/objectFingerprint.spec.ts +0 -70
  72. package/types.ts +0 -82
package/README.md CHANGED
@@ -1,41 +1,75 @@
1
1
  # Arrmatura
2
2
 
3
- ## Definitive
3
+ ## What is Arrmatura?
4
4
 
5
- `Arrmatura` is a framework which inherits declarative approach and functional programming.
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
- It comprises of
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
- - extended HTML notation to define components, its composition, behaviour and data flow.
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
- ## Key features and benefits of the platform
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
- The framework is designed to facilitate the creation of web applications
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
- This component composition is achieved through a declarative syntax,
20
- which describes how data flows between components and how it is propagated across the composition.
17
+ ## Key features
21
18
 
22
- This streamlines the development process and makes it easier for developers
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
- Overall, the framework aims to provide a flexible and intuitive way
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
- ## Documentation
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
- - [Manual](docs/manual.md)
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
- ## Getting started for Web
39
+ ### Performance
34
40
 
35
- See [Hello, world](docs/HELLO.md) for starting example.
41
+ What Makes It Fast
36
42
 
37
- ## Examples
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
- - [Emoji List](https://emojis-list.web.app/)
40
- - [Countries List](https://countries-list.web.app/)
41
- - [Game Solver](https://dlitskevich.github.io/solver/) ([source](https://github.com/dlitskevich/solver/tree/master/app))
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
- import{CRootNode as m}from"./src/registry/root";export*from"./src/registry";import{CRootNode as c}from"./src/registry/root";export*from"./src/core/Component";var n=(o,t)=>{let r=new m(t).createArrmatron(o);return r.up({},!0),r};export{c as CRootNode,n as launch};
2
- //# sourceMappingURL=index.js.map
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
+ ```