@samva/markup 0.1.1 → 0.1.2

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 (38) hide show
  1. package/dist/ast.js +1 -1
  2. package/dist/{checks-CW0nFj5n.js → checks-D-zFQt5R.js} +2 -2
  3. package/dist/checks.js +1 -1
  4. package/dist/compile-sms.d.ts +1 -1
  5. package/dist/compile-whatsapp.d.ts +1 -1
  6. package/dist/components.d.ts +3 -3
  7. package/dist/conditionals.js +1 -1
  8. package/dist/diagnostics.js +2 -2
  9. package/dist/jsx-dev-runtime.d.ts +1 -1
  10. package/dist/{jsx-runtime-fSxcvlx4.d.ts → jsx-runtime-eNIMY87F.d.ts} +2 -2
  11. package/dist/jsx-runtime.d.ts +1 -1
  12. package/dist/ops.js +2 -2
  13. package/dist/{parser-yzjUOGhc.d.ts → parser-DkQKIjDa.d.ts} +11 -2
  14. package/dist/parser.d.ts +2 -2
  15. package/dist/parser.js +48 -9
  16. package/dist/predicate-CvkzT-a2.js +539 -0
  17. package/dist/{predicate-DTtVtLK7.d.ts → predicate-G2SeSvoN.d.ts} +9 -2
  18. package/dist/predicate.d.ts +2 -2
  19. package/dist/predicate.js +2 -417
  20. package/dist/presets/category-mapping.d.ts +1 -1
  21. package/dist/presets/public-gallery.d.ts +2 -490
  22. package/dist/presets/public-gallery.js +2 -1
  23. package/dist/presets/public-handoff.d.ts +2 -68
  24. package/dist/presets/public-handoff.js +110 -24
  25. package/dist/presets/public-preview-artifacts.d.ts +2 -2
  26. package/dist/presets/public-preview.d.ts +2 -1168
  27. package/dist/presets/public-preview.js +17 -17
  28. package/dist/presets/sources.js +17 -17
  29. package/dist/public-gallery-D0Zv0pZE.d.ts +611 -0
  30. package/dist/public-preview-u1Z9aaGq.d.ts +1168 -0
  31. package/dist/render-template.d.ts +2 -2
  32. package/dist/render-template.js +1 -1
  33. package/dist/{variables-3NGLpNTB.d.ts → variables-if1VrV34.d.ts} +2 -2
  34. package/dist/variables.d.ts +1 -1
  35. package/dist/variables.js +1 -1
  36. package/generated/sml-email-language-reference.md +1 -1
  37. package/generated/sml-language-reference.md +1 -1
  38. package/package.json +4 -3
