@plitzi/sdk-shared 0.37.1 → 0.37.3

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 (195) hide show
  1. package/CHANGELOG.md +1288 -0
  2. package/dist/actions/access.d.ts +12 -0
  3. package/dist/actions/access.mjs +13 -0
  4. package/dist/actions/cron.d.ts +21 -12
  5. package/dist/actions/cron.mjs +48 -17
  6. package/dist/actions/functions.d.ts +27 -0
  7. package/dist/actions/functions.mjs +18 -0
  8. package/dist/actions/index.d.ts +5 -1
  9. package/dist/actions/index.mjs +9 -7
  10. package/dist/actions/triggers.d.ts +4 -0
  11. package/dist/actions/triggers.mjs +4 -1
  12. package/dist/auth/index.d.ts +2 -0
  13. package/dist/auth/index.mjs +2 -1
  14. package/dist/auth/visitorRoles.d.ts +27 -0
  15. package/dist/auth/visitorRoles.mjs +48 -0
  16. package/dist/authoring/builder.mjs +1 -0
  17. package/dist/authoring/declare.d.ts +74 -0
  18. package/dist/authoring/declare.mjs +2 -2
  19. package/dist/authoring/index.mjs +5 -5
  20. package/dist/authoring/paramSpec.d.ts +1 -1
  21. package/dist/authoring/paramSpec.mjs +1 -0
  22. package/dist/authoring/spaceCallbacks.mjs +2 -2
  23. package/dist/dataSource/computed.d.ts +21 -0
  24. package/dist/dataSource/computed.mjs +45 -0
  25. package/dist/dataSource/getBindingsDetails.mjs +35 -33
  26. package/dist/dataSource/index.d.ts +1 -0
  27. package/dist/dataSource/index.mjs +7 -6
  28. package/dist/dataSource/utility/checkboxParams.d.ts +11 -0
  29. package/dist/dataSource/utility/checkboxParams.mjs +12 -0
  30. package/dist/dataSource/utility/not.mjs +4 -7
  31. package/dist/dataSource/utility/stringToArray.mjs +1 -1
  32. package/dist/dataSource/utility/truthiness.d.ts +1 -0
  33. package/dist/dataSource/utility/truthiness.mjs +8 -0
  34. package/dist/dataSource/utility/twigTemplate.d.ts +2 -1
  35. package/dist/dataSource/utility/twigTemplate.mjs +29 -17
  36. package/dist/devTools/utils/PlitziConsole.mjs +22 -22
  37. package/dist/helpers/cookies.d.ts +10 -0
  38. package/dist/helpers/cookies.mjs +19 -0
  39. package/dist/helpers/fetchManifest.d.ts +9 -0
  40. package/dist/helpers/fetchManifest.mjs +3 -6
  41. package/dist/helpers/formatDate.d.ts +5 -3
  42. package/dist/helpers/formatDate.mjs +34 -36
  43. package/dist/helpers/index.d.ts +2 -0
  44. package/dist/helpers/index.mjs +18 -13
  45. package/dist/helpers/isDate.d.ts +7 -0
  46. package/dist/helpers/isDate.mjs +15 -0
  47. package/dist/helpers/keys.d.ts +42 -0
  48. package/dist/helpers/keys.mjs +91 -0
  49. package/dist/helpers/twigWrapper/AST.d.ts +2 -2
  50. package/dist/helpers/twigWrapper/Evaluator/Evaluator.d.ts +12 -2
  51. package/dist/helpers/twigWrapper/Evaluator/Evaluator.mjs +69 -31
  52. package/dist/helpers/twigWrapper/Evaluator/index.d.ts +1 -1
  53. package/dist/helpers/twigWrapper/Evaluator/index.mjs +2 -2
  54. package/dist/helpers/twigWrapper/Parser/ExpressionParser.d.ts +2 -2
  55. package/dist/helpers/twigWrapper/Parser/ExpressionParser.mjs +147 -34
  56. package/dist/helpers/twigWrapper/Parser/Parser.d.ts +2 -1
  57. package/dist/helpers/twigWrapper/Parser/Parser.mjs +21 -20
  58. package/dist/helpers/twigWrapper/filters/filters.mjs +134 -111
  59. package/dist/helpers/twigWrapper/index.d.ts +6 -2
  60. package/dist/helpers/twigWrapper/index.mjs +7 -4
  61. package/dist/helpers/twigWrapper/inspectTemplate.d.ts +23 -0
  62. package/dist/helpers/twigWrapper/inspectTemplate.mjs +110 -0
  63. package/dist/helpers/twigWrapper/processTwig/helpers.d.ts +7 -0
  64. package/dist/helpers/twigWrapper/processTwig/helpers.mjs +2 -1
  65. package/dist/helpers/twigWrapper/processTwig/index.d.ts +2 -1
  66. package/dist/helpers/twigWrapper/processTwig/index.mjs +3 -2
  67. package/dist/helpers/twigWrapper/processTwig/processTwig.d.ts +28 -0
  68. package/dist/helpers/twigWrapper/processTwig/processTwig.mjs +73 -16
  69. package/dist/helpers/twigWrapper/processTwig/resolveStepParam.d.ts +17 -0
  70. package/dist/helpers/twigWrapper/processTwig/resolveStepParam.mjs +14 -0
  71. package/dist/helpers/twigWrapper/templateRoots.d.ts +11 -0
  72. package/dist/helpers/twigWrapper/templateRoots.mjs +4 -4
  73. package/dist/helpers/twigWrapper/tokens/hasTemplateSyntax.d.ts +9 -0
  74. package/dist/helpers/twigWrapper/tokens/hasTemplateSyntax.mjs +4 -0
  75. package/dist/history/describe.d.ts +29 -0
  76. package/dist/history/describe.mjs +93 -0
  77. package/dist/history/diff.d.ts +33 -0
  78. package/dist/history/diff.mjs +73 -0
  79. package/dist/history/index.d.ts +3 -0
  80. package/dist/history/index.mjs +3 -0
  81. package/dist/history/types.d.ts +48 -0
  82. package/dist/history/types.mjs +0 -0
  83. package/dist/hooks/usePlitziServiceContext.d.ts +1 -1
  84. package/dist/index.d.ts +1 -0
  85. package/dist/index.mjs +77 -65
  86. package/dist/navigation/index.d.ts +1 -1
  87. package/dist/navigation/index.mjs +2 -2
  88. package/dist/navigation/routes.d.ts +11 -1
  89. package/dist/navigation/routes.mjs +35 -30
  90. package/dist/network/graphql/builder/Mutations/Space/SpaceFixIssuesMutation.d.ts +14 -0
  91. package/dist/network/graphql/builder/Mutations/Space/SpaceFixIssuesMutation.mjs +16 -0
  92. package/dist/network/graphql/builder/Mutations/Space/SpaceUpdatePluginMutation.d.ts +4 -0
  93. package/dist/network/graphql/builder/Mutations/Space/SpaceUpdatePluginMutation.mjs +2 -2
  94. package/dist/network/graphql/builder/Mutations/Space/actions/SpaceRunActionMutation.mjs +1 -0
  95. package/dist/network/graphql/builder/Mutations/Space/functions/SpaceRemoveFunctionsMutation.d.ts +3 -0
  96. package/dist/network/graphql/builder/Mutations/Space/functions/SpaceRemoveFunctionsMutation.mjs +9 -0
  97. package/dist/network/graphql/builder/Mutations/Space/functions/SpaceSaveFunctionsMutation.d.ts +11 -0
  98. package/dist/network/graphql/builder/Mutations/Space/functions/SpaceSaveFunctionsMutation.mjs +24 -0
  99. package/dist/network/graphql/builder/Mutations/Space/functions/SpaceTryFunctionMutation.d.ts +4 -0
  100. package/dist/network/graphql/builder/Mutations/Space/functions/SpaceTryFunctionMutation.mjs +15 -0
  101. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceRemoveRuntimeMutation.d.ts +2 -0
  102. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceRemoveRuntimeMutation.mjs +9 -0
  103. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceRemoveRuntimeVariableMutation.d.ts +2 -0
  104. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceRemoveRuntimeVariableMutation.mjs +9 -0
  105. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceSetRuntimeSizeMutation.d.ts +2 -0
  106. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceSetRuntimeSizeMutation.mjs +9 -0
  107. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceSetRuntimeVariableMutation.d.ts +2 -0
  108. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceSetRuntimeVariableMutation.mjs +9 -0
  109. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceStartRuntimeMutation.d.ts +2 -0
  110. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceStartRuntimeMutation.mjs +9 -0
  111. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceStopRuntimeMutation.d.ts +2 -0
  112. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceStopRuntimeMutation.mjs +9 -0
  113. package/dist/network/graphql/builder/Mutations/Space/visitors/SpaceAddVisitorMutation.d.ts +2 -0
  114. package/dist/network/graphql/builder/Mutations/Space/visitors/SpaceAddVisitorMutation.mjs +11 -0
  115. package/dist/network/graphql/builder/Mutations/Space/visitors/SpaceRemoveVisitorMutation.d.ts +2 -0
  116. package/dist/network/graphql/builder/Mutations/Space/visitors/SpaceRemoveVisitorMutation.mjs +11 -0
  117. package/dist/network/graphql/builder/Mutations/index.d.ts +28 -0
  118. package/dist/network/graphql/builder/Mutations/index.mjs +108 -84
  119. package/dist/network/graphql/builder/Queries/Space/SpaceChangesQuery.d.ts +23 -0
  120. package/dist/network/graphql/builder/Queries/Space/SpaceChangesQuery.mjs +49 -0
  121. package/dist/network/graphql/builder/Queries/Space/SpaceFunctionsQuery.d.ts +6 -0
  122. package/dist/network/graphql/builder/Queries/Space/SpaceFunctionsQuery.mjs +13 -0
  123. package/dist/network/graphql/builder/Queries/Space/SpaceIssuesQuery.d.ts +17 -0
  124. package/dist/network/graphql/builder/Queries/Space/SpaceIssuesQuery.mjs +22 -0
  125. package/dist/network/graphql/builder/Queries/Space/SpaceRuntimeQuery.d.ts +6 -0
  126. package/dist/network/graphql/builder/Queries/Space/SpaceRuntimeQuery.mjs +32 -0
  127. package/dist/network/graphql/builder/Queries/Space/SpaceVisitorsQuery.d.ts +6 -0
  128. package/dist/network/graphql/builder/Queries/Space/SpaceVisitorsQuery.mjs +16 -0
  129. package/dist/network/graphql/builder/Queries/index.d.ts +17 -3
  130. package/dist/network/graphql/builder/Queries/index.mjs +30 -22
  131. package/dist/network/graphql/sdk/Mutations/index.d.ts +1 -1
  132. package/dist/network/graphql/sdk/Queries/InitQuery.d.ts +1 -1
  133. package/dist/network/graphql/sdk/Queries/InitQuery.mjs +2 -91
  134. package/dist/network/graphql/sdk/Queries/Segment/SegmentQuery.d.ts +1 -1
  135. package/dist/network/graphql/sdk/Queries/Segment/SegmentQuery.mjs +2 -44
  136. package/dist/network/graphql/sdk/Queries/Segment/SegmentsQuery.d.ts +1 -1
  137. package/dist/network/graphql/sdk/Queries/Segment/SegmentsQuery.mjs +2 -55
  138. package/dist/network/graphql/sdk/Queries/index.d.ts +1 -5
  139. package/dist/network/index.mjs +7 -7
  140. package/dist/network/spaceEvents.d.ts +33 -3
  141. package/dist/network/spaceEvents.mjs +102 -89
  142. package/dist/realtime/client.d.ts +46 -0
  143. package/dist/realtime/client.mjs +192 -0
  144. package/dist/realtime/index.d.ts +6 -0
  145. package/dist/realtime/index.mjs +4 -0
  146. package/dist/realtime/presence.d.ts +38 -0
  147. package/dist/realtime/presence.mjs +70 -0
  148. package/dist/realtime/topics.d.ts +36 -0
  149. package/dist/realtime/topics.mjs +25 -0
  150. package/dist/schema/serverElements.d.ts +5 -0
  151. package/dist/schema/serverElements.mjs +15 -14
  152. package/dist/server/actions/useRealtimeSync.d.ts +9 -0
  153. package/dist/server/actions/useRealtimeSync.mjs +7 -0
  154. package/dist/state/index.d.ts +1 -0
  155. package/dist/state/index.mjs +3 -2
  156. package/dist/state/paintedState.d.ts +52 -0
  157. package/dist/state/paintedState.mjs +37 -0
  158. package/dist/state/runtimeStatePersist.d.ts +24 -0
  159. package/dist/state/runtimeStatePersist.mjs +113 -10
  160. package/dist/store/index.d.ts +45 -45
  161. package/dist/store/renderSettings.d.ts +6 -3
  162. package/dist/store/tracing/index.d.ts +1 -0
  163. package/dist/store/tracing/tracingCollector.d.ts +17 -1
  164. package/dist/store/tracing/tracingCollector.mjs +5 -0
  165. package/dist/style/index.d.ts +1 -0
  166. package/dist/style/index.mjs +3 -2
  167. package/dist/style/runtimeStyle.d.ts +29 -0
  168. package/dist/style/runtimeStyle.mjs +7 -0
  169. package/dist/style/styleConstants.d.ts +3 -2
  170. package/dist/style/styleConstants.mjs +2 -0
  171. package/dist/style/styleStates.d.ts +14 -1
  172. package/dist/style/styleStates.mjs +10 -7
  173. package/dist/theme/ThemeProvider.d.ts +1 -1
  174. package/dist/theme/ThemeProvider.mjs +35 -29
  175. package/dist/theme/themeCookie.mjs +11 -15
  176. package/dist/types/ActionTypes.d.ts +193 -0
  177. package/dist/types/AuthTypes.d.ts +11 -1
  178. package/dist/types/CommonTypes.d.ts +6 -0
  179. package/dist/types/FunctionTypes.d.ts +52 -0
  180. package/dist/types/FunctionTypes.mjs +0 -0
  181. package/dist/types/PluginTypes.d.ts +0 -1
  182. package/dist/types/RealtimeTypes.d.ts +94 -0
  183. package/dist/types/RealtimeTypes.mjs +0 -0
  184. package/dist/types/SchemaTypes.d.ts +54 -0
  185. package/dist/types/SchemaTypes.mjs +8 -0
  186. package/dist/types/ServerTypes.d.ts +310 -15
  187. package/dist/types/SpaceTypes.d.ts +53 -0
  188. package/dist/types/StateTypes.d.ts +6 -0
  189. package/dist/types/StoreTypes.d.ts +12 -1
  190. package/dist/types/index.d.ts +2 -0
  191. package/dist/types/index.mjs +3 -2
  192. package/package.json +190 -21
  193. package/vite.config.ts +0 -12
  194. package/dist/network/graphql/builder/Queries/PluginsQuery.d.ts +0 -9
  195. package/dist/network/graphql/builder/Queries/PluginsQuery.mjs +0 -54
