vsn 0.1.61 → 0.1.64
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/demo/demo.html +9 -8
- package/demo/vsn.js +2 -2
- package/demo/xhr.html +30 -5
- package/dist/AST/ClassNode.d.ts +4 -1
- package/dist/AST/ClassNode.js +251 -0
- package/dist/AST/ClassNode.js.map +1 -0
- package/dist/AST/FunctionCallNode.js +48 -10
- package/dist/AST/FunctionCallNode.js.map +1 -1
- package/dist/AST/FunctionNode.d.ts +2 -1
- package/dist/AST/FunctionNode.js +16 -4
- package/dist/AST/FunctionNode.js.map +1 -1
- package/dist/AST/OnNode.d.ts +9 -0
- package/dist/{attributes/ClassConstructor.js → AST/OnNode.js} +25 -40
- package/dist/AST/OnNode.js.map +1 -0
- package/dist/AST.d.ts +48 -47
- package/dist/AST.js +68 -46
- package/dist/AST.js.map +1 -1
- package/dist/DOM.d.ts +0 -2
- package/dist/DOM.js +55 -36
- package/dist/DOM.js.map +1 -1
- package/dist/Registry.d.ts +1 -0
- package/dist/Registry.js +8 -11
- package/dist/Registry.js.map +1 -1
- package/dist/Scope.js +15 -1
- package/dist/Scope.js.map +1 -1
- package/dist/Tag.d.ts +2 -0
- package/dist/Tag.js +12 -0
- package/dist/Tag.js.map +1 -1
- package/dist/attributes/ControllerAttribute.js +78 -2
- package/dist/attributes/ControllerAttribute.js.map +1 -1
- package/dist/attributes/ListItem.js +1 -1
- package/dist/attributes/ListItem.js.map +1 -1
- package/dist/attributes/ModelAttribute.js +2 -2
- package/dist/attributes/ModelAttribute.js.map +1 -1
- package/dist/attributes/ScopeAttribute.js +6 -2
- package/dist/attributes/ScopeAttribute.js.map +1 -1
- package/dist/attributes/SetAttribute.js +9 -6
- package/dist/attributes/SetAttribute.js.map +1 -1
- package/dist/helpers/ElementHelper.js +6 -0
- package/dist/helpers/ElementHelper.js.map +1 -1
- package/dist/vsn.js +3 -3
- package/dist/vsn.js.map +1 -1
- package/package.json +1 -1
- package/src/AST/ClassNode.ts +74 -2
- package/src/AST/FunctionCallNode.ts +16 -9
- package/src/AST/FunctionNode.ts +6 -2
- package/src/AST/OnNode.ts +18 -0
- package/src/AST.ts +10 -0
- package/src/DOM.ts +11 -16
- package/src/Registry.ts +4 -0
- package/src/Tag.ts +11 -0
- package/src/helpers/ElementHelper.ts +6 -0
- package/dist/attributes/ClassConstructor.d.ts +0 -10
- package/dist/attributes/ClassConstructor.js.map +0 -1
- package/dist/vsn.min.js +0 -2
package/src/AST/ClassNode.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {Scope} from "../Scope";
|
|
2
2
|
import {DOM} from "../DOM";
|
|
3
3
|
import {Tag} from "../Tag";
|
|
4
|
-
import {
|
|
4
|
+
import {Token, TokenType, Tree, TreeNode} from "../AST";
|
|
5
5
|
import {Node} from "./Node";
|
|
6
6
|
import {BlockNode} from "./BlockNode";
|
|
7
7
|
import {Registry} from "../Registry";
|
|
8
|
+
import {OnNode} from "./OnNode";
|
|
8
9
|
|
|
9
10
|
export class ClassNode extends Node implements TreeNode {
|
|
10
11
|
public static readonly classes: {[name: string]: ClassNode} = {};
|
|
@@ -23,11 +24,52 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
23
24
|
ClassNode.classes[this.name] = this;
|
|
24
25
|
await this.block.prepare(this.classScope, dom, tag);
|
|
25
26
|
Registry.class(this);
|
|
27
|
+
const hasConstructor = this.classScope.has('construct');
|
|
28
|
+
|
|
29
|
+
for (const element of Array.from(dom.querySelectorAll(`.${this.name}`))) {
|
|
30
|
+
const tag: Tag = await dom.getTagForElement(element as HTMLElement, true);
|
|
31
|
+
if (tag) {
|
|
32
|
+
await this.prepareTag(tag, dom, hasConstructor);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
26
35
|
}
|
|
27
36
|
|
|
28
|
-
public async prepareTag(tag: Tag, dom: DOM) {
|
|
37
|
+
public async prepareTag(tag: Tag, dom: DOM, hasConstructor: boolean | null = null) {
|
|
38
|
+
if (hasConstructor === null)
|
|
39
|
+
hasConstructor = this.classScope.has('construct');
|
|
40
|
+
|
|
29
41
|
tag.createScope(true);
|
|
30
42
|
await this.block.prepare(tag.scope, dom, tag);
|
|
43
|
+
if (hasConstructor) {
|
|
44
|
+
const fnc = this.classScope.get('construct');
|
|
45
|
+
(await fnc.evaluate(tag.scope, dom, tag))();
|
|
46
|
+
}
|
|
47
|
+
/*
|
|
48
|
+
for (const key of this.classScope.keys) {
|
|
49
|
+
if (this.classScope.get(key) instanceof OnNode) {
|
|
50
|
+
const on = this.classScope.get(key) as OnNode;
|
|
51
|
+
tag.addEventHandler(on.name, [], await on.getFunction(tag.scope, dom, tag), on);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
*/
|
|
55
|
+
tag.preppedClasses.push(this.name);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public async tearDownTag(tag: Tag, dom: DOM, hasDeconstructor: boolean | null = null) {
|
|
59
|
+
if (hasDeconstructor === null)
|
|
60
|
+
hasDeconstructor = this.classScope.has('deconstruct');
|
|
61
|
+
|
|
62
|
+
if (hasDeconstructor) {
|
|
63
|
+
const fnc = this.classScope.get('deconstruct');
|
|
64
|
+
(await fnc.evaluate(tag.scope, dom, tag))();
|
|
65
|
+
}
|
|
66
|
+
for (const key of this.classScope.keys) {
|
|
67
|
+
if (this.classScope.get(key) instanceof OnNode) {
|
|
68
|
+
const on = this.classScope.get(key) as OnNode;
|
|
69
|
+
tag.removeContextEventHandlers(on);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
tag.preppedClasses.splice(tag.preppedClasses.indexOf(this.name), 1);
|
|
31
73
|
}
|
|
32
74
|
|
|
33
75
|
public async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
|
|
@@ -46,4 +88,34 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
46
88
|
const block = Tree.processTokens(Tree.getNextStatementTokens(tokens, true, true));
|
|
47
89
|
return new ClassNode(name, block);
|
|
48
90
|
}
|
|
91
|
+
|
|
92
|
+
public static async checkForClassChanges(element: HTMLElement, dom: DOM, tag: Tag = null) {
|
|
93
|
+
const classes: string[] = Array.from(element.classList);
|
|
94
|
+
let addedClasses: string[] = classes.filter(c => Registry.instance.classes.has(c));
|
|
95
|
+
let removedClasses: string[] = [];
|
|
96
|
+
if (tag) {
|
|
97
|
+
addedClasses = addedClasses.filter(c => !tag.preppedClasses.includes(c));
|
|
98
|
+
removedClasses = tag.preppedClasses.filter(c => !classes.includes(c));
|
|
99
|
+
} else {
|
|
100
|
+
tag = await dom.getTagForElement(element, true);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
for (const addedClass of addedClasses) {
|
|
104
|
+
const classNode: ClassNode = Registry.instance.classes.getSynchronous(addedClass);
|
|
105
|
+
if (classNode) {
|
|
106
|
+
await classNode.prepareTag(tag, dom);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
for (const removedClass of removedClasses) {
|
|
111
|
+
const classNode: ClassNode = Registry.instance.classes.getSynchronous(removedClass);
|
|
112
|
+
if (classNode) {
|
|
113
|
+
await classNode.tearDownTag(tag, dom);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public static isClass(cls: string): boolean {
|
|
119
|
+
return this.classes[cls] instanceof ClassNode;
|
|
120
|
+
}
|
|
49
121
|
}
|
|
@@ -6,7 +6,6 @@ import {Node} from "./Node";
|
|
|
6
6
|
import {FunctionArgumentNode} from "./FunctionArgumentNode";
|
|
7
7
|
import {ScopeMemberNode} from "./ScopeMemberNode";
|
|
8
8
|
import {FunctionNode} from "./FunctionNode";
|
|
9
|
-
import {ClassNode} from "./ClassNode";
|
|
10
9
|
import {Registry} from "../Registry";
|
|
11
10
|
|
|
12
11
|
export class FunctionCallNode<T = any> extends Node implements TreeNode {
|
|
@@ -34,17 +33,25 @@ export class FunctionCallNode<T = any> extends Node implements TreeNode {
|
|
|
34
33
|
const func = await this.fnc.evaluate(scope, dom, tag);
|
|
35
34
|
if (!func) {
|
|
36
35
|
const functionName = await (this.fnc as any).name.evaluate(scope, dom, tag);
|
|
37
|
-
const
|
|
38
|
-
|
|
36
|
+
const returnValues = [];
|
|
37
|
+
let calls = 0;
|
|
38
|
+
for (const className of tag.preppedClasses) {
|
|
39
39
|
const cls = Registry.instance.classes.getSynchronous(className);
|
|
40
|
-
if (cls)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
if (cls) {
|
|
41
|
+
if (cls.classScope.has(functionName)) {
|
|
42
|
+
const fnc = cls.classScope.get(functionName);
|
|
43
|
+
returnValues.push((await fnc.evaluate(functionScope, dom, tag))(...values));
|
|
44
|
+
calls++;
|
|
45
|
+
}
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
+
if (calls === 1) {
|
|
49
|
+
return returnValues[0];
|
|
50
|
+
} else if (calls === 0) {
|
|
51
|
+
throw new Error(`Function ${functionName} not found`);
|
|
52
|
+
} else {
|
|
53
|
+
return returnValues;
|
|
54
|
+
}
|
|
48
55
|
} else if (func instanceof FunctionNode) {
|
|
49
56
|
return (await func.evaluate(functionScope, dom, tag) as any)(...values);
|
|
50
57
|
} else {
|
package/src/AST/FunctionNode.ts
CHANGED
|
@@ -28,6 +28,10 @@ export class FunctionNode extends Node implements TreeNode {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
public async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
|
|
31
|
+
return await this.getFunction(scope, dom, tag);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public async getFunction(scope: Scope, dom: DOM, tag: Tag = null) {
|
|
31
35
|
return async (...args) => {
|
|
32
36
|
const functionScope = new FunctionScope(scope);
|
|
33
37
|
for (const arg of this.args) {
|
|
@@ -37,7 +41,7 @@ export class FunctionNode extends Node implements TreeNode {
|
|
|
37
41
|
}
|
|
38
42
|
}
|
|
39
43
|
|
|
40
|
-
public static parse(lastNode, token, tokens: Token[]): FunctionNode {
|
|
44
|
+
public static parse<T = FunctionNode>(lastNode, token, tokens: Token[], cls: any = FunctionNode): FunctionNode {
|
|
41
45
|
tokens.shift(); // skip 'func'
|
|
42
46
|
const name = tokens.shift();
|
|
43
47
|
const argTokens = Tree.getBlockTokens(tokens);
|
|
@@ -46,6 +50,6 @@ export class FunctionNode extends Node implements TreeNode {
|
|
|
46
50
|
funcArgs.push(t[0].value);
|
|
47
51
|
}
|
|
48
52
|
const block = Tree.processTokens(Tree.getNextStatementTokens(tokens, true, true));
|
|
49
|
-
return new
|
|
53
|
+
return new cls(name.value, funcArgs, block);
|
|
50
54
|
}
|
|
51
55
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {Token, TreeNode} from "../AST";
|
|
2
|
+
import {FunctionNode} from "./FunctionNode";
|
|
3
|
+
import {Scope} from "../Scope";
|
|
4
|
+
import {DOM} from "../DOM";
|
|
5
|
+
import {Tag} from "../Tag";
|
|
6
|
+
|
|
7
|
+
export class OnNode extends FunctionNode implements TreeNode {
|
|
8
|
+
public async prepare(scope: Scope, dom: DOM, tag: Tag = null): Promise<void> {
|
|
9
|
+
if (tag) {
|
|
10
|
+
tag.addEventHandler(this.name, [], await this.getFunction(scope, dom, tag), this);
|
|
11
|
+
}
|
|
12
|
+
await super.prepare(scope, dom, tag);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public static parse(lastNode, token, tokens: Token[]): OnNode {
|
|
16
|
+
return super.parse<OnNode>(lastNode, token, tokens, OnNode);
|
|
17
|
+
}
|
|
18
|
+
}
|
package/src/AST.ts
CHANGED
|
@@ -28,6 +28,7 @@ import {XHRNode} from "./AST/XHRNode";
|
|
|
28
28
|
import {StringFormatNode} from "./AST/StringFormatNode";
|
|
29
29
|
import {FunctionNode} from "./AST/FunctionNode";
|
|
30
30
|
import {ClassNode} from "./AST/ClassNode";
|
|
31
|
+
import {OnNode} from "./AST/OnNode";
|
|
31
32
|
|
|
32
33
|
function lower(str: string): string {
|
|
33
34
|
return str ? str.toLowerCase() : null;
|
|
@@ -68,6 +69,7 @@ export enum TokenType {
|
|
|
68
69
|
ELSE_IF,
|
|
69
70
|
ELSE,
|
|
70
71
|
FUNC,
|
|
72
|
+
ON,
|
|
71
73
|
CLASS,
|
|
72
74
|
NAME,
|
|
73
75
|
L_BRACE,
|
|
@@ -202,6 +204,10 @@ const TOKEN_PATTERNS: TokenPattern[] = [
|
|
|
202
204
|
type: TokenType.FUNC,
|
|
203
205
|
pattern: /^func\s/
|
|
204
206
|
},
|
|
207
|
+
{
|
|
208
|
+
type: TokenType.ON,
|
|
209
|
+
pattern: /^on\s/
|
|
210
|
+
},
|
|
205
211
|
{
|
|
206
212
|
type: TokenType.CLASS,
|
|
207
213
|
pattern: /^class\s/
|
|
@@ -498,6 +504,10 @@ export class Tree {
|
|
|
498
504
|
node = FunctionNode.parse(node, token, tokens);
|
|
499
505
|
blockNodes.push(node);
|
|
500
506
|
node = null;
|
|
507
|
+
} else if (token.type === TokenType.ON) {
|
|
508
|
+
node = OnNode.parse(node, token, tokens);
|
|
509
|
+
blockNodes.push(node);
|
|
510
|
+
node = null;
|
|
501
511
|
} else if (token.type === TokenType.CLASS) {
|
|
502
512
|
node = ClassNode.parse(node, token, tokens);
|
|
503
513
|
blockNodes.push(node);
|
package/src/DOM.ts
CHANGED
|
@@ -28,7 +28,6 @@ export class DOM extends EventDispatcher {
|
|
|
28
28
|
) {
|
|
29
29
|
super();
|
|
30
30
|
this.observer = new MutationObserver(this.mutation.bind(this));
|
|
31
|
-
Registry.instance.classes.on('register', this.prepareDOMClass.bind(this));
|
|
32
31
|
this.tags = [];
|
|
33
32
|
|
|
34
33
|
this.window = new WrappedWindow(window);
|
|
@@ -59,18 +58,6 @@ export class DOM extends EventDispatcher {
|
|
|
59
58
|
}
|
|
60
59
|
}
|
|
61
60
|
|
|
62
|
-
public async prepareDOMClass(className: string, classObject: ClassNode) {
|
|
63
|
-
for (const element of Array.from(this.querySelectorAll(`.${className}`))) {
|
|
64
|
-
const tag: Tag = await this.getTagForElement(element as HTMLElement, true);
|
|
65
|
-
if (tag) {
|
|
66
|
-
await classObject.prepareTag(tag, this);
|
|
67
|
-
if (classObject.classScope.has('construct')) {
|
|
68
|
-
await tag.exec('construct()');
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
61
|
public async getFromTag(tag: Tag, selector: string, create: boolean = false) {
|
|
75
62
|
const nodes = this.querySelectorElement(tag.element, selector);
|
|
76
63
|
return await this.getTagsForElements(Array.from(nodes) as Element[], create);
|
|
@@ -130,11 +117,16 @@ export class DOM extends EventDispatcher {
|
|
|
130
117
|
|
|
131
118
|
public async mutation(mutations: MutationRecord[]) {
|
|
132
119
|
for (const mutation of mutations) {
|
|
133
|
-
|
|
120
|
+
let tag: Tag = await this.getTagForElement(mutation.target as HTMLElement);
|
|
134
121
|
if (tag) {
|
|
135
122
|
tag.mutate(mutation);
|
|
136
123
|
}
|
|
137
124
|
|
|
125
|
+
// Check for class changes
|
|
126
|
+
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
|
127
|
+
await ClassNode.checkForClassChanges(mutation.target as HTMLElement, this, tag);
|
|
128
|
+
}
|
|
129
|
+
|
|
138
130
|
for (const ele of Array.from(mutation.removedNodes)) {
|
|
139
131
|
const toRemove: Tag = await this.getTagForElement(ele as HTMLElement);
|
|
140
132
|
if (toRemove) {
|
|
@@ -206,12 +198,15 @@ export class DOM extends EventDispatcher {
|
|
|
206
198
|
this.queued.splice(this.queued.indexOf(tag.element), 1);
|
|
207
199
|
}
|
|
208
200
|
|
|
209
|
-
|
|
201
|
+
for (const tag of newTags) {
|
|
202
|
+
this.observer.observe(tag.element, {
|
|
210
203
|
attributes: true,
|
|
211
204
|
characterData: true,
|
|
212
205
|
childList: true,
|
|
213
206
|
subtree: true
|
|
214
|
-
})
|
|
207
|
+
});
|
|
208
|
+
await ClassNode.checkForClassChanges(tag.element, this, tag);
|
|
209
|
+
}
|
|
215
210
|
|
|
216
211
|
this.dispatch('built');
|
|
217
212
|
}
|
package/src/Registry.ts
CHANGED
package/src/Tag.ts
CHANGED
|
@@ -27,6 +27,7 @@ export class Tag extends DOMObject {
|
|
|
27
27
|
public readonly rawAttributes: { [key: string]: string; };
|
|
28
28
|
public readonly parsedAttributes: { [key: string]: string[]; };
|
|
29
29
|
public readonly deferredAttributes: Attribute[] = [];
|
|
30
|
+
public readonly preppedClasses: string[] = [];
|
|
30
31
|
protected _state: TagState;
|
|
31
32
|
protected attributes: Attribute[];
|
|
32
33
|
protected _nonDeferredAttributes: Attribute[] = [];
|
|
@@ -598,6 +599,16 @@ export class Tag extends DOMObject {
|
|
|
598
599
|
}
|
|
599
600
|
}
|
|
600
601
|
|
|
602
|
+
public removeContextEventHandlers(context: any) {
|
|
603
|
+
for (const eventType of Object.keys(this.onEventHandlers)) {
|
|
604
|
+
for (const handler of this.onEventHandlers[eventType]) {
|
|
605
|
+
if (handler.context === context) {
|
|
606
|
+
this.removeEventHandler(eventType, handler.handler, context);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
601
612
|
public createScope(force: boolean = false): Scope {
|
|
602
613
|
// Standard attribute requires a unique scope
|
|
603
614
|
// @todo: Does this cause any issues with attribute bindings on the parent scope prior to having its own scope? hmm...
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {ClassNode} from "../AST/ClassNode";
|
|
1
2
|
|
|
2
3
|
export class ElementHelper {
|
|
3
4
|
public static hasVisionAttribute(element: HTMLElement | Element, testAttr: string = 'vsn-'): boolean {
|
|
@@ -10,6 +11,11 @@ export class ElementHelper {
|
|
|
10
11
|
}
|
|
11
12
|
}
|
|
12
13
|
|
|
14
|
+
for (const cls of Array.from(element.classList)) {
|
|
15
|
+
if (ClassNode.isClass(cls))
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
return false;
|
|
14
20
|
}
|
|
15
21
|
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Attribute } from "../Attribute";
|
|
2
|
-
export declare class ClassConstructor extends Attribute {
|
|
3
|
-
static readonly canDefer: boolean;
|
|
4
|
-
static readonly scoped: boolean;
|
|
5
|
-
protected attributeKey: string;
|
|
6
|
-
protected className: string;
|
|
7
|
-
protected defaultClassName: string;
|
|
8
|
-
setup(): Promise<void>;
|
|
9
|
-
protected instantiateClass(cls: any): void;
|
|
10
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ClassConstructor.js","sourceRoot":"","sources":["../../src/attributes/ClassConstructor.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,0CAAuC;AACvC,wCAAqC;AAGrC;IAAsC,oCAAS;IAA/C;;IA0BA,CAAC;IAnBgB,gCAAK,GAAlB;;;;;;wBACU,WAAW,GAAU,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC;wBACpD,IAAI,CAAC,WAAW;4BACZ,sBAAO;wBAEX,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;wBAC/C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;wBAEnD,qBAAM,mBAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAA;;wBAAzD,GAAG,GAAG,SAAmD;wBAC/D,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;wBAE3B,IAAI,IAAI,CAAC,YAAY,IAAI,WAAW;4BAChC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;wBACvD,qBAAM,iBAAM,KAAK,WAAE,EAAA;;wBAAnB,SAAmB,CAAC;;;;;KACvB;IAES,2CAAgB,GAA1B,UAA2B,GAAG;QAC1B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAxBsB,yBAAQ,GAAY,KAAK,CAAC;IAC1B,uBAAM,GAAY,IAAI,CAAC;IAFrC,gBAAgB;QAD5B,mBAAQ,CAAC,SAAS,CAAC,gBAAgB,CAAC;OACxB,gBAAgB,CA0B5B;IAAD,uBAAC;CAAA,AA1BD,CAAsC,qBAAS,GA0B9C;AA1BY,4CAAgB"}
|