package/dist/predicate.js CHANGED
@@ -1,417 +1,2 @@
1
- import { Result } from "effect";
2
- //#region src/predicate.ts
3
- const CHAR_TAB = 9;
4
- const CHAR_LINE_FEED = 10;
5
- const CHAR_CARRIAGE_RETURN = 13;
6
- const CHAR_SPACE = 32;
7
- const CHAR_BANG = 33;
8
- const CHAR_SINGLE_QUOTE = 39;
9
- const CHAR_OPEN_PAREN = 40;
10
- const CHAR_CLOSE_PAREN = 41;
11
- const CHAR_MINUS = 45;
12
- const CHAR_DOT = 46;
13
- const CHAR_LESS_THAN = 60;
14
- const CHAR_EQUALS = 61;
15
- const CHAR_GREATER_THAN = 62;
16
- const CHAR_UNDERSCORE = 95;
17
- const CHAR_0 = 48;
18
- const CHAR_9 = 57;
19
- const CHAR_UPPER_A = 65;
20
- const CHAR_UPPER_Z = 90;
21
- const CHAR_LOWER_A = 97;
22
- const CHAR_LOWER_Z = 122;
23
- const isWhitespace = (code) => code === CHAR_SPACE || code === CHAR_TAB || code === CHAR_LINE_FEED || code === CHAR_CARRIAGE_RETURN;
24
- const isDigit = (code) => code >= CHAR_0 && code <= CHAR_9;
25
- const isLetter = (code) => code >= CHAR_UPPER_A && code <= CHAR_UPPER_Z || code >= CHAR_LOWER_A && code <= CHAR_LOWER_Z;
26
- const isNameStart = (code) => isLetter(code) || code === CHAR_UNDERSCORE;
27
- const isNameChar = (code) => isNameStart(code) || isDigit(code);
28
- const KEYWORDS = [
29
- "and",
30
- "or",
31
- "not"
32
- ];
33
- const isKeyword = (text) => KEYWORDS.includes(text);
34
- const tokenize = (source, baseOffset) => {
35
- const tokens = [];
36
- let index = 0;
37
- const length = source.length;
38
- const failAt = (code, message, start, end) => Result.fail({ diagnostic: {
39
- code,
40
- message,
41
- span: {
42
- start: baseOffset + start,
43
- end: baseOffset + end
44
- }
45
- } });
46
- while (index < length) {
47
- const code = source.charCodeAt(index);
48
- if (isWhitespace(code)) {
49
- index++;
50
- continue;
51
- }
52
- const start = index;
53
- if (code === CHAR_OPEN_PAREN) {
54
- index++;
55
- tokens.push({
56
- kind: "lparen",
57
- text: "(",
58
- span: {
59
- start: baseOffset + start,
60
- end: baseOffset + index
61
- }
62
- });
63
- continue;
64
- }
65
- if (code === CHAR_CLOSE_PAREN) {
66
- index++;
67
- tokens.push({
68
- kind: "rparen",
69
- text: ")",
70
- span: {
71
- start: baseOffset + start,
72
- end: baseOffset + index
73
- }
74
- });
75
- continue;
76
- }
77
- if (code === CHAR_EQUALS || code === CHAR_BANG) {
78
- if (source.charCodeAt(index + 1) === CHAR_EQUALS) {
79
- index += 2;
80
- tokens.push({
81
- kind: "op",
82
- text: code === CHAR_EQUALS ? "==" : "!=",
83
- span: {
84
- start: baseOffset + start,
85
- end: baseOffset + index
86
- }
87
- });
88
- continue;
89
- }
90
- return failAt("predicate-invalid-operator", `unexpected ${String.fromCharCode(code)} — ${code === CHAR_EQUALS ? "write == to compare" : "write != to compare"}`, start, start + 1);
91
- }
92
- if (code === CHAR_GREATER_THAN || code === CHAR_LESS_THAN) {
93
- index++;
94
- if (source.charCodeAt(index) === CHAR_EQUALS) index++;
95
- tokens.push({
96
- kind: "op",
97
- text: source.slice(start, index),
98
- span: {
99
- start: baseOffset + start,
100
- end: baseOffset + index
101
- }
102
- });
103
- continue;
104
- }
105
- if (code === CHAR_SINGLE_QUOTE) {
106
- index++;
107
- const contentStart = index;
108
- while (index < length && source.charCodeAt(index) !== CHAR_SINGLE_QUOTE) index++;
109
- if (index >= length) return failAt("predicate-unterminated-string", "unterminated string — add a closing '", start, length);
110
- const value = source.slice(contentStart, index);
111
- index++;
112
- if (value.includes("--")) return failAt("predicate-string-double-dash", "string literals cannot contain -- (predicates are embedded in HTML comment markers)", start, index);
113
- tokens.push({
114
- kind: "string",
115
- text: source.slice(start, index),
116
- string: value,
117
- span: {
118
- start: baseOffset + start,
119
- end: baseOffset + index
120
- }
121
- });
122
- continue;
123
- }
124
- if (isDigit(code) || code === CHAR_MINUS && isDigit(source.charCodeAt(index + 1))) {
125
- index++;
126
- while (index < length && isDigit(source.charCodeAt(index))) index++;
127
- if (source.charCodeAt(index) === CHAR_DOT && isDigit(source.charCodeAt(index + 1))) {
128
- index++;
129
- while (index < length && isDigit(source.charCodeAt(index))) index++;
130
- }
131
- tokens.push({
132
- kind: "number",
133
- text: source.slice(start, index),
134
- number: Number.parseFloat(source.slice(start, index)),
135
- span: {
136
- start: baseOffset + start,
137
- end: baseOffset + index
138
- }
139
- });
140
- continue;
141
- }
142
- if (isNameStart(code)) {
143
- index++;
144
- while (index < length && isNameChar(source.charCodeAt(index))) index++;
145
- if (source.charCodeAt(index) === CHAR_DOT) return failAt("predicate-path-not-supported", `unexpected . after "${source.slice(start, index)}" — predicates use flat variable names, not paths`, start, index + 1);
146
- tokens.push({
147
- kind: "name",
148
- text: source.slice(start, index),
149
- span: {
150
- start: baseOffset + start,
151
- end: baseOffset + index
152
- }
153
- });
154
- continue;
155
- }
156
- if (code === CHAR_DOT) return failAt("predicate-path-not-supported", "unexpected . — predicates use flat variable names, not paths", start, start + 1);
157
- return failAt("predicate-unexpected-character", `unexpected character ${JSON.stringify(String.fromCharCode(code))} in predicate`, start, start + 1);
158
- }
159
- tokens.push({
160
- kind: "eof",
161
- text: "",
162
- span: {
163
- start: baseOffset + length,
164
- end: baseOffset + length
165
- }
166
- });
167
- return Result.succeed(tokens);
168
- };
169
- const COMPARISON_OPS = [
170
- "==",
171
- "!=",
172
- ">",
173
- ">=",
174
- "<",
175
- "<="
176
- ];
177
- /**
178
- * Parses a predicate. `baseOffset` is the absolute source offset of the
179
- * predicate's first character (an <If> test attribute passes valueSpan.start),
180
- * so diagnostic and node spans point into the containing document.
181
- */
182
- const parsePredicate = (source, baseOffset = 0) => {
183
- const lexed = tokenize(source, baseOffset);
184
- if (Result.isFailure(lexed)) return Result.fail([lexed.failure.diagnostic]);
185
- const tokens = lexed.success;
186
- let index = 0;
187
- let diagnostic;
188
- const fail = (code, message, span) => {
189
- diagnostic ??= {
190
- code,
191
- message,
192
- span
193
- };
194
- return null;
195
- };
196
- const peek = () => tokens[index];
197
- const advance = () => tokens[index++];
198
- const isKeywordToken = (token, keyword) => token.kind === "name" && token.text === keyword;
199
- const parsePrimary = () => {
200
- const token = advance();
201
- if (token.kind === "lparen") {
202
- const inner = parseOr();
203
- if (inner === null) return null;
204
- const close = advance();
205
- if (close.kind !== "rparen") return fail("predicate-missing-paren", "missing ) — close the group", close.span);
206
- return inner;
207
- }
208
- if (token.kind === "name") {
209
- if (isKeyword(token.text)) return fail("predicate-unexpected-token", `unexpected "${token.text}" — expected a variable name, comparison, or ( group )`, token.span);
210
- const opToken = peek();
211
- if (opToken.kind !== "op") return {
212
- kind: "name",
213
- name: token.text,
214
- span: token.span
215
- };
216
- advance();
217
- const op = COMPARISON_OPS.find((candidate) => candidate === opToken.text);
218
- if (op === void 0) return fail("predicate-invalid-operator", `unknown operator ${opToken.text} — use ==, !=, >, >=, <, or <=`, opToken.span);
219
- const literalToken = advance();
220
- if (literalToken.kind === "string") return {
221
- kind: "comparison",
222
- name: token.text,
223
- op,
224
- literal: {
225
- kind: "string",
226
- value: literalToken.string
227
- },
228
- span: {
229
- start: token.span.start,
230
- end: literalToken.span.end
231
- }
232
- };
233
- if (literalToken.kind === "number") return {
234
- kind: "comparison",
235
- name: token.text,
236
- op,
237
- literal: {
238
- kind: "number",
239
- value: literalToken.number
240
- },
241
- span: {
242
- start: token.span.start,
243
- end: literalToken.span.end
244
- }
245
- };
246
- return fail("predicate-expected-literal", `expected a literal after ${op} — write ${token.text} ${op} 'value' or ${token.text} ${op} 5`, literalToken.span);
247
- }
248
- if (token.kind === "eof") return fail("predicate-unexpected-end", "unexpected end of predicate — expected a variable name, comparison, or ( group )", token.span);
249
- return fail("predicate-unexpected-token", `unexpected ${token.text} — comparisons put the variable first: name == 'value'`, token.span);
250
- };
251
- const parseUnary = () => {
252
- const token = peek();
253
- if (isKeywordToken(token, "not")) {
254
- advance();
255
- const operand = parsePrimary();
256
- if (operand === null) return null;
257
- return {
258
- kind: "not",
259
- operand,
260
- span: {
261
- start: token.span.start,
262
- end: operand.span.end
263
- }
264
- };
265
- }
266
- return parsePrimary();
267
- };
268
- const parseAnd = () => {
269
- let left = parseUnary();
270
- while (left !== null && isKeywordToken(peek(), "and")) {
271
- advance();
272
- const right = parseUnary();
273
- if (right === null) return null;
274
- left = {
275
- kind: "and",
276
- left,
277
- right,
278
- span: {
279
- start: left.span.start,
280
- end: right.span.end
281
- }
282
- };
283
- }
284
- return left;
285
- };
286
- const parseOr = () => {
287
- let left = parseAnd();
288
- while (left !== null && isKeywordToken(peek(), "or")) {
289
- advance();
290
- const right = parseAnd();
291
- if (right === null) return null;
292
- left = {
293
- kind: "or",
294
- left,
295
- right,
296
- span: {
297
- start: left.span.start,
298
- end: right.span.end
299
- }
300
- };
301
- }
302
- return left;
303
- };
304
- if (source.trim().length === 0) return Result.fail([{
305
- code: "predicate-empty",
306
- message: "empty predicate — write e.g. plan == 'pro'",
307
- span: {
308
- start: baseOffset,
309
- end: baseOffset + source.length
310
- }
311
- }]);
312
- const ast = parseOr();
313
- if (ast !== null && diagnostic === void 0) {
314
- const trailing = peek();
315
- if (trailing.kind !== "eof") fail("predicate-trailing-input", `unexpected ${JSON.stringify(trailing.text)} after the predicate — join clauses with "and" or "or"`, trailing.span);
316
- }
317
- if (ast === null || diagnostic !== void 0) return Result.fail([diagnostic ?? {
318
- code: "predicate-parse-failed",
319
- message: "predicate parse failed",
320
- span: {
321
- start: baseOffset,
322
- end: baseOffset + source.length
323
- }
324
- }]);
325
- return Result.succeed(ast);
326
- };
327
- const toNumber = (value) => {
328
- if (typeof value === "number") return value;
329
- if (typeof value === "string" && value.trim() !== "") return Number(value);
330
- return NaN;
331
- };
332
- const compareNumbers = (op, left, right) => {
333
- switch (op) {
334
- case "==": return left === right;
335
- case "!=": return left !== right;
336
- case ">": return left > right;
337
- case ">=": return left >= right;
338
- case "<": return left < right;
339
- case "<=": return left <= right;
340
- }
341
- };
342
- const evaluateComparison = (node, variables) => {
343
- const value = variables[node.name];
344
- if (value === void 0 || value === null) return false;
345
- if (node.literal.kind === "number") {
346
- const left = toNumber(value);
347
- if (Number.isNaN(left)) return false;
348
- return compareNumbers(node.op, left, node.literal.value);
349
- }
350
- if (node.op === "==" || node.op === "!=") {
351
- if (typeof value !== "string") return false;
352
- return node.op === "==" ? value === node.literal.value : value !== node.literal.value;
353
- }
354
- const left = toNumber(value);
355
- const right = toNumber(node.literal.value);
356
- if (Number.isNaN(left) || Number.isNaN(right)) return false;
357
- return compareNumbers(node.op, left, right);
358
- };
359
- const evaluatePredicate = (ast, variables) => {
360
- switch (ast.kind) {
361
- case "or": return evaluatePredicate(ast.left, variables) || evaluatePredicate(ast.right, variables);
362
- case "and": return evaluatePredicate(ast.left, variables) && evaluatePredicate(ast.right, variables);
363
- case "not": return !evaluatePredicate(ast.operand, variables);
364
- case "comparison": return evaluateComparison(ast, variables);
365
- case "name": {
366
- const value = variables[ast.name];
367
- return value !== void 0 && value !== null && value !== "";
368
- }
369
- }
370
- };
371
- const precedence = (node) => {
372
- switch (node.kind) {
373
- case "or": return 1;
374
- case "and": return 2;
375
- case "not": return 3;
376
- case "comparison":
377
- case "name": return 4;
378
- }
379
- };
380
- const printLiteral = (literal) => literal.kind === "string" ? `'${literal.value}'` : String(literal.value);
381
- const printNode = (node, minPrecedence) => {
382
- const wrap = (text) => precedence(node) < minPrecedence ? `(${text})` : text;
383
- switch (node.kind) {
384
- case "or": return wrap(`${printNode(node.left, 1)} or ${printNode(node.right, 1)}`);
385
- case "and": return wrap(`${printNode(node.left, 2)} and ${printNode(node.right, 2)}`);
386
- case "not": return wrap(`not ${printNode(node.operand, 4)}`);
387
- case "comparison": return wrap(`${node.name} ${node.op} ${printLiteral(node.literal)}`);
388
- case "name": return wrap(node.name);
389
- }
390
- };
391
- /** Canonical form: single space around operators/keywords, minimal parens. */
392
- const printPredicate = (ast) => printNode(ast, 0);
393
- const collectPredicateVariables = (ast) => {
394
- const names = /* @__PURE__ */ new Set();
395
- const visit = (node) => {
396
- switch (node.kind) {
397
- case "or":
398
- case "and":
399
- visit(node.left);
400
- visit(node.right);
401
- return;
402
- case "not":
403
- visit(node.operand);
404
- return;
405
- case "comparison":
406
- case "name":
407
- names.add(node.name);
408
- return;
409
- }
410
- };
411
- visit(ast);
412
- return names;
413
- };
414
- //#endregion
415
- export { collectPredicateVariables, evaluatePredicate, parsePredicate, printPredicate };
416
-
417
- //# sourceMappingURL=predicate.js.map
1
+ import { a as printPredicate, i as parsePredicate, n as collectPredicateVariables, r as evaluatePredicate, t as PREDICATE_PARSER_LIMITS } from "./predicate-CvkzT-a2.js";
2
+ export { PREDICATE_PARSER_LIMITS, collectPredicateVariables, evaluatePredicate, parsePredicate, printPredicate };
@@ -1,5 +1,5 @@
1
1
  import { PresetCategory } from "../presets.js";
2
- import { TemplateCollectionId } from "./public-gallery.js";
2
+ import { i as TemplateCollectionId } from "../public-gallery-D0Zv0pZE.js";
3
3
  //#region presets/category-mapping.d.ts
4
4
  declare const LAB_DIMENSIONS: readonly ["newsletter", "receipt", "security", "product-update", "onboarding", "promotion", "shipping", "social-notification"];
5
5
  type LabDimension = (typeof LAB_DIMENSIONS)[number];