@@ -0,0 +1,91 @@
1
+ //#region src/helpers/keys.ts
2
+ var e = "onKey", t = [
3
+ "ctrl",
4
+ "alt",
5
+ "shift",
6
+ "meta"
7
+ ], n = {
8
+ ctrl: "ctrl",
9
+ control: "ctrl",
10
+ alt: "alt",
11
+ option: "alt",
12
+ shift: "shift",
13
+ meta: "meta",
14
+ cmd: "meta",
15
+ command: "meta",
16
+ mod: "mod"
17
+ }, r = {
18
+ esc: "escape",
19
+ space: "space",
20
+ spacebar: "space",
21
+ plus: "+",
22
+ minus: "-",
23
+ up: "arrowup",
24
+ down: "arrowdown",
25
+ left: "arrowleft",
26
+ right: "arrowright",
27
+ del: "delete",
28
+ return: "enter"
29
+ }, i = /* @__PURE__ */ new Set([
30
+ "escape",
31
+ "enter",
32
+ "tab",
33
+ "space",
34
+ "backspace",
35
+ "delete",
36
+ "insert",
37
+ "arrowup",
38
+ "arrowdown",
39
+ "arrowleft",
40
+ "arrowright",
41
+ "home",
42
+ "end",
43
+ "pageup",
44
+ "pagedown",
45
+ ...Array.from({ length: 12 }, (e, t) => `f${t + 1}`)
46
+ ]), a = (e, n) => [...t.filter((t) => e.has(t)), n].join("+"), o = (e, t) => {
47
+ let o = e.trim().toLowerCase();
48
+ if (!o) return { problem: "an empty shortcut (two commas in a row, or one at the end)" };
49
+ let s = o.endsWith("++") ? [...o.slice(0, -2).split("+"), "+"] : o.split("+"), c = o === "+" ? ["+"] : s.filter((e) => e !== ""), l = /* @__PURE__ */ new Set(), u = [];
50
+ for (let e of c) {
51
+ if (Object.hasOwn(n, e)) {
52
+ let r = n[e];
53
+ l.add(r === "mod" ? t ? "meta" : "ctrl" : r);
54
+ continue;
55
+ }
56
+ u.push(Object.hasOwn(r, e) ? r[e] : e);
57
+ }
58
+ if (u.length !== 1) return { problem: `"${e.trim()}" names ${u.length ? `${u.length} keys (${u.join(", ")})` : "no key, only modifiers"}: a shortcut is modifiers and ONE key, like "shift+f"` };
59
+ let [d] = u;
60
+ return d.length !== 1 && !i.has(d) ? { problem: `"${d}" in "${e.trim()}" is not a key: use one character ("f", "?", "+") or a key's name (${[...i].slice(0, 15).join(", ")}, f1…f12)` } : { combo: a(l, d) };
61
+ }, s = (e, t = !1) => {
62
+ let n = e.split(",").map((e) => o(e, t));
63
+ return {
64
+ combos: n.flatMap((e) => e.combo ? [e.combo] : []),
65
+ problems: n.flatMap((e) => e.problem ? [e.problem] : [])
66
+ };
67
+ }, c = (e) => {
68
+ let t = e.ctrlKey || e.altKey || e.metaKey, n = /^(?:Key|Digit)([A-Z0-9])$/.exec(e.code), r = t && n ? n[1] : e.key, i = r === " " ? "space" : r.toLowerCase(), o = i.length === 1 && !/[a-z0-9]/.test(i), s = /* @__PURE__ */ new Set();
69
+ return e.ctrlKey && s.add("ctrl"), e.altKey && s.add("alt"), e.shiftKey && !o && s.add("shift"), e.metaKey && s.add("meta"), a(s, i);
70
+ }, l = /* @__PURE__ */ new Set([
71
+ "a",
72
+ "z",
73
+ "y",
74
+ "c",
75
+ "x",
76
+ "v"
77
+ ]), u = /* @__PURE__ */ new Set([
78
+ "arrowleft",
79
+ "arrowright",
80
+ "arrowup",
81
+ "arrowdown",
82
+ "home",
83
+ "end",
84
+ "backspace",
85
+ "delete"
86
+ ]), d = (e) => {
87
+ let t = e.split("+"), n = e.endsWith("++") ? "+" : t[t.length - 1];
88
+ return u.has(n) || l.has(n) && (e.includes("ctrl+") || e.includes("meta+"));
89
+ };
90
+ //#endregion
91
+ export { e as KEY_TRIGGER, d as isFieldEditing, c as keyPressCombo, s as parseKeys };
@@ -47,7 +47,7 @@ export type ContinueNode = {
47
47
  export type Expression = LiteralNode | ArrayLiteralNode | ObjectLiteralNode | RangeNode | PathNode | IndexNode | FunctionNode | FilterExpression | ConcatNode | UnaryNode | BinaryNode | DefaultNode | TernaryNode | ArrowFunctionNode;
48
48
  export type LiteralNode = {
49
49
  readonly type: 'literal';
50
- readonly value: string | number | boolean;
50
+ readonly value: string | number | boolean | null;
51
51
  };
52
52
  export type ArrayLiteralNode = {
53
53
  readonly type: 'array';
@@ -117,7 +117,7 @@ export type DefaultNode = {
117
117
  export type TernaryNode = {
118
118
  readonly type: 'ternary';
119
119
  readonly condition: Expression;
120
- readonly trueExpr: Expression;
120
+ readonly trueExpr: Expression | null;
121
121
  readonly falseExpr: Expression;
122
122
  };
123
123
  export type ArrowFunctionNode = {
@@ -1,7 +1,17 @@
1
- import { ASTNode } from '../AST';
1
+ import { ASTNode, Expression } from '../AST';
2
2
  export type EvalResult = {
3
3
  readonly output: string;
4
4
  readonly variables: Record<string, unknown>;
5
5
  readonly hasSet: boolean;
6
6
  };
7
- export declare const evaluate: (nodes: readonly ASTNode[], context: Record<string, unknown>, keepEmptyTokens?: boolean) => EvalResult;
7
+ /**
8
+ * Renders `nodes` against `context`.
9
+ *
10
+ * `jsonStrings` is for a template the author wrote as a JSON document — `{ "city": "{{ values.city }}" }`: a value
11
+ * printed inside one of its string literals is escaped for it, so a city typed with a quote or on two lines is still
12
+ * that document, not text the reader has to give up on. A value printed anywhere else is printed as always: it IS the
13
+ * JSON value there (`"seen": {{ count }}`).
14
+ */
15
+ export declare const evaluate: (nodes: readonly ASTNode[], context: Record<string, unknown>, keepEmptyTokens?: boolean, jsonStrings?: boolean) => EvalResult;
16
+ /** One expression's value, as it is — not rendered to text. What `processTwigValue` answers a `{{ expr }}` with. */
17
+ export declare const evaluateExpression: (expression: Expression, context: Record<string, unknown>) => unknown;
@@ -1,21 +1,33 @@
1
1
  import { isTruthy as e, resolveCollection as t, resolveObjectEntries as n, valueIn as r } from "./helpers.mjs";
2
2
  import { ARROW_PARAMS as i, filters as a, isRawMarker as o, unwrapRaw as s } from "../filters/filters.mjs";
3
+ import { serializeValue as c } from "../processTwig/helpers.mjs";
3
4
  //#region src/helpers/twigWrapper/Evaluator/Evaluator.ts
4
- var c = [], l = (e, t, n = !1) => {
5
- let r = new u(t, n);
5
+ var l = {
6
+ defined: (e) => e !== void 0,
7
+ null: (e) => e == null,
8
+ none: (e) => e == null,
9
+ empty: (e) => e == null || e === "" || e === !1 || Array.isArray(e) && e.length === 0 || typeof e == "object" && !Array.isArray(e) && Object.keys(e).length === 0,
10
+ iterable: (e) => Array.isArray(e) || typeof e == "object" && !!e,
11
+ even: (e) => typeof e == "number" && e % 2 == 0,
12
+ odd: (e) => typeof e == "number" && Math.abs(e % 2) === 1
13
+ }, u = (e) => e.type === "path" || e.type === "filter" && u(e.subject), d = (e, t) => t == null || t === "" && u(e), f = (e) => e.type === "path" && e.segments.length === 1 ? e.segments[0] : e.type === "literal" && e.value === null ? "null" : void 0, p = [], m = (e, t, n = !1, r = !1) => {
14
+ let i = new g(t, n, r);
6
15
  return {
7
- output: r.evalNodes(e),
8
- variables: r.variables,
9
- hasSet: r.hasSet
16
+ output: i.evalNodes(e),
17
+ variables: i.variables,
18
+ hasSet: i.hasSet
10
19
  };
11
- }, u = class l {
20
+ }, h = (e, t) => new g(t).evalExpression(e), g = class u {
12
21
  variables;
13
22
  keepEmptyTokens;
23
+ jsonStrings;
24
+ inString = !1;
25
+ escaping = !1;
14
26
  breakFlag = !1;
15
27
  continueFlag = !1;
16
28
  hasSet = !1;
17
- constructor(e, t = !1) {
18
- this.variables = { ...e }, this.keepEmptyTokens = t;
29
+ constructor(e, t = !1, n = !1) {
30
+ this.variables = { ...e }, this.keepEmptyTokens = t, this.jsonStrings = n;
19
31
  }
20
32
  evalNodes(e) {
21
33
  let t = e.length;
@@ -27,8 +39,8 @@ var c = [], l = (e, t, n = !1) => {
27
39
  }
28
40
  evalNode(e) {
29
41
  switch (e.type) {
30
- case "text": return e.value;
31
- case "variable": return this.evalVariable(e);
42
+ case "text": return this.jsonStrings && this.followQuotes(e.value), e.value;
43
+ case "variable": return this.jsonStrings && this.inString ? JSON.stringify(this.evalVariable(e)).slice(1, -1) : this.evalVariable(e);
32
44
  case "if": return this.evalIf(e);
33
45
  case "for": return this.evalFor(e);
34
46
  case "set": return this.evalSet(e);
@@ -39,7 +51,13 @@ var c = [], l = (e, t, n = !1) => {
39
51
  }
40
52
  evalVariable(e) {
41
53
  let t = this.evalExpression(e.expression);
42
- return this.keepEmptyTokens && (t == null || t === "") ? e.source : o(t) ? String(s(t)) : typeof t == "function" ? "" : t != null && typeof t != "object" ? String(t) : e.raw ? t == null ? "" : String(t) : typeof t == "object" && t ? JSON.stringify(t) : "";
54
+ return this.keepEmptyTokens && d(e.expression, t) ? e.source : o(t) ? String(s(t)) : typeof t == "function" ? "" : t != null && typeof t != "object" ? String(t) : e.raw ? t == null ? "" : String(t) : typeof t == "object" && t ? JSON.stringify(t) : "";
55
+ }
56
+ followQuotes(e) {
57
+ for (let t = 0; t < e.length; t++) {
58
+ let n = e[t];
59
+ this.escaping ? this.escaping = !1 : this.inString && n === "\\" ? this.escaping = !0 : n === "\"" && (this.inString = !this.inString);
60
+ }
43
61
  }
44
62
  evalIf(t) {
45
63
  if (e(this.evalExpression(t.condition))) return this.evalNodes(t.body);
@@ -94,7 +112,7 @@ var c = [], l = (e, t, n = !1) => {
94
112
  let n = e;
95
113
  for (let e of t) {
96
114
  let t = a[e.name];
97
- t !== void 0 && (n = t(n, e.args.length === 0 ? c : this.evalArgs(e.args)));
115
+ t !== void 0 && (n = t(n, e.args.length === 0 ? p : this.evalArgs(e.args)));
98
116
  }
99
117
  return n;
100
118
  }
@@ -135,13 +153,16 @@ var c = [], l = (e, t, n = !1) => {
135
153
  case "unary": return t.operator === "-" ? -Number(this.evalExpression(t.operand)) : !e(this.evalExpression(t.operand));
136
154
  case "binary": return this.evalBinary(t.operator, t.left, t.right);
137
155
  case "default": return this.evalExpression(t.value) ?? this.evalExpression(t.defaultExpr);
138
- case "ternary": return e(this.evalExpression(t.condition)) ? this.evalExpression(t.trueExpr) : this.evalExpression(t.falseExpr);
156
+ case "ternary": {
157
+ let n = this.evalExpression(t.condition);
158
+ return e(n) ? t.trueExpr ? this.evalExpression(t.trueExpr) : n : this.evalExpression(t.falseExpr);
159
+ }
139
160
  case "arrow": return this.createArrowFunction(t.params, t.body);
140
161
  }
141
162
  }
142
163
  createArrowFunction(e, t) {
143
164
  let n = { ...this.variables }, r = this.keepEmptyTokens, a = (...i) => {
144
- let a = new l(n, r);
165
+ let a = new u(n, r);
145
166
  for (let t = 0; t < e.length; t++) a.variables[e[t]] = i[t];
146
167
  return a.evalExpression(t);
147
168
  };
@@ -200,28 +221,45 @@ var c = [], l = (e, t, n = !1) => {
200
221
  return a;
201
222
  }
202
223
  evalBinary(t, n, i) {
224
+ let a = f(i);
225
+ if ((t === "is" || t === "is not") && a !== void 0) {
226
+ let e = l[a];
227
+ if (e) {
228
+ let r = e(this.evalExpression(n));
229
+ return t === "is" ? r : !r;
230
+ }
231
+ }
203
232
  if (t === "or") return e(this.evalExpression(n)) || e(this.evalExpression(i));
204
233
  if (t === "and") return e(this.evalExpression(n)) && e(this.evalExpression(i));
205
- let a = this.evalExpression(n), o = this.evalExpression(i), s = typeof a == "number" && typeof o == "number";
234
+ let o = this.evalExpression(n), s = this.evalExpression(i), u = typeof o == "number" && typeof s == "number";
206
235
  switch (t) {
207
- case "+": return s ? a + o : Number(a) + Number(o);
208
- case "-": return s ? a - o : Number(a) - Number(o);
209
- case "*": return s ? a * o : Number(a) * Number(o);
210
- case "/": return s ? a / o : Number(a) / Number(o);
211
- case "%": return s ? a % o : Number(a) % Number(o);
212
- case "==": return a === o || String(a) === String(o);
213
- case "!=": return a !== o && String(a) !== String(o);
214
- case ">": return s ? a > o : Number(a) > Number(o);
215
- case "<": return s ? a < o : Number(a) < Number(o);
216
- case ">=": return s ? a >= o : Number(a) >= Number(o);
217
- case "<=": return s ? a <= o : Number(a) <= Number(o);
218
- case "in": return r(a, o);
219
- case "not in": return !r(a, o);
220
- case "is": return a === o;
221
- case "is not": return a !== o;
236
+ case "+": return u ? o + s : Number(o) + Number(s);
237
+ case "-": return u ? o - s : Number(o) - Number(s);
238
+ case "*": return u ? o * s : Number(o) * Number(s);
239
+ case "/": return u ? o / s : Number(o) / Number(s);
240
+ case "//": return Math.floor(Number(o) / Number(s));
241
+ case "**": return Number(o) ** Number(s);
242
+ case "starts with": return typeof o == "string" && o.startsWith(c(s));
243
+ case "ends with": return typeof o == "string" && o.endsWith(c(s));
244
+ case "%": return u ? o % s : Number(o) % Number(s);
245
+ case "==": return o === s || String(o) === String(s);
246
+ case "!=": return o !== s && String(o) !== String(s);
247
+ case ">": return u ? o > s : Number(o) > Number(s);
248
+ case "<": return u ? o < s : Number(o) < Number(s);
249
+ case ">=": return u ? o >= s : Number(o) >= Number(s);
250
+ case "<=": return u ? o <= s : Number(o) <= Number(s);
251
+ case "in": return r(o, s);
252
+ case "not in": return !r(o, s);
253
+ case "same as": return o === s;
254
+ case "divisible by": {
255
+ let e = Number(s);
256
+ return e !== 0 && Number.isFinite(e) && Number(o) % e === 0;
257
+ }
258
+ case "is": return o === s;
259
+ case "is not": return o !== s;
222
260
  default: return !1;
223
261
  }
224
262
  }
225
263
  };
226
264
  //#endregion
227
- export { l as evaluate };
265
+ export { m as evaluate, h as evaluateExpression };
@@ -1,2 +1,2 @@
1
- export { evaluate } from './Evaluator';
1
+ export { evaluate, evaluateExpression } from './Evaluator';
2
2
  export type { EvalResult } from './Evaluator';
@@ -1,2 +1,2 @@
1
- import { evaluate as e } from "./Evaluator.mjs";
2
- export { e as evaluate };
1
+ import { evaluate as e, evaluateExpression as t } from "./Evaluator.mjs";
2
+ export { e as evaluate, t as evaluateExpression };
@@ -1,3 +1,3 @@
1
1
  import { Expression, FilterCall } from '../AST';
2
- export declare const parseExpression: (expr: string) => Expression;
3
- export declare const parseApplyFilters: (expr: string) => FilterCall[];
2
+ export declare const parseExpression: (expr: string, issues?: string[]) => Expression;
3
+ export declare const parseApplyFilters: (expr: string, issues?: string[]) => FilterCall[];
@@ -1,20 +1,54 @@
1
1
  import { Char as e, isDigit as t } from "../charClass.mjs";
2
2
  import { Cursor as n } from "./Cursor.mjs";
3
3
  //#region src/helpers/twigWrapper/Parser/ExpressionParser.ts
4
- var r = (e) => new a(e).parseTernary(), i = (e) => new a(e).parseApplyChain(), a = class extends n {
4
+ var r = (e, t) => {
5
+ let n = new s(e, t), r = n.parseTernary();
6
+ return n.expectEnd(), r;
7
+ }, i = (e, t) => {
8
+ let n = new s(e, t), r = n.parseApplyChain();
9
+ return n.expectEnd(), r;
10
+ }, a = ["same as", "divisible by"], o = "`matches` is not supported: templates evaluate no regular expressions. Use `starts with`, `ends with` or `in`.", s = class extends n {
11
+ issues;
12
+ constructor(e, t) {
13
+ super(e), this.issues = t;
14
+ }
15
+ report(e) {
16
+ this.issues?.push(e);
17
+ }
18
+ expectEnd() {
19
+ this.skipWs(), this.eof() || this.report(`Unexpected "${this.src.slice(this.pos).trim()}" in "${this.src.trim()}"`);
20
+ }
21
+ expectChar(e, t) {
22
+ if (this.skipWs(), this.peek() === e) {
23
+ this.pos++;
24
+ return;
25
+ }
26
+ this.report(`Missing ${t} in "${this.src.trim()}"`);
27
+ }
5
28
  parseTernary() {
6
29
  let t = this.parseOr();
7
- if (this.skipWs(), this.peek() === e.Question) {
8
- this.pos++, this.skipWs();
9
- let n = this.parseOr();
10
- if (this.skipWs(), this.peek() === e.Colon) return this.pos++, this.skipWs(), {
11
- type: "ternary",
12
- condition: t,
13
- trueExpr: n,
14
- falseExpr: this.parseTernary()
15
- };
16
- }
17
- return t;
30
+ if (this.skipWs(), this.peek() !== e.Question) return t;
31
+ if (this.pos++, this.skipWs(), this.peek() === e.Colon) return this.pos++, this.skipWs(), {
32
+ type: "ternary",
33
+ condition: t,
34
+ trueExpr: null,
35
+ falseExpr: this.parseTernary()
36
+ };
37
+ let n = this.parseOr();
38
+ return this.skipWs(), this.peek() === e.Colon ? (this.pos++, this.skipWs(), {
39
+ type: "ternary",
40
+ condition: t,
41
+ trueExpr: n,
42
+ falseExpr: this.parseTernary()
43
+ }) : {
44
+ type: "ternary",
45
+ condition: t,
46
+ trueExpr: n,
47
+ falseExpr: {
48
+ type: "literal",
49
+ value: ""
50
+ }
51
+ };
18
52
  }
19
53
  parseOr() {
20
54
  let e = this.parseAnd();
@@ -47,9 +81,27 @@ var r = (e) => new a(e).parseTernary(), i = (e) => new a(e).parseApplyChain(), a
47
81
  let e = this.parseConcat();
48
82
  for (this.skipWs(); !this.eof();) {
49
83
  if (this.matchKeyword("is")) {
50
- this.skipWs(), e = {
84
+ this.skipWs();
85
+ let t = this.matchKeyword("not");
86
+ this.skipWs();
87
+ let n = this.matchWordedTest();
88
+ if (n) {
89
+ let r = {
90
+ type: "binary",
91
+ operator: n,
92
+ left: e,
93
+ right: this.parseConcat()
94
+ };
95
+ e = t ? {
96
+ type: "unary",
97
+ operator: "not",
98
+ operand: r
99
+ } : r, this.skipWs();
100
+ continue;
101
+ }
102
+ e = {
51
103
  type: "binary",
52
- operator: this.matchKeyword("not") ? "is not" : "is",
104
+ operator: t ? "is not" : "is",
53
105
  left: e,
54
106
  right: this.parseConcat()
55
107
  }, this.skipWs();
@@ -69,7 +121,7 @@ var r = (e) => new a(e).parseTernary(), i = (e) => new a(e).parseApplyChain(), a
69
121
  return this.pos = this.src.length, {
70
122
  type: "unary",
71
123
  operator: "not",
72
- operand: r(t)
124
+ operand: r(t, this.issues)
73
125
  };
74
126
  }
75
127
  if (this.matchKeyword("in")) {
@@ -81,7 +133,7 @@ var r = (e) => new a(e).parseTernary(), i = (e) => new a(e).parseApplyChain(), a
81
133
  }, this.skipWs();
82
134
  continue;
83
135
  }
84
- let t = this.matchBinaryOp();
136
+ let t = this.matchAffixTest();
85
137
  if (t) {
86
138
  e = {
87
139
  type: "binary",
@@ -91,10 +143,48 @@ var r = (e) => new a(e).parseTernary(), i = (e) => new a(e).parseApplyChain(), a
91
143
  }, this.skipWs();
92
144
  continue;
93
145
  }
146
+ if (this.matchKeyword("matches")) {
147
+ this.report(o), e = {
148
+ type: "binary",
149
+ operator: "matches",
150
+ left: e,
151
+ right: this.parseConcat()
152
+ }, this.skipWs();
153
+ continue;
154
+ }
155
+ let n = this.matchBinaryOp();
156
+ if (n) {
157
+ e = {
158
+ type: "binary",
159
+ operator: n,
160
+ left: e,
161
+ right: this.parseConcat()
162
+ }, this.skipWs();
163
+ continue;
164
+ }
94
165
  break;
95
166
  }
96
167
  return e;
97
168
  }
169
+ matchWordedTest() {
170
+ let e = this.pos;
171
+ for (let t of a) {
172
+ let [n, r] = t.split(" ");
173
+ if (this.matchKeyword(n)) {
174
+ if (this.skipWs(), this.matchKeyword(r)) return t;
175
+ this.pos = e;
176
+ }
177
+ }
178
+ return null;
179
+ }
180
+ matchAffixTest() {
181
+ let e = this.pos;
182
+ for (let t of ["starts", "ends"]) if (this.matchKeyword(t)) {
183
+ if (this.matchKeyword("with")) return t === "starts" ? "starts with" : "ends with";
184
+ this.pos = e;
185
+ }
186
+ return null;
187
+ }
98
188
  parseConcat() {
99
189
  let t = this.parseAdditive();
100
190
  for (this.skipWs(); this.peek() === e.Tilde;) {
@@ -122,15 +212,27 @@ var r = (e) => new a(e).parseTernary(), i = (e) => new a(e).parseApplyChain(), a
122
212
  return t;
123
213
  }
124
214
  parseMultiplicative() {
125
- let t = this.parseDefault();
215
+ let t = this.parsePower();
126
216
  this.skipWs();
127
- for (let n = this.peek(); n === e.Star || n === e.Slash || n === e.Percent; n = this.peek()) this.pos++, t = {
217
+ for (let n = this.peek(); (n === e.Star || n === e.Slash || n === e.Percent) && (n !== e.Star || this.at(1) !== e.Star); n = this.peek()) {
218
+ let r = n === e.Slash && this.at(1) === e.Slash;
219
+ this.pos += r ? 2 : 1, t = {
220
+ type: "binary",
221
+ operator: r ? "//" : n === e.Star ? "*" : n === e.Slash ? "/" : "%",
222
+ left: t,
223
+ right: this.parsePower()
224
+ }, this.skipWs();
225
+ }
226
+ return t;
227
+ }
228
+ parsePower() {
229
+ let t = this.parseDefault();
230
+ return this.skipWs(), this.peek() !== e.Star || this.at(1) !== e.Star ? t : (this.pos += 2, {
128
231
  type: "binary",
129
- operator: n === e.Star ? "*" : n === e.Slash ? "/" : "%",
232
+ operator: "**",
130
233
  left: t,
131
- right: this.parseDefault()
132
- }, this.skipWs();
133
- return t;
234
+ right: this.parsePower()
235
+ });
134
236
  }
135
237
  parseDefault() {
136
238
  if (this.skipWs(), this.peek() === e.Minus && t(this.at(1))) return this.maybeTrailingFilters({
@@ -163,18 +265,25 @@ var r = (e) => new a(e).parseTernary(), i = (e) => new a(e).parseApplyChain(), a
163
265
  });
164
266
  this.pos = t;
165
267
  let r = this.parseTernary();
166
- return this.skipWs(), this.peek() === e.RParen && this.pos++, this.maybeTrailingFilters(r);
268
+ return this.expectChar(e.RParen, "a closing \")\""), this.maybeTrailingFilters(this.parseAccessChain(r, null));
167
269
  }
168
- return n === e.SingleQuote || n === e.DoubleQuote ? this.maybeTrailingFilters({
270
+ if (n === e.SingleQuote || n === e.DoubleQuote) return this.maybeTrailingFilters({
169
271
  type: "literal",
170
272
  value: this.scanStringLiteral()
171
- }) : t(n) ? this.maybeTrailingFilters({
273
+ });
274
+ if (t(n)) return this.maybeTrailingFilters({
172
275
  type: "literal",
173
276
  value: this.scanNumber()
174
- }) : n === e.LBracket ? (this.pos++, this.maybeTrailingFilters({
175
- type: "array",
176
- elements: this.parseArgList(e.RBracket)
177
- })) : n === e.LBrace ? (this.pos++, this.maybeTrailingFilters(this.parseObjectLiteral())) : this.parsePathOrFunctionOrArrow();
277
+ });
278
+ if (n === e.LBracket) {
279
+ this.pos++;
280
+ let t = {
281
+ type: "array",
282
+ elements: this.parseArgList(e.RBracket)
283
+ };
284
+ return this.maybeTrailingFilters(this.parseAccessChain(t, null));
285
+ }
286
+ return n === e.LBrace ? (this.pos++, this.maybeTrailingFilters(this.parseAccessChain(this.parseObjectLiteral(), null))) : this.parsePathOrFunctionOrArrow();
178
287
  }
179
288
  tryParseArrowParams() {
180
289
  let t = this.pos, n = [];
@@ -191,7 +300,7 @@ var r = (e) => new a(e).parseTernary(), i = (e) => new a(e).parseApplyChain(), a
191
300
  }
192
301
  parsePathOrFunctionOrArrow() {
193
302
  let t = this.scanName();
194
- if (!t) return this.pos++, {
303
+ if (!t) return this.report(this.eof() ? `Missing a value at the end of "${this.src.trim()}"` : `Unexpected "${this.src.slice(this.pos).trim()}" in "${this.src.trim()}"`), this.pos++, {
195
304
  type: "literal",
196
305
  value: ""
197
306
  };
@@ -199,6 +308,10 @@ var r = (e) => new a(e).parseTernary(), i = (e) => new a(e).parseApplyChain(), a
199
308
  type: "literal",
200
309
  value: t === "true"
201
310
  });
311
+ if (t === "null" || t === "none") return this.maybeTrailingFilters({
312
+ type: "literal",
313
+ value: null
314
+ });
202
315
  if (this.skipWs(), this.peek() === e.Equals && this.at(1) === e.Greater) return this.pos += 2, this.maybeTrailingFilters({
203
316
  type: "arrow",
204
317
  params: [t],
@@ -244,7 +357,7 @@ var r = (e) => new a(e).parseTernary(), i = (e) => new a(e).parseApplyChain(), a
244
357
  if (t !== e.LBracket) break;
245
358
  this.pos++;
246
359
  let n = this.parseTernary();
247
- if (this.skipWs(), this.peek() === e.RBracket && this.pos++, i && n.type === "literal" && typeof n.value != "boolean") {
360
+ if (this.expectChar(e.RBracket, "a closing \"]\""), i && n.type === "literal" && (typeof n.value == "string" || typeof n.value == "number")) {
248
361
  i.push(String(n.value));
249
362
  continue;
250
363
  }
@@ -278,7 +391,7 @@ var r = (e) => new a(e).parseTernary(), i = (e) => new a(e).parseApplyChain(), a
278
391
  value: this.parseTernary()
279
392
  }), this.skipWs(), this.peek() === e.Comma && (this.pos++, this.skipWs());
280
393
  }
281
- return this.peek() === e.RBrace && this.pos++, {
394
+ return this.expectChar(e.RBrace, "a closing \"}\""), {
282
395
  type: "object",
283
396
  entries: t
284
397
  };
@@ -306,7 +419,7 @@ var r = (e) => new a(e).parseTernary(), i = (e) => new a(e).parseApplyChain(), a
306
419
  parseArgList(t) {
307
420
  let n = [];
308
421
  for (this.skipWs(); !this.eof() && this.peek() !== t;) n.push(this.parseTernary()), this.skipWs(), this.peek() === e.Comma && (this.pos++, this.skipWs());
309
- return this.peek() === t && this.pos++, n;
422
+ return this.expectChar(t, t === e.RParen ? "a closing \")\"" : "a closing \"]\""), n;
310
423
  }
311
424
  parseTrailingFilters() {
312
425
  let t = [];
@@ -321,7 +434,7 @@ var r = (e) => new a(e).parseTernary(), i = (e) => new a(e).parseApplyChain(), a
321
434
  }
322
435
  readFilter() {
323
436
  let t = this.scanName();
324
- return this.skipWs(), this.peek() === e.LParen ? (this.pos++, {
437
+ return t || this.report(`A "|" with no filter name after it in "${this.src.trim()}"`), this.skipWs(), this.peek() === e.LParen ? (this.pos++, {
325
438
  name: t,
326
439
  args: this.parseArgList(e.RParen)
327
440
  }) : {
@@ -1,3 +1,4 @@
1
1
  import { Token } from '../Lexer';
2
2
  import { ParseResult } from './types';
3
- export declare const parse: (tokens: readonly Token[], keepEmptyTokens?: boolean) => ParseResult;
3
+ /** `issues`, when given, collects what the expression grammar read past rather than understood — see `inspectTemplate`. */
4
+ export declare const parse: (tokens: readonly Token[], keepEmptyTokens?: boolean, issues?: string[]) => ParseResult;