arrmatura 5.0.6 → 6.2.1
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/index.ts +20 -0
- package/package.json +14 -43
- package/src/core/composition.ts +71 -0
- package/src/core/conditionals.ts +80 -0
- package/src/core/elementary.ts +40 -0
- package/src/core/fragment.ts +21 -0
- package/src/core/index.ts +19 -0
- package/src/core/iterations.ts +121 -0
- package/src/core/root.ts +46 -0
- package/src/core/routing.ts +37 -0
- package/src/core/selection.ts +57 -0
- package/src/core/slot.ts +36 -0
- package/src/ctx/Ctx.ts +424 -0
- package/src/ctx/CtxNode.ts +159 -0
- package/src/utils/compileExpression.ts +126 -0
- package/src/utils/stringify.ts +39 -0
- package/LICENSE +0 -21
- package/README.md +0 -54
- package/commons/auth/UserService.ts +0 -107
- package/commons/auth/index.ts +0 -4
- package/commons/auth/user.xml +0 -66
- package/commons/components/buttons.xml +0 -23
- package/commons/components/index.ts +0 -13
- package/commons/components/inputs.xml +0 -33
- package/commons/components/layouts.xml +0 -77
- package/commons/components/media.xml +0 -21
- package/commons/components/modal.xml +0 -37
- package/commons/components/navigation.xml +0 -59
- package/commons/components/popups.xml +0 -12
- package/commons/components/searchbar.xml +0 -40
- package/commons/components/table.xml +0 -120
- package/commons/components/toasts.xml +0 -13
- package/commons/components/viewport.xml +0 -48
- package/commons/forms/FieldItem.xml +0 -20
- package/commons/forms/FormController.ts +0 -73
- package/commons/forms/Item.ts +0 -68
- package/commons/forms/ItemCollection.ts +0 -152
- package/commons/forms/ItemController.ts +0 -62
- package/commons/forms/MetadataService.ts +0 -45
- package/commons/forms/MultiEnumField.xml +0 -44
- package/commons/forms/MultivalueController.ts +0 -49
- package/commons/forms/SmartareaField.xml +0 -51
- package/commons/forms/SuggestionController.ts +0 -80
- package/commons/forms/SuggestionField.xml +0 -28
- package/commons/forms/fields.xml +0 -138
- package/commons/forms/form.xml +0 -37
- package/commons/forms/index.ts +0 -29
- package/commons/index.ts +0 -6
- package/commons/pipes/index.ts +0 -21
- package/commons/pipes/showCounts.ts +0 -16
- package/commons/services/ErrorHandlingService.ts +0 -11
- package/commons/services/FirebaseService.ts +0 -185
- package/commons/services/GSheetsService.ts +0 -92
- package/commons/services/HeartbeatService.ts +0 -35
- package/commons/services/Invoke.ts +0 -13
- package/commons/services/JsonpService.ts +0 -18
- package/commons/services/Loader.ts +0 -17
- package/commons/services/LocalStorage.ts +0 -46
- package/commons/services/NavigationService.ts +0 -55
- package/commons/services/Service.ts +0 -68
- package/commons/services/ServiceWorker.ts +0 -111
- package/commons/services/ToastService.ts +0 -49
- package/commons/services/index.ts +0 -14
- package/core/Arrmatura.ts +0 -84
- package/core/CNode.ts +0 -112
- package/core/Component.ts +0 -426
- package/core/cnodes/composition.ts +0 -100
- package/core/cnodes/conditionals.ts +0 -51
- package/core/cnodes/elementary.ts +0 -44
- package/core/cnodes/iterations.ts +0 -92
- package/core/cnodes/routing.ts +0 -25
- package/core/compileNode.ts +0 -39
- package/core/expression.ts +0 -73
- package/core/index.ts +0 -1
- package/core/register.ts +0 -43
- package/core/utils.ts +0 -25
- package/core-web/WebPlatform.ts +0 -25
- package/core-web/attributes.ts +0 -190
- package/core-web/elements.ts +0 -64
- package/core-web/index.ts +0 -16
- package/core-web/reflow.ts +0 -28
- package/core-web/type.ts +0 -18
- package/docs/index.js +0 -269
- package/lib/arrayGroupBy.ts +0 -19
- package/lib/arraySortBy.ts +0 -49
- package/lib/arrayToObject.ts +0 -18
- package/lib/codus.ts +0 -25
- package/lib/consts.ts +0 -3
- package/lib/createListeners.ts +0 -12
- package/lib/curry.ts +0 -8
- package/lib/dateFormat.ts +0 -69
- package/lib/dateOf.ts +0 -31
- package/lib/dateParseISO8601.ts +0 -27
- package/lib/fx.ts +0 -62
- package/lib/geospatial.js +0 -22
- package/lib/guid.ts +0 -7
- package/lib/index.ts +0 -19
- package/lib/l10n.ts +0 -40
- package/lib/nextId.ts +0 -9
- package/lib/noop.ts +0 -8
- package/lib/obj.ts +0 -64
- package/lib/predicat.ts +0 -26
- package/lib/resources.ru.ts +0 -20
- package/lib/resources.ts +0 -20
- package/lib/scalar.ts +0 -25
- package/lib/str.ts +0 -76
- package/lib/urls.ts +0 -91
- package/lib/xml.ts +0 -117
package/index.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ICtx, IPlatform } from "arrmatura-api/types";
|
|
2
|
+
import { CRootNode } from "./src/core/root";
|
|
3
|
+
|
|
4
|
+
export { Registry } from "./src/core";
|
|
5
|
+
export { CRootNode } from "./src/core/root";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Launches the runtime with given top-level template on the specified platform.
|
|
9
|
+
*
|
|
10
|
+
* @param {IPlatform} platform - The platform on which to launch the template.
|
|
11
|
+
* @param {string} template - The template to launch with.
|
|
12
|
+
* @return {ICtx} The root context object.
|
|
13
|
+
*/
|
|
14
|
+
export const launch = (platform: IPlatform, template: string): ICtx => {
|
|
15
|
+
const root = new CRootNode(template).createContext(platform);
|
|
16
|
+
|
|
17
|
+
root.up({}, true);
|
|
18
|
+
|
|
19
|
+
return root;
|
|
20
|
+
};
|
package/package.json
CHANGED
|
@@ -1,48 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arrmatura",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"release": "npx webpack-cli && npm publish"
|
|
10
|
-
},
|
|
11
|
-
"repository": {
|
|
12
|
-
"type": "git",
|
|
13
|
-
"url": "https://github.com/alitskevich/arrmatura.git"
|
|
14
|
-
},
|
|
15
|
-
"author": "alitskevich",
|
|
16
|
-
"license": "MIT",
|
|
17
|
-
"main": "docs/index.js",
|
|
3
|
+
"version": "6.2.1",
|
|
4
|
+
"description": "Arrmatura runtime engine",
|
|
5
|
+
"author": "alitskevich@gmail.com",
|
|
6
|
+
"license": "ISC",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "index.ts",
|
|
18
9
|
"files": [
|
|
19
|
-
"
|
|
20
|
-
"core",
|
|
21
|
-
"core-web",
|
|
22
|
-
"commons",
|
|
23
|
-
"declarations.d"
|
|
10
|
+
"src/**/*"
|
|
24
11
|
],
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
"eslint": "^7.30.0",
|
|
32
|
-
"@typescript-eslint/eslint-plugin": "^2.27.0",
|
|
33
|
-
"@typescript-eslint/parser": "^2.27.0",
|
|
34
|
-
"eslint-config-airbnb": "^18.2.1",
|
|
35
|
-
"eslint-plugin-jest": "^23.18.0",
|
|
36
|
-
"eslint-plugin-react": "^7.20.3",
|
|
37
|
-
"eslint-plugin-react-hooks": "^4.0.5",
|
|
38
|
-
"eslint-plugin-import": "^2.22.1",
|
|
39
|
-
"eslint-plugin-node": "^11.1.0",
|
|
40
|
-
"eslint-plugin-promise": "^4.2.1",
|
|
41
|
-
"metro-react-native-babel-preset": "^0.66.2",
|
|
42
|
-
"raw-loader": "^4.0.2",
|
|
43
|
-
"typescript": "^4.4.4",
|
|
44
|
-
"webpack": "^4.44.2",
|
|
45
|
-
"webpack-cli": "^3.3.12",
|
|
46
|
-
"webpack-dev-server": "^3.11.0"
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"arrmatura-api": "1.0.2",
|
|
14
|
+
"ultimus": "2.1.4"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"pnpm:publish": "pnpm publish --no-git-checks"
|
|
47
18
|
}
|
|
48
|
-
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { CtxNode } from "../ctx/CtxNode";
|
|
2
|
+
import { Ctx } from "../ctx/Ctx";
|
|
3
|
+
import type { Hash, XmlNode } from "ultimus/types";
|
|
4
|
+
import type { EContent, ICtxNode, IPlatform } from "arrmatura-api/types";
|
|
5
|
+
|
|
6
|
+
export class Composite extends Ctx<CCompositeNode> {
|
|
7
|
+
get displayName(): string {
|
|
8
|
+
return `💠${this.node.tag}`;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get recontentScope(): Ctx {
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
slotContent(slotId?: string): EContent | undefined {
|
|
16
|
+
return this.node.getSlotContent(this.platform, slotId);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
createComponent(initials: Hash) {
|
|
20
|
+
return this.platform.createComponent(this.node.tag, initials, this);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class CCompositeNode extends CtxNode {
|
|
25
|
+
slotContent: Hash<EContent> | null = null;
|
|
26
|
+
tag: string;
|
|
27
|
+
nodes?: XmlNode["nodes"];
|
|
28
|
+
#content: Map<string, ICtxNode>;
|
|
29
|
+
|
|
30
|
+
constructor({ tag, attrs, nodes }: XmlNode) {
|
|
31
|
+
super();
|
|
32
|
+
this.tag = tag;
|
|
33
|
+
this.nodes = nodes;
|
|
34
|
+
this.compileAttributes(attrs);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
getSlotContent(platform: IPlatform, slotId?: string): EContent | undefined {
|
|
38
|
+
if (!this.slotContent) {
|
|
39
|
+
const slots = this.nodes?.reduce<Hash<XmlNode[]>>((groups, e) => {
|
|
40
|
+
let gId = "default";
|
|
41
|
+
let isContainer = false;
|
|
42
|
+
if (e.tag.startsWith(`${this.tag}:`)) {
|
|
43
|
+
gId = e.tag.split(":")[1];
|
|
44
|
+
isContainer = true;
|
|
45
|
+
}
|
|
46
|
+
groups[gId] = (groups[gId] || []).concat(
|
|
47
|
+
isContainer ? e.nodes ?? [] : e
|
|
48
|
+
);
|
|
49
|
+
return groups;
|
|
50
|
+
}, {});
|
|
51
|
+
|
|
52
|
+
this.slotContent = Object.entries(slots ?? {}).reduce<Hash<EContent>>(
|
|
53
|
+
(groups, [gId, nodes]) => {
|
|
54
|
+
groups[gId] = platform.getCompiledNodes(nodes);
|
|
55
|
+
return groups;
|
|
56
|
+
},
|
|
57
|
+
{}
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return this.slotContent[slotId ?? "default"] ?? undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
getContent(platform: IPlatform) {
|
|
65
|
+
return this.#content ?? (this.#content = platform.getCompiledNodes(this.tag));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get EntityConstructor() {
|
|
69
|
+
return Composite;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { CtxNode } from "../ctx/CtxNode";
|
|
2
|
+
import { Composite } from "./composition";
|
|
3
|
+
import { Ctx } from "../ctx/Ctx";
|
|
4
|
+
import type { EContent, ICtx, IPlatform } from "arrmatura-api/types";
|
|
5
|
+
import type { XmlNode } from "ultimus/types";
|
|
6
|
+
import { compilePlaceholder } from "../utils/compileExpression";
|
|
7
|
+
|
|
8
|
+
class Conditional extends Ctx<CIfNode> {
|
|
9
|
+
get content() {
|
|
10
|
+
const branches = this.node.getBranches(this.platform);
|
|
11
|
+
return this.component.condition ? branches.then : branches.else;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get displayName(): string {
|
|
15
|
+
return "🔹if";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class CIfNode extends CtxNode {
|
|
20
|
+
#xml: XmlNode;
|
|
21
|
+
#branches?: { then?: EContent; else?: EContent };
|
|
22
|
+
constructor(xml: XmlNode, expr: string) {
|
|
23
|
+
super();
|
|
24
|
+
this.#xml = xml;
|
|
25
|
+
this.compileCondition(expr);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get EntityConstructor() {
|
|
29
|
+
return Conditional;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
getBranches(platform: IPlatform) {
|
|
33
|
+
if (this.#branches) {
|
|
34
|
+
return this.#branches;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
this.#branches = {};
|
|
38
|
+
|
|
39
|
+
const { nodes } = this.#xml;
|
|
40
|
+
|
|
41
|
+
let $then: XmlNode[] | undefined = [this.#xml];
|
|
42
|
+
if (nodes?.length) {
|
|
43
|
+
const ifElse = nodes.find((e) => e.tag === "Else");
|
|
44
|
+
const ifThen = nodes.find((e) => e.tag === "Then");
|
|
45
|
+
if (ifElse) {
|
|
46
|
+
this.#branches.else = ifElse.nodes
|
|
47
|
+
? platform.getCompiledNodes(ifElse.nodes)
|
|
48
|
+
: undefined;
|
|
49
|
+
$then = ifThen
|
|
50
|
+
? ifThen.nodes
|
|
51
|
+
: [
|
|
52
|
+
Object.assign(this.#xml, {
|
|
53
|
+
nodes: nodes.filter((e) => e !== ifElse),
|
|
54
|
+
}),
|
|
55
|
+
];
|
|
56
|
+
} else if (ifThen) {
|
|
57
|
+
$then = ifThen.nodes;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
this.#branches.then = $then ? platform.getCompiledNodes($then) : undefined;
|
|
61
|
+
|
|
62
|
+
return this.#branches;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
compileCondition(expr: string): void {
|
|
66
|
+
if (expr[0] === "<" && expr[1] === "-") {
|
|
67
|
+
this.addConnector(expr.slice(2), "condition");
|
|
68
|
+
} else if (expr.slice(0, 5) === "slot(") {
|
|
69
|
+
const slotId = expr.slice(5, -1);
|
|
70
|
+
// DO NOT place inside iterations.
|
|
71
|
+
this.addPropertyResolver(
|
|
72
|
+
(c: ICtx) => !!(c.scope as Composite).slotContent?.(slotId)?.size,
|
|
73
|
+
"condition"
|
|
74
|
+
);
|
|
75
|
+
} else {
|
|
76
|
+
const resolver = compilePlaceholder(expr);
|
|
77
|
+
this.addPropertyResolver((c) => !!resolver(c), "condition");
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { CtxNode } from "../ctx/CtxNode";
|
|
2
|
+
import { Ctx } from "../ctx/Ctx";
|
|
3
|
+
import type { Hash, XmlNode } from "ultimus/types";
|
|
4
|
+
import { IPlatform } from "arrmatura-api/types";
|
|
5
|
+
|
|
6
|
+
class Element extends Ctx<CElementNode> {
|
|
7
|
+
get displayName(): string {
|
|
8
|
+
return this.node.tag;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
createComponent(initials: Hash) {
|
|
12
|
+
return this.platform.createComponent(
|
|
13
|
+
{ tag: this.node.tag, native: true },
|
|
14
|
+
initials,
|
|
15
|
+
this
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class CElementNode extends CtxNode {
|
|
21
|
+
#nodes: XmlNode[] | undefined;
|
|
22
|
+
|
|
23
|
+
constructor({ tag, attrs, nodes, text }: XmlNode) {
|
|
24
|
+
super();
|
|
25
|
+
this.tag = tag;
|
|
26
|
+
this.compileAttributes(attrs);
|
|
27
|
+
if (text) {
|
|
28
|
+
this.compileAttribute("#text", text);
|
|
29
|
+
}
|
|
30
|
+
this.#nodes = nodes;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
getContent(platform: IPlatform) {
|
|
34
|
+
return this.#nodes ? platform.getCompiledNodes(this.#nodes) : undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get EntityConstructor() {
|
|
38
|
+
return Element;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CtxNode } from "../ctx/CtxNode";
|
|
2
|
+
import { Ctx } from "../ctx/Ctx";
|
|
3
|
+
import type { XmlNode } from "ultimus/types";
|
|
4
|
+
import type { IPlatform } from "arrmatura-api/types";
|
|
5
|
+
|
|
6
|
+
export class CFragmentNode extends CtxNode {
|
|
7
|
+
#nodes: XmlNode[] | undefined;
|
|
8
|
+
|
|
9
|
+
constructor({ nodes }: XmlNode) {
|
|
10
|
+
super();
|
|
11
|
+
this.#nodes = nodes;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
getContent(platform: IPlatform) {
|
|
15
|
+
return this.#nodes ? platform.getCompiledNodes(this.#nodes) : undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get EntityConstructor() {
|
|
19
|
+
return Ctx;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CForNode } from "./iterations";
|
|
2
|
+
import { CCompositeNode } from "./composition";
|
|
3
|
+
import { CIfNode } from "./conditionals";
|
|
4
|
+
import { CElementNode } from "./elementary";
|
|
5
|
+
import { CDynamicTagNode } from "./routing";
|
|
6
|
+
import { CSlotNode } from "./slot";
|
|
7
|
+
import { CFragmentNode } from "./fragment";
|
|
8
|
+
import { CSelectorNode } from "./selection";
|
|
9
|
+
|
|
10
|
+
export const Registry = {
|
|
11
|
+
CForNode,
|
|
12
|
+
CIfNode,
|
|
13
|
+
CDynamicTagNode,
|
|
14
|
+
CSlotNode,
|
|
15
|
+
CFragmentNode,
|
|
16
|
+
CCompositeNode,
|
|
17
|
+
CSelectorNode,
|
|
18
|
+
CElementNode,
|
|
19
|
+
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { CtxNode } from "../ctx/CtxNode";
|
|
2
|
+
import { Ctx } from "../ctx/Ctx";
|
|
3
|
+
import type { Datum, Delta, Hash, Uid, XmlNode } from "ultimus/types";
|
|
4
|
+
import type { EContent, ICtxNode, IPlatform } from "arrmatura-api/types";
|
|
5
|
+
import { compilePlaceholder } from "../utils/compileExpression";
|
|
6
|
+
|
|
7
|
+
class Iterative extends Ctx<CForNode> {
|
|
8
|
+
pkHash: Hash<Datum> = {};
|
|
9
|
+
|
|
10
|
+
get displayName(): string {
|
|
11
|
+
return "🔹each";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get content() {
|
|
15
|
+
const each: any = this.component.each;
|
|
16
|
+
const itemNode = this.node.getItemCtxNode(this.platform);
|
|
17
|
+
const nodes: Map<Uid, ICtxNode> = new Map();
|
|
18
|
+
this.pkHash = {};
|
|
19
|
+
if (each?.length) {
|
|
20
|
+
if (!each.forEach) {
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
22
|
+
throw new Error(`[each] Items has no forEach() ${each.toString()}`);
|
|
23
|
+
}
|
|
24
|
+
each.forEach((datum: Datum, index: number) => {
|
|
25
|
+
let id = datum.id;
|
|
26
|
+
if (id == null) {
|
|
27
|
+
this.logError("ERROR: empty item id: ", datum);
|
|
28
|
+
id = String(index);
|
|
29
|
+
}
|
|
30
|
+
const pk = String(id);
|
|
31
|
+
if (this.pkHash[pk]) {
|
|
32
|
+
this.logError(`ERROR: duplicate item id : ${pk} (skipped)`, datum);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
this.pkHash[pk] = datum;
|
|
36
|
+
const inode = itemNode
|
|
37
|
+
.cloneWithDatum(datum, this.platform)
|
|
38
|
+
.addPropertyResolver(() => this.pkHash[pk], itemNode.itemName);
|
|
39
|
+
nodes.set(inode.uid, inode);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return nodes;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class CForNode extends CtxNode {
|
|
47
|
+
#itemNode?: CItemNode;
|
|
48
|
+
#itemName: string;
|
|
49
|
+
#xmlNode: XmlNode;
|
|
50
|
+
constructor(xmlNode: XmlNode, [itemName, prep, expr = prep]: string[]) {
|
|
51
|
+
super();
|
|
52
|
+
this.#xmlNode = xmlNode;
|
|
53
|
+
this.#itemName = itemName;
|
|
54
|
+
if (expr[0] === "<" && expr[1] === "-") {
|
|
55
|
+
this.addConnector(expr.slice(2), "each");
|
|
56
|
+
} else {
|
|
57
|
+
this.addPropertyResolver(compilePlaceholder(expr), "each");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
getItemCtxNode(platform: IPlatform) {
|
|
62
|
+
return (
|
|
63
|
+
this.#itemNode ??
|
|
64
|
+
(this.#itemNode = new CItemNode(
|
|
65
|
+
this.#itemName,
|
|
66
|
+
platform.getCompiledNodes([this.#xmlNode])
|
|
67
|
+
))
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
get EntityConstructor() {
|
|
72
|
+
return Iterative;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
class IterativeItem extends Ctx<CItemNode> {
|
|
77
|
+
get recontentScope(): Ctx {
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
get displayName(): string {
|
|
82
|
+
return "🔹ui:for:item";
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
emit(key: string, data: Delta) {
|
|
86
|
+
return this.scope.emit(key, data);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
get(propId: string) {
|
|
90
|
+
const iName: string = this.node.itemName;
|
|
91
|
+
const value =
|
|
92
|
+
propId.startsWith(`${iName}.`) || propId === iName
|
|
93
|
+
? super.get(propId)
|
|
94
|
+
: this.scope.get(propId);
|
|
95
|
+
// this.log(propId, value);
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
class CItemNode extends CtxNode {
|
|
101
|
+
itemName: string;
|
|
102
|
+
constructor(itemName: string, content?: EContent) {
|
|
103
|
+
super();
|
|
104
|
+
this.itemName = itemName;
|
|
105
|
+
this.$content = content;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
cloneWithDatum(datum: Datum, platform: IPlatform) {
|
|
109
|
+
const uid = `${String(this.uid)}#${datum.id}`;
|
|
110
|
+
return Object.assign(
|
|
111
|
+
new CItemNode(this.itemName, this.getContent(platform)),
|
|
112
|
+
{
|
|
113
|
+
uid,
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
get EntityConstructor() {
|
|
119
|
+
return IterativeItem;
|
|
120
|
+
}
|
|
121
|
+
}
|
package/src/core/root.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { CtxNode } from "../ctx/CtxNode";
|
|
2
|
+
import { Ctx } from "../ctx/Ctx";
|
|
3
|
+
import type { Hash, XmlNode } from "ultimus/types";
|
|
4
|
+
import type { EContent, IPlatform } from "arrmatura-api/types";
|
|
5
|
+
import { xmlParse } from "ultimus";
|
|
6
|
+
import { CCompositeNode } from "./composition";
|
|
7
|
+
|
|
8
|
+
class RootCtx extends Ctx<CCompositeNode> {
|
|
9
|
+
get displayName(): string {
|
|
10
|
+
return `ROOT`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get recontentScope(): Ctx {
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
slotContent(_slotId?: string): EContent | undefined {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
createComponent(initials: Hash) {
|
|
22
|
+
return this.platform.createComponent({}, initials, this);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class CRootNode extends CtxNode {
|
|
27
|
+
slotContent: Hash<EContent>;
|
|
28
|
+
nodes?: XmlNode["nodes"];
|
|
29
|
+
|
|
30
|
+
constructor(private template: string) {
|
|
31
|
+
super();
|
|
32
|
+
this.slotContent = {};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getContent(platform: IPlatform) {
|
|
36
|
+
return platform.getCompiledNodes(xmlParse(this.template));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getSlotContent(_platform: IPlatform, _slotId?: string) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get EntityConstructor() {
|
|
44
|
+
return RootCtx;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { CtxNode } from "../ctx/CtxNode";
|
|
2
|
+
import { Ctx } from "../ctx/Ctx";
|
|
3
|
+
import type { XmlNode } from "ultimus/types";
|
|
4
|
+
|
|
5
|
+
class DynamicTag extends Ctx<CDynamicTagNode> {
|
|
6
|
+
get displayName(): string {
|
|
7
|
+
return "dynamics";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
get content() {
|
|
11
|
+
const tag = this.component.tag;
|
|
12
|
+
const uid = `${this.uid}:${String(tag ?? "")}`;
|
|
13
|
+
return new Map([
|
|
14
|
+
[
|
|
15
|
+
uid,
|
|
16
|
+
Object.assign(
|
|
17
|
+
this.platform.getCompiledNodes({ ...this.node.xml, tag } as XmlNode),
|
|
18
|
+
{ uid }
|
|
19
|
+
),
|
|
20
|
+
],
|
|
21
|
+
]);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class CDynamicTagNode extends CtxNode {
|
|
26
|
+
xml: XmlNode & { tag: string };
|
|
27
|
+
|
|
28
|
+
constructor(xml: XmlNode, expr: string) {
|
|
29
|
+
super();
|
|
30
|
+
this.compileAttribute("tag", expr);
|
|
31
|
+
this.xml = xml;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get EntityConstructor() {
|
|
35
|
+
return DynamicTag;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { CtxNode } from "../ctx/CtxNode";
|
|
2
|
+
import { Ctx } from "../ctx/Ctx";
|
|
3
|
+
import type { Hash, XmlNode } from "ultimus/types";
|
|
4
|
+
import type { EContent, IPlatform } from "arrmatura-api/types";
|
|
5
|
+
|
|
6
|
+
export class Selector extends Ctx<CSelectorNode> {
|
|
7
|
+
get displayName(): string {
|
|
8
|
+
return `💠Selector`;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Gets the content of the function.
|
|
13
|
+
*
|
|
14
|
+
* @return {any} The content of the function.
|
|
15
|
+
*/
|
|
16
|
+
get content() {
|
|
17
|
+
const cases = this.node.getCases(this.platform);
|
|
18
|
+
const matchedCase = cases?.[this.component.on as string];
|
|
19
|
+
if (!matchedCase) {
|
|
20
|
+
this.log('unmatched case', this.component.on, cases);
|
|
21
|
+
}
|
|
22
|
+
return matchedCase ?? cases?.['default'] ?? Object.values(cases)[0];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class CSelectorNode extends CtxNode {
|
|
27
|
+
cases: Hash<EContent> | null = null;
|
|
28
|
+
key = '';
|
|
29
|
+
nodes?: XmlNode["nodes"];
|
|
30
|
+
|
|
31
|
+
constructor({ tag, attrs, nodes }: XmlNode) {
|
|
32
|
+
super();
|
|
33
|
+
this.tag = tag;
|
|
34
|
+
this.nodes = nodes;
|
|
35
|
+
this.compileAttributes(attrs);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Retrieves the cases nodes for a component.
|
|
40
|
+
*
|
|
41
|
+
* @param {IPlatform} platform - The platform to get cases for.
|
|
42
|
+
* @return {Hash<EContent>} - The cases for the platform.
|
|
43
|
+
*/
|
|
44
|
+
getCases(platform: IPlatform): Hash<EContent> {
|
|
45
|
+
return this.cases ?? (this.cases = (this.nodes ?? []).reduce<Hash<EContent>>(
|
|
46
|
+
(groups, node) => {
|
|
47
|
+
groups[node.attrs?.when as string] = platform.getCompiledNodes(node.nodes ?? []);
|
|
48
|
+
return groups;
|
|
49
|
+
},
|
|
50
|
+
{}
|
|
51
|
+
));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get EntityConstructor() {
|
|
55
|
+
return Selector;
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/core/slot.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { CtxNode } from "../ctx/CtxNode";
|
|
2
|
+
import { Ctx } from "../ctx/Ctx";
|
|
3
|
+
import type { XmlNode } from "ultimus/types";
|
|
4
|
+
import type { ICtx } from "arrmatura-api/types";
|
|
5
|
+
import { Composite } from "./composition";
|
|
6
|
+
|
|
7
|
+
class Slot extends Ctx {
|
|
8
|
+
get displayName(): string {
|
|
9
|
+
return "🔸";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get compositeScope(): Composite {
|
|
13
|
+
return this.scope as Composite;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get content() {
|
|
17
|
+
return this.compositeScope.slotContent((this.node as CSlotNode).key);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get recontentScope(): ICtx {
|
|
21
|
+
return this.compositeScope.scope;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class CSlotNode extends CtxNode {
|
|
26
|
+
key?: string;
|
|
27
|
+
|
|
28
|
+
constructor(x: XmlNode) {
|
|
29
|
+
super();
|
|
30
|
+
this.key = x.attrs?.key as string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get EntityConstructor() {
|
|
34
|
+
return Slot;
|
|
35
|
+
}
|
|
36
|
+
}
|