@reidelsaltres/pureper 0.1.157 → 0.1.162
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/out/foundation/Triplet.d.ts.map +1 -1
- package/out/foundation/Triplet.js +4 -5
- package/out/foundation/Triplet.js.map +1 -1
- package/out/foundation/api/Observer.d.ts +30 -0
- package/out/foundation/api/Observer.d.ts.map +1 -1
- package/out/foundation/api/Observer.js +48 -0
- package/out/foundation/api/Observer.js.map +1 -1
- package/out/foundation/component_api/Component.d.ts +2 -2
- package/out/foundation/component_api/Component.d.ts.map +1 -1
- package/out/foundation/component_api/Component.js.map +1 -1
- package/out/foundation/component_api/UniHtml.d.ts +4 -10
- package/out/foundation/component_api/UniHtml.d.ts.map +1 -1
- package/out/foundation/component_api/UniHtml.js +7 -15
- package/out/foundation/component_api/UniHtml.js.map +1 -1
- package/out/foundation/engine/BalancedParser.d.ts +58 -0
- package/out/foundation/engine/BalancedParser.d.ts.map +1 -0
- package/out/foundation/engine/BalancedParser.js +301 -0
- package/out/foundation/engine/BalancedParser.js.map +1 -0
- package/out/foundation/engine/EscapeHandler.d.ts +27 -0
- package/out/foundation/engine/EscapeHandler.d.ts.map +1 -0
- package/out/foundation/engine/EscapeHandler.js +47 -0
- package/out/foundation/engine/EscapeHandler.js.map +1 -0
- package/out/foundation/engine/Expression.d.ts +83 -0
- package/out/foundation/engine/Expression.d.ts.map +1 -0
- package/out/foundation/engine/Expression.js +256 -0
- package/out/foundation/engine/Expression.js.map +1 -0
- package/out/foundation/engine/Rule.d.ts +85 -0
- package/out/foundation/engine/Rule.d.ts.map +1 -0
- package/out/foundation/engine/Rule.js +69 -0
- package/out/foundation/engine/Rule.js.map +1 -0
- package/out/foundation/engine/Scope.d.ts +61 -0
- package/out/foundation/engine/Scope.d.ts.map +1 -0
- package/out/foundation/engine/Scope.js +156 -0
- package/out/foundation/engine/Scope.js.map +1 -0
- package/out/foundation/engine/TemplateEngine.d.ts +96 -0
- package/out/foundation/engine/TemplateEngine.d.ts.map +1 -0
- package/out/foundation/engine/TemplateEngine.js +235 -0
- package/out/foundation/engine/TemplateEngine.js.map +1 -0
- package/out/foundation/engine/TemplateInstance.d.ts +241 -0
- package/out/foundation/engine/TemplateInstance.d.ts.map +1 -0
- package/out/foundation/engine/TemplateInstance.js +637 -0
- package/out/foundation/engine/TemplateInstance.js.map +1 -0
- package/out/foundation/engine/TemplateInstance.old.d.ts +219 -0
- package/out/foundation/engine/TemplateInstance.old.d.ts.map +1 -0
- package/out/foundation/engine/TemplateInstance.old.js +487 -0
- package/out/foundation/engine/TemplateInstance.old.js.map +1 -0
- package/out/foundation/engine/exceptions/TemplateExceptions.d.ts +21 -0
- package/out/foundation/engine/exceptions/TemplateExceptions.d.ts.map +1 -0
- package/out/foundation/engine/exceptions/TemplateExceptions.js +26 -0
- package/out/foundation/engine/exceptions/TemplateExceptions.js.map +1 -0
- package/out/foundation/engine/index.d.ts +18 -0
- package/out/foundation/engine/index.d.ts.map +1 -0
- package/out/foundation/engine/index.js +19 -0
- package/out/foundation/engine/index.js.map +1 -0
- package/out/foundation/engine/rules/attribute/EventRule.d.ts +22 -0
- package/out/foundation/engine/rules/attribute/EventRule.d.ts.map +1 -0
- package/out/foundation/engine/rules/attribute/EventRule.js +129 -0
- package/out/foundation/engine/rules/attribute/EventRule.js.map +1 -0
- package/out/foundation/engine/rules/attribute/InjectionRule.d.ts +20 -0
- package/out/foundation/engine/rules/attribute/InjectionRule.d.ts.map +1 -0
- package/out/foundation/engine/rules/attribute/InjectionRule.js +108 -0
- package/out/foundation/engine/rules/attribute/InjectionRule.js.map +1 -0
- package/out/foundation/engine/rules/attribute/RefRule.d.ts +23 -0
- package/out/foundation/engine/rules/attribute/RefRule.d.ts.map +1 -0
- package/out/foundation/engine/rules/attribute/RefRule.js +104 -0
- package/out/foundation/engine/rules/attribute/RefRule.js.map +1 -0
- package/out/foundation/engine/rules/syntax/ExpressionRule.d.ts +19 -0
- package/out/foundation/engine/rules/syntax/ExpressionRule.d.ts.map +1 -0
- package/out/foundation/engine/rules/syntax/ExpressionRule.js +82 -0
- package/out/foundation/engine/rules/syntax/ExpressionRule.js.map +1 -0
- package/out/foundation/engine/rules/syntax/ForRule.d.ts +19 -0
- package/out/foundation/engine/rules/syntax/ForRule.d.ts.map +1 -0
- package/out/foundation/engine/rules/syntax/ForRule.js +226 -0
- package/out/foundation/engine/rules/syntax/ForRule.js.map +1 -0
- package/out/foundation/engine/rules/syntax/IfRule.d.ts +17 -0
- package/out/foundation/engine/rules/syntax/IfRule.d.ts.map +1 -0
- package/out/foundation/engine/rules/syntax/IfRule.js +220 -0
- package/out/foundation/engine/rules/syntax/IfRule.js.map +1 -0
- package/out/foundation/worker/Router.d.ts.map +1 -1
- package/out/foundation/worker/Router.js.map +1 -1
- package/out/index.d.ts +2 -0
- package/out/index.d.ts.map +1 -1
- package/out/index.js +2 -0
- package/out/index.js.map +1 -1
- package/package.json +1 -1
- package/src/foundation/Triplet.ts +6 -6
- package/src/foundation/api/Observer.ts +60 -0
- package/src/foundation/component_api/Component.ts +2 -1
- package/src/foundation/component_api/UniHtml.ts +12 -22
- package/src/foundation/engine/BalancedParser.ts +353 -0
- package/src/foundation/engine/EscapeHandler.ts +54 -0
- package/src/foundation/engine/Expression.ts +285 -0
- package/src/foundation/engine/Rule.ts +138 -0
- package/src/foundation/engine/Scope.ts +176 -0
- package/src/foundation/engine/TemplateEngine.ts +318 -0
- package/src/foundation/engine/TemplateInstance.md +110 -0
- package/src/foundation/engine/TemplateInstance.old.ts +673 -0
- package/src/foundation/engine/TemplateInstance.ts +843 -0
- package/src/foundation/engine/exceptions/TemplateExceptions.ts +27 -0
- package/src/foundation/engine/rules/attribute/EventRule.ts +171 -0
- package/src/foundation/engine/rules/attribute/InjectionRule.ts +140 -0
- package/src/foundation/engine/rules/attribute/RefRule.ts +126 -0
- package/src/foundation/engine/rules/syntax/ExpressionRule.ts +102 -0
- package/src/foundation/engine/rules/syntax/ForRule.ts +267 -0
- package/src/foundation/engine/rules/syntax/IfRule.ts +261 -0
- package/src/foundation/worker/Router.ts +1 -1
- package/src/index.ts +8 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { AttributeRule } from '../../Rule.js';
|
|
2
|
+
import Expression from '../../Expression.js';
|
|
3
|
+
/**
|
|
4
|
+
* EventRule - обработка @on[eventName]="expression"
|
|
5
|
+
* Подписывает элемент на событие.
|
|
6
|
+
*/
|
|
7
|
+
export default class EventRule extends AttributeRule {
|
|
8
|
+
name = 'event';
|
|
9
|
+
priority = 30;
|
|
10
|
+
find(template) {
|
|
11
|
+
const results = [];
|
|
12
|
+
// Match @on[eventName]="
|
|
13
|
+
const pattern = /@on\[([a-zA-Z]+)\]\s*=/gi;
|
|
14
|
+
let match;
|
|
15
|
+
while ((match = pattern.exec(template)) !== null) {
|
|
16
|
+
const idx = match.index;
|
|
17
|
+
// Check for @@ escape
|
|
18
|
+
if (idx > 0 && template[idx - 1] === '@') {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const eventName = match[1].toLowerCase();
|
|
22
|
+
// Find quote char after =
|
|
23
|
+
let pos = idx + match[0].length;
|
|
24
|
+
while (pos < template.length && /\s/.test(template[pos])) {
|
|
25
|
+
pos++;
|
|
26
|
+
}
|
|
27
|
+
const quoteChar = template[pos];
|
|
28
|
+
if (quoteChar !== '"' && quoteChar !== "'") {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
// Find matching closing quote
|
|
32
|
+
const contentStart = pos + 1;
|
|
33
|
+
pos++;
|
|
34
|
+
while (pos < template.length && template[pos] !== quoteChar) {
|
|
35
|
+
pos++;
|
|
36
|
+
}
|
|
37
|
+
if (pos >= template.length)
|
|
38
|
+
continue;
|
|
39
|
+
const content = template.slice(contentStart, pos);
|
|
40
|
+
const fullMatch = template.slice(idx, pos + 1);
|
|
41
|
+
results.push({
|
|
42
|
+
fullMatch,
|
|
43
|
+
start: idx,
|
|
44
|
+
end: pos + 1,
|
|
45
|
+
data: {
|
|
46
|
+
eventName,
|
|
47
|
+
expression: content,
|
|
48
|
+
attributeMatch: fullMatch
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return results;
|
|
53
|
+
}
|
|
54
|
+
execute(match, scope) {
|
|
55
|
+
const data = match.data;
|
|
56
|
+
// Generate data attribute for later DOM binding
|
|
57
|
+
// Actual event binding happens in postprocessing
|
|
58
|
+
const encodedExpr = encodeURIComponent(data.expression);
|
|
59
|
+
return {
|
|
60
|
+
output: `data-event-${data.eventName}="${encodedExpr}"`,
|
|
61
|
+
observables: []
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Постобработка: привязать события к элементам
|
|
66
|
+
*/
|
|
67
|
+
static bindEvents(element, scope) {
|
|
68
|
+
const unbinders = [];
|
|
69
|
+
// Find all data-event-* attributes
|
|
70
|
+
const attributes = Array.from(element.attributes);
|
|
71
|
+
for (const attr of attributes) {
|
|
72
|
+
if (attr.name.startsWith('data-event-')) {
|
|
73
|
+
const eventName = attr.name.slice('data-event-'.length);
|
|
74
|
+
const exprCode = decodeURIComponent(attr.value);
|
|
75
|
+
const handler = (event) => {
|
|
76
|
+
// Create local scope with event
|
|
77
|
+
const localScope = scope.createChild({ event });
|
|
78
|
+
const expr = new Expression(exprCode);
|
|
79
|
+
try {
|
|
80
|
+
expr.execute(localScope);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
console.error(`[EventRule] Error executing handler for ${eventName}:`, error);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
element.addEventListener(eventName, handler);
|
|
87
|
+
unbinders.push(() => element.removeEventListener(eventName, handler));
|
|
88
|
+
// Optionally remove the data attribute
|
|
89
|
+
// element.removeAttribute(attr.name);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return unbinders;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Привязать событие с поддержкой Observable
|
|
96
|
+
*/
|
|
97
|
+
static bindEventWithObservable(element, eventName, exprCode, scope) {
|
|
98
|
+
let currentHandler = null;
|
|
99
|
+
const setupHandler = () => {
|
|
100
|
+
// Remove old handler if exists
|
|
101
|
+
if (currentHandler) {
|
|
102
|
+
element.removeEventListener(eventName, currentHandler);
|
|
103
|
+
}
|
|
104
|
+
currentHandler = (event) => {
|
|
105
|
+
const localScope = scope.createChild({ event });
|
|
106
|
+
const expr = new Expression(exprCode);
|
|
107
|
+
try {
|
|
108
|
+
const result = expr.execute(localScope);
|
|
109
|
+
// If result is Observable, handle it
|
|
110
|
+
if (result && typeof result === 'object' && typeof result.subscribe === 'function') {
|
|
111
|
+
// Re-setup handler when Observable changes
|
|
112
|
+
result.subscribe(() => setupHandler());
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error(`[EventRule] Error executing handler for ${eventName}:`, error);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
element.addEventListener(eventName, currentHandler);
|
|
120
|
+
};
|
|
121
|
+
setupHandler();
|
|
122
|
+
return () => {
|
|
123
|
+
if (currentHandler) {
|
|
124
|
+
element.removeEventListener(eventName, currentHandler);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=EventRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventRule.js","sourceRoot":"","sources":["../../../../../src/foundation/engine/rules/attribute/EventRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG9C,OAAO,UAAU,MAAM,qBAAqB,CAAC;AAU7C;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,aAAa;IAChC,IAAI,GAAG,OAAO,CAAC;IACf,QAAQ,GAAG,EAAE,CAAC;IAEvB,IAAI,CAAC,QAAgB;QACxB,MAAM,OAAO,GAAgB,EAAE,CAAC;QAChC,yBAAyB;QACzB,MAAM,OAAO,GAAG,0BAA0B,CAAC;QAC3C,IAAI,KAA6B,CAAC;QAElC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC/C,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC;YAExB,sBAAsB;YACtB,IAAI,GAAG,GAAG,CAAC,IAAI,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACvC,SAAS;YACb,CAAC;YAED,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YAEzC,0BAA0B;YAC1B,IAAI,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAChC,OAAO,GAAG,GAAG,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBACvD,GAAG,EAAE,CAAC;YACV,CAAC;YAED,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YAChC,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;gBACzC,SAAS;YACb,CAAC;YAED,8BAA8B;YAC9B,MAAM,YAAY,GAAG,GAAG,GAAG,CAAC,CAAC;YAC7B,GAAG,EAAE,CAAC;YACN,OAAO,GAAG,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC1D,GAAG,EAAE,CAAC;YACV,CAAC;YAED,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM;gBAAE,SAAS;YAErC,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YAClD,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;YAE/C,OAAO,CAAC,IAAI,CAAC;gBACT,SAAS;gBACT,KAAK,EAAE,GAAG;gBACV,GAAG,EAAE,GAAG,GAAG,CAAC;gBACZ,IAAI,EAAE;oBACF,SAAS;oBACT,UAAU,EAAE,OAAO;oBACnB,cAAc,EAAE,SAAS;iBAC5B;aACJ,CAAC,CAAC;QACP,CAAC;QAED,OAAO,OAAO,CAAC;IACnB,CAAC;IAEM,OAAO,CAAC,KAAgB,EAAE,KAAY;QACzC,MAAM,IAAI,GAAI,KAAoB,CAAC,IAAI,CAAC;QAExC,gDAAgD;QAChD,iDAAiD;QACjD,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAExD,OAAO;YACH,MAAM,EAAE,cAAc,IAAI,CAAC,SAAS,KAAK,WAAW,GAAG;YACvD,WAAW,EAAE,EAAE;SAClB,CAAC;IACN,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,UAAU,CAAC,OAAgB,EAAE,KAAY;QACnD,MAAM,SAAS,GAAmB,EAAE,CAAC;QAErC,mCAAmC;QACnC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAElD,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;gBACtC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;gBACxD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAEhD,MAAM,OAAO,GAAG,CAAC,KAAY,EAAE,EAAE;oBAC7B,gCAAgC;oBAChC,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;oBAChD,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;oBAEtC,IAAI,CAAC;wBACD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;oBAC7B,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACb,OAAO,CAAC,KAAK,CAAC,2CAA2C,SAAS,GAAG,EAAE,KAAK,CAAC,CAAC;oBAClF,CAAC;gBACL,CAAC,CAAC;gBAEF,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBAC7C,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;gBAEtE,uCAAuC;gBACvC,sCAAsC;YAC1C,CAAC;QACL,CAAC;QAED,OAAO,SAAS,CAAC;IACrB,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,uBAAuB,CACjC,OAAgB,EAChB,SAAiB,EACjB,QAAgB,EAChB,KAAY;QAEZ,IAAI,cAAc,GAAoC,IAAI,CAAC;QAE3D,MAAM,YAAY,GAAG,GAAG,EAAE;YACtB,+BAA+B;YAC/B,IAAI,cAAc,EAAE,CAAC;gBACjB,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;YAC3D,CAAC;YAED,cAAc,GAAG,CAAC,KAAY,EAAE,EAAE;gBAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;gBAChD,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;gBAEtC,IAAI,CAAC;oBACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;oBAExC,qCAAqC;oBACrC,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;wBACjF,2CAA2C;wBAC3C,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;oBAC3C,CAAC;gBACL,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,2CAA2C,SAAS,GAAG,EAAE,KAAK,CAAC,CAAC;gBAClF,CAAC;YACL,CAAC,CAAC;YAEF,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QACxD,CAAC,CAAC;QAEF,YAAY,EAAE,CAAC;QAEf,OAAO,GAAG,EAAE;YACR,IAAI,cAAc,EAAE,CAAC;gBACjB,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;YAC3D,CAAC;QACL,CAAC,CAAC;IACN,CAAC;CACJ"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AttributeRule } from '../../Rule.js';
|
|
2
|
+
import type { RuleMatch, RuleResult } from '../../Rule.js';
|
|
3
|
+
import Scope from '../../Scope.js';
|
|
4
|
+
/**
|
|
5
|
+
* InjectionRule - обработка @injection[type]="expression"
|
|
6
|
+
* Инжектирует элемент в целевой элемент (найденный по @[ref]).
|
|
7
|
+
* type: 'head' = prepend, 'tail' = append
|
|
8
|
+
*/
|
|
9
|
+
export default class InjectionRule extends AttributeRule {
|
|
10
|
+
readonly name = "injection";
|
|
11
|
+
readonly priority = 200;
|
|
12
|
+
find(template: string): RuleMatch[];
|
|
13
|
+
execute(match: RuleMatch, scope: Scope): RuleResult;
|
|
14
|
+
supportsObservable(): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Постобработка: выполнить инжекцию элементов
|
|
17
|
+
*/
|
|
18
|
+
static processInjections(root: Element | DocumentFragment, scope: Scope): void;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=InjectionRule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InjectionRule.d.ts","sourceRoot":"","sources":["../../../../../src/foundation/engine/rules/attribute/InjectionRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,KAAK,MAAM,gBAAgB,CAAC;AAYnC;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,aAAa;IACpD,SAAgB,IAAI,eAAe;IACnC,SAAgB,QAAQ,OAAO;IAExB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE;IAsDnC,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,UAAU;IAyBnD,kBAAkB,IAAI,OAAO;IAIpC;;OAEG;WACW,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;CA8BxF"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { AttributeRule } from '../../Rule.js';
|
|
2
|
+
import Expression from '../../Expression.js';
|
|
3
|
+
import { InvalidDynamicRuleUsage } from '../../exceptions/TemplateExceptions.js';
|
|
4
|
+
/**
|
|
5
|
+
* InjectionRule - обработка @injection[type]="expression"
|
|
6
|
+
* Инжектирует элемент в целевой элемент (найденный по @[ref]).
|
|
7
|
+
* type: 'head' = prepend, 'tail' = append
|
|
8
|
+
*/
|
|
9
|
+
export default class InjectionRule extends AttributeRule {
|
|
10
|
+
name = 'injection';
|
|
11
|
+
priority = 200; // Выполняется в самом конце
|
|
12
|
+
find(template) {
|
|
13
|
+
const results = [];
|
|
14
|
+
// Match @injection[head] or @injection[tail]
|
|
15
|
+
const pattern = /@injection\[(head|tail)\]\s*=/gi;
|
|
16
|
+
let match;
|
|
17
|
+
while ((match = pattern.exec(template)) !== null) {
|
|
18
|
+
const idx = match.index;
|
|
19
|
+
// Check for @@ escape
|
|
20
|
+
if (idx > 0 && template[idx - 1] === '@') {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const injectionType = match[1].toLowerCase();
|
|
24
|
+
// Find quote char after =
|
|
25
|
+
let pos = idx + match[0].length;
|
|
26
|
+
while (pos < template.length && /\s/.test(template[pos])) {
|
|
27
|
+
pos++;
|
|
28
|
+
}
|
|
29
|
+
const quoteChar = template[pos];
|
|
30
|
+
if (quoteChar !== '"' && quoteChar !== "'") {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
// Find matching closing quote
|
|
34
|
+
const contentStart = pos + 1;
|
|
35
|
+
pos++;
|
|
36
|
+
while (pos < template.length && template[pos] !== quoteChar) {
|
|
37
|
+
pos++;
|
|
38
|
+
}
|
|
39
|
+
if (pos >= template.length)
|
|
40
|
+
continue;
|
|
41
|
+
const content = template.slice(contentStart, pos);
|
|
42
|
+
const fullMatch = template.slice(idx, pos + 1);
|
|
43
|
+
results.push({
|
|
44
|
+
fullMatch,
|
|
45
|
+
start: idx,
|
|
46
|
+
end: pos + 1,
|
|
47
|
+
data: {
|
|
48
|
+
type: injectionType,
|
|
49
|
+
expression: content,
|
|
50
|
+
attributeMatch: fullMatch
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return results;
|
|
55
|
+
}
|
|
56
|
+
execute(match, scope) {
|
|
57
|
+
const data = match.data;
|
|
58
|
+
const expr = new Expression(data.expression);
|
|
59
|
+
const targetRefName = expr.execute(scope);
|
|
60
|
+
// Check if Observable - not allowed for @injection
|
|
61
|
+
if (targetRefName && typeof targetRefName === 'object' && typeof targetRefName.subscribe === 'function') {
|
|
62
|
+
throw new InvalidDynamicRuleUsage('@injection', '@injection does not support Observable values. The target reference must be static.');
|
|
63
|
+
}
|
|
64
|
+
if (typeof targetRefName !== 'string') {
|
|
65
|
+
console.error(`[InjectionRule] Expression must return a string (reference name), got: ${typeof targetRefName}`);
|
|
66
|
+
return { output: '' };
|
|
67
|
+
}
|
|
68
|
+
// Store injection info for postprocessing
|
|
69
|
+
const encodedTarget = encodeURIComponent(targetRefName);
|
|
70
|
+
return {
|
|
71
|
+
output: `data-injection-type="${data.type}" data-injection-target="${encodedTarget}"`,
|
|
72
|
+
observables: []
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
supportsObservable() {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Постобработка: выполнить инжекцию элементов
|
|
80
|
+
*/
|
|
81
|
+
static processInjections(root, scope) {
|
|
82
|
+
// Find all elements with injection attributes
|
|
83
|
+
const injectElements = root.querySelectorAll('[data-injection-type][data-injection-target]');
|
|
84
|
+
for (const element of Array.from(injectElements)) {
|
|
85
|
+
const type = element.getAttribute('data-injection-type');
|
|
86
|
+
const targetRefName = decodeURIComponent(element.getAttribute('data-injection-target') || '');
|
|
87
|
+
if (!targetRefName)
|
|
88
|
+
continue;
|
|
89
|
+
// Get target element from scope
|
|
90
|
+
const targetElement = scope.get(targetRefName);
|
|
91
|
+
if (!targetElement || !(targetElement instanceof Element)) {
|
|
92
|
+
console.warn(`[InjectionRule] Target element "${targetRefName}" not found in scope or is not an Element`);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
// Remove injection attributes
|
|
96
|
+
element.removeAttribute('data-injection-type');
|
|
97
|
+
element.removeAttribute('data-injection-target');
|
|
98
|
+
// Perform injection
|
|
99
|
+
if (type === 'head') {
|
|
100
|
+
targetElement.prepend(element);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
targetElement.append(element);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=InjectionRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InjectionRule.js","sourceRoot":"","sources":["../../../../../src/foundation/engine/rules/attribute/InjectionRule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AttributeRule } from '../../Rule.js';
|
|
2
|
+
import type { RuleMatch, RuleResult } from '../../Rule.js';
|
|
3
|
+
import Scope from '../../Scope.js';
|
|
4
|
+
/**
|
|
5
|
+
* RefRule - обработка @[ref]="expression"
|
|
6
|
+
* Добавляет HTML элемент в Scope под указанным именем.
|
|
7
|
+
*/
|
|
8
|
+
export default class RefRule extends AttributeRule {
|
|
9
|
+
readonly name = "ref";
|
|
10
|
+
readonly priority = 5;
|
|
11
|
+
find(template: string): RuleMatch[];
|
|
12
|
+
execute(match: RuleMatch, scope: Scope): RuleResult;
|
|
13
|
+
supportsObservable(): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Постобработка: привязать реальный элемент к Scope
|
|
16
|
+
*/
|
|
17
|
+
static bindElement(element: Element, refName: string, scope: Scope): void;
|
|
18
|
+
/**
|
|
19
|
+
* Очистка: установить ref в null если элемент удалён
|
|
20
|
+
*/
|
|
21
|
+
static unbindElement(refName: string, scope: Scope): void;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=RefRule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RefRule.d.ts","sourceRoot":"","sources":["../../../../../src/foundation/engine/rules/attribute/RefRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,KAAK,MAAM,gBAAgB,CAAC;AAInC;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,aAAa;IAC9C,SAAgB,IAAI,SAAS;IAC7B,SAAgB,QAAQ,KAAK;IAEtB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE;IA6DnC,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,UAAU;IA+BnD,kBAAkB,IAAI,OAAO;IAIpC;;OAEG;WACW,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAIhF;;OAEG;WACW,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;CAKnE"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { AttributeRule } from '../../Rule.js';
|
|
2
|
+
import Expression from '../../Expression.js';
|
|
3
|
+
import { InvalidDynamicRuleUsage } from '../../exceptions/TemplateExceptions.js';
|
|
4
|
+
/**
|
|
5
|
+
* RefRule - обработка @[ref]="expression"
|
|
6
|
+
* Добавляет HTML элемент в Scope под указанным именем.
|
|
7
|
+
*/
|
|
8
|
+
export default class RefRule extends AttributeRule {
|
|
9
|
+
name = 'ref';
|
|
10
|
+
priority = 5; // Выполняется очень рано
|
|
11
|
+
find(template) {
|
|
12
|
+
const results = [];
|
|
13
|
+
// Match @[ref]=" or @[ref]='
|
|
14
|
+
const opener = '@[ref]=';
|
|
15
|
+
let i = 0;
|
|
16
|
+
while (i < template.length) {
|
|
17
|
+
const idx = template.toLowerCase().indexOf(opener.toLowerCase(), i);
|
|
18
|
+
if (idx === -1)
|
|
19
|
+
break;
|
|
20
|
+
// Check for @@ escape
|
|
21
|
+
if (idx > 0 && template[idx - 1] === '@') {
|
|
22
|
+
i = idx + 1;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
// Find quote char after =
|
|
26
|
+
let pos = idx + opener.length;
|
|
27
|
+
while (pos < template.length && /\s/.test(template[pos])) {
|
|
28
|
+
pos++;
|
|
29
|
+
}
|
|
30
|
+
const quoteChar = template[pos];
|
|
31
|
+
if (quoteChar !== '"' && quoteChar !== "'") {
|
|
32
|
+
i = idx + 1;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// Find matching closing quote (handle nested quotes)
|
|
36
|
+
const contentStart = pos + 1;
|
|
37
|
+
pos++;
|
|
38
|
+
// Simple: find the closing quote that matches
|
|
39
|
+
while (pos < template.length && template[pos] !== quoteChar) {
|
|
40
|
+
pos++;
|
|
41
|
+
}
|
|
42
|
+
if (pos >= template.length) {
|
|
43
|
+
i = idx + 1;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const content = template.slice(contentStart, pos);
|
|
47
|
+
const fullMatch = template.slice(idx, pos + 1);
|
|
48
|
+
results.push({
|
|
49
|
+
fullMatch,
|
|
50
|
+
start: idx,
|
|
51
|
+
end: pos + 1,
|
|
52
|
+
data: {
|
|
53
|
+
expression: content,
|
|
54
|
+
attributeMatch: fullMatch
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
i = pos + 1;
|
|
58
|
+
}
|
|
59
|
+
return results;
|
|
60
|
+
}
|
|
61
|
+
execute(match, scope) {
|
|
62
|
+
const exprCode = match.data?.expression;
|
|
63
|
+
const expr = new Expression(exprCode);
|
|
64
|
+
const refName = expr.execute(scope);
|
|
65
|
+
// Check if Observable - not allowed for @[ref]
|
|
66
|
+
if (refName && typeof refName === 'object' && typeof refName.subscribe === 'function') {
|
|
67
|
+
throw new InvalidDynamicRuleUsage('@[ref]', '@[ref] does not support Observable values. The reference name must be static.');
|
|
68
|
+
}
|
|
69
|
+
if (typeof refName !== 'string') {
|
|
70
|
+
console.error(`[RefRule] Expression must return a string (variable name), got: ${typeof refName}`);
|
|
71
|
+
return { output: '' };
|
|
72
|
+
}
|
|
73
|
+
// Сразу регистрируем ref в scope с null значением
|
|
74
|
+
// Будет заполнен реальным элементом при bindRefs()
|
|
75
|
+
if (!scope.has(refName)) {
|
|
76
|
+
scope.set(refName, null);
|
|
77
|
+
}
|
|
78
|
+
// Store placeholder - actual element will be set during DOM processing
|
|
79
|
+
// For now, return the attribute without the @[ref] syntax
|
|
80
|
+
return {
|
|
81
|
+
output: `data-ref="${refName}"`,
|
|
82
|
+
observables: [],
|
|
83
|
+
data: { refName } // Сохраняем имя ref для быстрого доступа
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
supportsObservable() {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Постобработка: привязать реальный элемент к Scope
|
|
91
|
+
*/
|
|
92
|
+
static bindElement(element, refName, scope) {
|
|
93
|
+
scope.set(refName, element);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Очистка: установить ref в null если элемент удалён
|
|
97
|
+
*/
|
|
98
|
+
static unbindElement(refName, scope) {
|
|
99
|
+
if (scope.has(refName)) {
|
|
100
|
+
scope.set(refName, null);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=RefRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RefRule.js","sourceRoot":"","sources":["../../../../../src/foundation/engine/rules/attribute/RefRule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SyntaxRule } from '../../Rule.js';
|
|
2
|
+
import type { RuleMatch, RuleResult } from '../../Rule.js';
|
|
3
|
+
import Scope from '../../Scope.js';
|
|
4
|
+
/**
|
|
5
|
+
* ExpressionRule - обработка @(Expression)
|
|
6
|
+
* Выводит результат выражения как строку.
|
|
7
|
+
* Автоматически отслеживает Observable и разворачивает их значения.
|
|
8
|
+
*/
|
|
9
|
+
export default class ExpressionRule extends SyntaxRule {
|
|
10
|
+
readonly name = "expression";
|
|
11
|
+
readonly priority = 50;
|
|
12
|
+
find(template: string): RuleMatch[];
|
|
13
|
+
execute(match: RuleMatch, scope: Scope): RuleResult;
|
|
14
|
+
/**
|
|
15
|
+
* Асинхронная версия execute
|
|
16
|
+
*/
|
|
17
|
+
executeAsync(match: RuleMatch, scope: Scope): Promise<RuleResult>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=ExpressionRule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpressionRule.d.ts","sourceRoot":"","sources":["../../../../../src/foundation/engine/rules/syntax/ExpressionRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,KAAK,MAAM,gBAAgB,CAAC;AAKnC;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,UAAU;IAClD,SAAgB,IAAI,gBAAgB;IACpC,SAAgB,QAAQ,MAAM;IAEvB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE;IAWnC,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,UAAU;IA+C1D;;OAEG;IACU,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;CAwBjF"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { SyntaxRule } from '../../Rule.js';
|
|
2
|
+
import Expression from '../../Expression.js';
|
|
3
|
+
import BalancedParser from '../../BalancedParser.js';
|
|
4
|
+
import { isObservable } from '../../../api/Observer.js';
|
|
5
|
+
/**
|
|
6
|
+
* ExpressionRule - обработка @(Expression)
|
|
7
|
+
* Выводит результат выражения как строку.
|
|
8
|
+
* Автоматически отслеживает Observable и разворачивает их значения.
|
|
9
|
+
*/
|
|
10
|
+
export default class ExpressionRule extends SyntaxRule {
|
|
11
|
+
name = 'expression';
|
|
12
|
+
priority = 50; // Выполняется после блочных правил
|
|
13
|
+
find(template) {
|
|
14
|
+
const matches = BalancedParser.parseExpressions(template);
|
|
15
|
+
return matches.map(m => ({
|
|
16
|
+
fullMatch: template.slice(m.start, m.end),
|
|
17
|
+
start: m.start,
|
|
18
|
+
end: m.end,
|
|
19
|
+
data: { expression: m.content }
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
execute(match, scope) {
|
|
23
|
+
const code = match.data?.expression;
|
|
24
|
+
if (!code || code.trim() === '') {
|
|
25
|
+
return { output: '' };
|
|
26
|
+
}
|
|
27
|
+
const expr = new Expression(code);
|
|
28
|
+
// Находим Observable, используемые в выражении
|
|
29
|
+
const observables = expr.findObservables(scope);
|
|
30
|
+
// Check for async
|
|
31
|
+
if (expr.isAsyncExpression()) {
|
|
32
|
+
// Return promise wrapper - engine should handle this
|
|
33
|
+
const promise = expr.executeAsync(scope).then(result => {
|
|
34
|
+
if (result === undefined || result === null) {
|
|
35
|
+
return '';
|
|
36
|
+
}
|
|
37
|
+
return String(result);
|
|
38
|
+
});
|
|
39
|
+
// For now, return placeholder - proper async handling in engine
|
|
40
|
+
return {
|
|
41
|
+
output: '',
|
|
42
|
+
observables,
|
|
43
|
+
children: []
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const result = expr.execute(scope);
|
|
47
|
+
// Если результат сам Observable (например @(counter)), отслеживаем его
|
|
48
|
+
if (isObservable(result)) {
|
|
49
|
+
return {
|
|
50
|
+
output: String(result.getObject?.() ?? result),
|
|
51
|
+
observables: [...observables, result]
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (result === undefined || result === null) {
|
|
55
|
+
return { output: '', observables };
|
|
56
|
+
}
|
|
57
|
+
return { output: String(result), observables };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Асинхронная версия execute
|
|
61
|
+
*/
|
|
62
|
+
async executeAsync(match, scope) {
|
|
63
|
+
const code = match.data?.expression;
|
|
64
|
+
if (!code || code.trim() === '') {
|
|
65
|
+
return { output: '' };
|
|
66
|
+
}
|
|
67
|
+
const expr = new Expression(code);
|
|
68
|
+
const observables = expr.findObservables(scope);
|
|
69
|
+
const result = await expr.executeAsync(scope);
|
|
70
|
+
if (isObservable(result)) {
|
|
71
|
+
return {
|
|
72
|
+
output: String(result.getObject?.() ?? result),
|
|
73
|
+
observables: [...observables, result]
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (result === undefined || result === null) {
|
|
77
|
+
return { output: '', observables };
|
|
78
|
+
}
|
|
79
|
+
return { output: String(result), observables };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=ExpressionRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpressionRule.js","sourceRoot":"","sources":["../../../../../src/foundation/engine/rules/syntax/ExpressionRule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SyntaxRule } from '../../Rule.js';
|
|
2
|
+
import type { RuleMatch, RuleResult } from '../../Rule.js';
|
|
3
|
+
import Scope from '../../Scope.js';
|
|
4
|
+
/**
|
|
5
|
+
* ForRule - обработка @for
|
|
6
|
+
* Варианты:
|
|
7
|
+
* 1. @for(item in collection) { ... }
|
|
8
|
+
* 2. @for(idx, item in collection) { ... }
|
|
9
|
+
* 3. @for(i in 5) { ... } - числовая итерация 0..4
|
|
10
|
+
*/
|
|
11
|
+
export default class ForRule extends SyntaxRule {
|
|
12
|
+
readonly name = "for";
|
|
13
|
+
readonly priority = 10;
|
|
14
|
+
find(template: string): RuleMatch[];
|
|
15
|
+
private parseForStatement;
|
|
16
|
+
private skipString;
|
|
17
|
+
execute(match: RuleMatch, scope: Scope, engine?: any): RuleResult;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=ForRule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ForRule.d.ts","sourceRoot":"","sources":["../../../../../src/foundation/engine/rules/syntax/ForRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,KAAK,MAAM,gBAAgB,CAAC;AAkBnC;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,UAAU;IAC3C,SAAgB,IAAI,SAAS;IAC7B,SAAgB,QAAQ,MAAM;IAEvB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE;IAqC1C,OAAO,CAAC,iBAAiB;IAwFzB,OAAO,CAAC,UAAU;IAeX,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,UAAU;CA+F3E"}
|