@samva/markup 0.5.0 → 0.6.0

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 (80) hide show
  1. package/AGENTS.md +2 -0
  2. package/dist/{ast-BLybiDxp.d.ts → ast-BrDtApwS.d.ts} +2 -2
  3. package/dist/ast.d.ts +1 -1
  4. package/dist/ast.js +1 -1
  5. package/dist/{catalog-Db0UcCTg.d.ts → catalog-60eaYC7b.d.ts} +2 -2
  6. package/dist/{checks-CmmITP6j.js → checks-DBweSIPN.js} +12 -14
  7. package/dist/checks.d.ts +1 -1
  8. package/dist/checks.js +1 -1
  9. package/dist/classes.d.ts +1 -1
  10. package/dist/compile-sms.d.ts +3 -3
  11. package/dist/compile-whatsapp.d.ts +3 -3
  12. package/dist/compile.d.ts +2 -2
  13. package/dist/compiler.d.ts +7 -4
  14. package/dist/compiler.js +40 -40
  15. package/dist/components.d.ts +4 -4
  16. package/dist/conditionals.js +55 -23
  17. package/dist/{corpus-CM7rKX41.d.ts → corpus-BjYMqOoY.d.ts} +2 -2
  18. package/dist/{css-DoNc7CiC.d.ts → css-COcFOT1y.d.ts} +3 -3
  19. package/dist/{diagnostics-eFM9A_TU.d.ts → diagnostics-BMYtBCQk.d.ts} +2 -2
  20. package/dist/{diagnostics-CqepLcpI.d.ts → diagnostics-OcQKQYSY.d.ts} +4 -2
  21. package/dist/diagnostics.d.ts +2 -2
  22. package/dist/diagnostics.js +10 -5
  23. package/dist/{elements-ChJULZlh.d.ts → elements-BzjjnoCS.d.ts} +3 -3
  24. package/dist/email/components.d.ts +1 -1
  25. package/dist/email/components.js +40 -10
  26. package/dist/email/diagnostics.d.ts +1 -1
  27. package/dist/email/elements.d.ts +1 -1
  28. package/dist/email/html.d.ts +2 -2
  29. package/dist/email/html.js +2 -1
  30. package/dist/email/jsx-dev-runtime.d.ts +2 -2
  31. package/dist/email/jsx-runtime.d.ts +1 -1
  32. package/dist/email/render.d.ts +4 -4
  33. package/dist/email/render.js +1 -1
  34. package/dist/email/selection.d.ts +1 -1
  35. package/dist/email/source-edit.d.ts +1 -1
  36. package/dist/email/stylesheets.d.ts +1 -1
  37. package/dist/email/text.d.ts +1 -1
  38. package/dist/emit.d.ts +2 -2
  39. package/dist/footer.js +7 -4
  40. package/dist/jsx-dev-runtime.d.ts +2 -2
  41. package/dist/{jsx-runtime-BI4gI19E.d.ts → jsx-runtime-I-1nCtl2.d.ts} +3 -3
  42. package/dist/jsx-runtime.d.ts +1 -1
  43. package/dist/lexer.js +17 -5
  44. package/dist/model.d.ts +1 -1
  45. package/dist/ops-2aiiYO7m.js +630 -0
  46. package/dist/ops.d.ts +2 -2
  47. package/dist/ops.js +1 -479
  48. package/dist/{parser-b_Kp5MT6.d.ts → parser-CQcASEyy.d.ts} +3 -3
  49. package/dist/parser.d.ts +1 -1
  50. package/dist/parser.js +1 -1
  51. package/dist/{predicate-DwXzmqIY.js → predicate-BI6uRRM-.js} +14 -4
  52. package/dist/{predicate-Bmvgw7Ao.d.ts → predicate-M-05Nd7R.d.ts} +2 -2
  53. package/dist/predicate.d.ts +1 -1
  54. package/dist/predicate.js +1 -1
  55. package/dist/presets/category-mapping.d.ts +1 -1
  56. package/dist/presets/corpus.d.ts +1 -1
  57. package/dist/presets/public-gallery.d.ts +2 -2
  58. package/dist/presets/public-gallery.js +10 -2
  59. package/dist/presets/public-handoff.d.ts +2 -2
  60. package/dist/presets/public-preview-artifacts.d.ts +3 -1
  61. package/dist/presets/public-preview-artifacts.js +1 -0
  62. package/dist/presets/showcase.d.ts +1 -1
  63. package/dist/presets.d.ts +1 -1
  64. package/dist/printer.d.ts +1 -1
  65. package/dist/{render-T6IFPnP4.js → render-aaJBnsXK.js} +33 -16
  66. package/dist/render-template.d.ts +5 -5
  67. package/dist/render-template.js +1 -1
  68. package/dist/{showcase-dvJMn-Lo.d.ts → showcase-DGZAWn4Z.d.ts} +2 -2
  69. package/dist/{source-locations-D6Te6Gy1.d.ts → source-locations-DrCM82Ym.d.ts} +2 -2
  70. package/dist/source-locations.d.ts +1 -1
  71. package/dist/{template-G-QPcfmn.d.ts → template-DWftqh4x.d.ts} +2 -2
  72. package/dist/template.d.ts +1 -1
  73. package/dist/theme-css.d.ts +1 -1
  74. package/dist/theme.js +25 -2
  75. package/dist/tsx-tracer.d.ts +1 -1
  76. package/dist/tsx-tracer.js +1 -1
  77. package/dist/{variables-BnKs1iqb.d.ts → variables-J_L3qxRa.d.ts} +2 -2
  78. package/dist/variables.d.ts +1 -1
  79. package/dist/variables.js +1 -1
  80. package/package.json +1 -1
@@ -6,22 +6,33 @@ import { EmailCompileError, hasBlockingDiagnostic } from "./email/diagnostics.js
6
6
  import { snapshotStylesheets } from "./email/stylesheets.js";
7
7
  import { deriveEmailText } from "./email/text.js";
8
8
  //#region src/email/css-values.ts
9
- /** Expand `var(--x, fallback)` against the collected custom properties. */
10
- const resolveVariables = (value, variables, depth = 0) => {
9
+ const MAX_RESOLVED_VALUE_LENGTH = 65536;
10
+ const MAX_RESOLUTION_WORK = 262144;
11
+ const resolveVariablesWithin = (value, variables, depth, budget, work) => {
12
+ if (value.length > work.remaining) return void 0;
13
+ work.remaining -= value.length;
14
+ if (value.length > budget) return void 0;
11
15
  if (depth > 8 || !value.includes("var(")) return value;
12
- let result = "";
13
- let rest = value;
14
- while (rest.length > 0) {
15
- const start = rest.indexOf("var(");
16
+ const chunks = [];
17
+ let length = 0;
18
+ const append = (chunk) => {
19
+ length += chunk.length;
20
+ if (length > budget) return false;
21
+ chunks.push(chunk);
22
+ return true;
23
+ };
24
+ let cursor = 0;
25
+ while (cursor < value.length) {
26
+ const start = value.indexOf("var(", cursor);
16
27
  if (start < 0) {
17
- result += rest;
28
+ if (!append(value.slice(cursor))) return void 0;
18
29
  break;
19
30
  }
20
- result += rest.slice(0, start);
31
+ if (!append(value.slice(cursor, start))) return void 0;
21
32
  let level = 0;
22
33
  let end = -1;
23
- for (let index = start + 3; index < rest.length; index++) if (rest[index] === "(") level += 1;
24
- else if (rest[index] === ")") {
34
+ for (let index = start + 3; index < value.length; index++) if (value[index] === "(") level += 1;
35
+ else if (value[index] === ")") {
25
36
  level -= 1;
26
37
  if (level === 0) {
27
38
  end = index;
@@ -29,20 +40,26 @@ const resolveVariables = (value, variables, depth = 0) => {
29
40
  }
30
41
  }
31
42
  if (end < 0) {
32
- result += rest.slice(start);
43
+ if (!append(value.slice(start))) return void 0;
33
44
  break;
34
45
  }
35
- const body = rest.slice(start + 4, end);
46
+ const body = value.slice(start + 4, end);
36
47
  const comma = body.indexOf(",");
37
48
  const name = (comma < 0 ? body : body.slice(0, comma)).trim();
38
49
  const fallback = comma < 0 ? void 0 : body.slice(comma + 1).trim();
39
50
  const replacement = variables[name] ?? fallback;
40
- result += replacement === void 0 ? rest.slice(start, end + 1) : resolveVariables(replacement, variables, depth + 1);
41
- rest = rest.slice(end + 1);
51
+ const resolved = replacement === void 0 ? value.slice(start, end + 1) : resolveVariablesWithin(replacement, variables, depth + 1, budget - length, work);
52
+ if (resolved === void 0 || !append(resolved)) return void 0;
53
+ cursor = end + 1;
42
54
  }
43
- return result;
55
+ return chunks.join("");
44
56
  };
45
57
  /**
58
+ * Expand `var(--x, fallback)` against the collected custom properties.
59
+ * Values whose expansion exceeds the render-time budget are left as authored.
60
+ */
61
+ const resolveVariables = (value, variables, depth = 0) => resolveVariablesWithin(value, variables, depth, MAX_RESOLVED_VALUE_LENGTH, { remaining: MAX_RESOLUTION_WORK }) ?? value;
62
+ /**
46
63
  * Fold a constant `calc()` to a plain value. Tailwind writes every spacing
47
64
  * utility as `calc(var(--spacing) * n)`, and classic Outlook does not implement
48
65
  * `calc()` at all, so an unfolded value is a silently missing style. An
@@ -589,4 +606,4 @@ const renderEmailWith = (stylesheet, template, data, options) => {
589
606
  //#endregion
590
607
  export { applyStylesheet as a, downlevelMediaQuery as c, renderHeadCss as d, resolveVariables as f, renderEmail as i, finalizeValue as l, bindStylesheets as n, classListOf as o, compileEmail as r, matchesSelector as s, EMAIL_DOCTYPE as t, foldCalc as u };
591
608
 
592
- //# sourceMappingURL=render-T6IFPnP4.js.map
609
+ //# sourceMappingURL=render-aaJBnsXK.js.map
@@ -1,8 +1,8 @@
1
- import { i as SmlParseError } from "./diagnostics-CqepLcpI.js";
2
- import { b as SmlDocument } from "./ast-BLybiDxp.js";
3
- import { s as UnboundTemplateSourceLocations } from "./source-locations-D6Te6Gy1.js";
4
- import { a as VariableKind, l as Variables } from "./variables-BnKs1iqb.js";
5
- import { a as JsxResult } from "./jsx-runtime-BI4gI19E.js";
1
+ import { i as SmlParseError } from "./diagnostics-OcQKQYSY.js";
2
+ import { b as SmlDocument } from "./ast-BrDtApwS.js";
3
+ import { s as UnboundTemplateSourceLocations } from "./source-locations-DrCM82Ym.js";
4
+ import { a as VariableKind, l as Variables } from "./variables-J_L3qxRa.js";
5
+ import { a as JsxResult } from "./jsx-runtime-I-1nCtl2.js";
6
6
  import { Result } from "better-result";
7
7
  //#region src/render-template.d.ts
8
8
  /**
@@ -1,5 +1,5 @@
1
1
  import { mapJsxSourceLocations } from "./source-locations.js";
2
- import { i as parsePredicate, n as collectPredicateVariables } from "./predicate-DwXzmqIY.js";
2
+ import { i as parsePredicate, n as collectPredicateVariables } from "./predicate-BI6uRRM-.js";
3
3
  import { isRootTag } from "./ast.js";
4
4
  import { createVariablesProxy } from "./variables.js";
5
5
  import { parseSml } from "./parser.js";
@@ -1,4 +1,4 @@
1
- import { r as PresetCategory } from "./catalog-Db0UcCTg.js";
1
+ import { r as PresetCategory } from "./catalog-60eaYC7b.js";
2
2
  //#region presets/showcase.d.ts
3
3
  /**
4
4
  * The showcase projects: presets authored as complete editable projects under
@@ -453,4 +453,4 @@ declare const showcaseSourcePath: (project: ShowcaseProject) => string;
453
453
  declare const showcaseProjectPaths: (project: ShowcaseProject) => ReadonlyArray<string>;
454
454
  //#endregion
455
455
  export { ShowcaseProjectId as a, showcaseProject as c, showcaseSourcePath as d, ShowcaseProject as i, showcaseProjectPaths as l, OwnedShowcaseId as n, ShowcaseProvenance as o, SHOWCASE_ROOT as r, isShowcaseProjectId as s, BrandRecreationShowcaseId as t, showcaseProjects as u };
456
- //# sourceMappingURL=showcase-dvJMn-Lo.d.ts.map
456
+ //# sourceMappingURL=showcase-DGZAWn4Z.d.ts.map
@@ -1,4 +1,4 @@
1
- import { f as ElementNode, x as SmlNode } from "./ast-BLybiDxp.js";
1
+ import { f as ElementNode, x as SmlNode } from "./ast-BrDtApwS.js";
2
2
  //#region src/source-locations.d.ts
3
3
  /**
4
4
  * The source payload emitted by the JSX development transform. The transform
@@ -64,4 +64,4 @@ declare const mapJsxSourceLocations: (draft: ElementNode, parsed: ElementNode) =
64
64
  declare const sameTemplateSourceLocations: (left: UnboundTemplateSourceLocations, right: UnboundTemplateSourceLocations) => boolean;
65
65
  //#endregion
66
66
  export { SourceLocationUnavailableReason as a, attachJsxSourceLocation as c, mapJsxSourceLocations as d, sameTemplateSourceLocations as f, JsxSourceLocation as i, completeJsxSourceLocation as l, JSX_SOURCE_LOCATION_PROP as n, TemplateSourceLocations as o, JsxSource as r, UnboundTemplateSourceLocations as s, JSX_SOURCE_LOCATION as t, jsxSourceLocationOf as u };
67
- //# sourceMappingURL=source-locations-D6Te6Gy1.d.ts.map
67
+ //# sourceMappingURL=source-locations-DrCM82Ym.d.ts.map
@@ -1,2 +1,2 @@
1
- import { a as SourceLocationUnavailableReason, c as attachJsxSourceLocation, d as mapJsxSourceLocations, f as sameTemplateSourceLocations, i as JsxSourceLocation, l as completeJsxSourceLocation, n as JSX_SOURCE_LOCATION_PROP, o as TemplateSourceLocations, r as JsxSource, s as UnboundTemplateSourceLocations, t as JSX_SOURCE_LOCATION, u as jsxSourceLocationOf } from "./source-locations-D6Te6Gy1.js";
1
+ import { a as SourceLocationUnavailableReason, c as attachJsxSourceLocation, d as mapJsxSourceLocations, f as sameTemplateSourceLocations, i as JsxSourceLocation, l as completeJsxSourceLocation, n as JSX_SOURCE_LOCATION_PROP, o as TemplateSourceLocations, r as JsxSource, s as UnboundTemplateSourceLocations, t as JSX_SOURCE_LOCATION, u as jsxSourceLocationOf } from "./source-locations-DrCM82Ym.js";
2
2
  export { JSX_SOURCE_LOCATION, JSX_SOURCE_LOCATION_PROP, JsxSource, JsxSourceLocation, SourceLocationUnavailableReason, TemplateSourceLocations, UnboundTemplateSourceLocations, attachJsxSourceLocation, completeJsxSourceLocation, jsxSourceLocationOf, mapJsxSourceLocations, sameTemplateSourceLocations };
@@ -1,4 +1,4 @@
1
- import { m as EmailNode } from "./elements-ChJULZlh.js";
1
+ import { m as EmailNode } from "./elements-BzjjnoCS.js";
2
2
  import { r as InputSchema } from "./input-schema-7dPFVvNE.js";
3
3
  import { StandardJSONSchemaV1 } from "@standard-schema/spec";
4
4
  //#region src/template.d.ts
@@ -57,4 +57,4 @@ type TemplateInput<T extends {
57
57
  }> = Parameters<T["render"]>[0];
58
58
  //#endregion
59
59
  export { TemplateRuntime as a, TemplateInput as i, TEMPLATE_NAME_PATTERN as n, defineEmail as o, TemplateDefinition as r, isTemplateDefinition as s, EmailContent as t };
60
- //# sourceMappingURL=template-G-QPcfmn.d.ts.map
60
+ //# sourceMappingURL=template-DWftqh4x.d.ts.map
@@ -1,2 +1,2 @@
1
- import { a as TemplateRuntime, i as TemplateInput, n as TEMPLATE_NAME_PATTERN, o as defineEmail, r as TemplateDefinition, s as isTemplateDefinition, t as EmailContent } from "./template-G-QPcfmn.js";
1
+ import { a as TemplateRuntime, i as TemplateInput, n as TEMPLATE_NAME_PATTERN, o as defineEmail, r as TemplateDefinition, s as isTemplateDefinition, t as EmailContent } from "./template-DWftqh4x.js";
2
2
  export { EmailContent, TEMPLATE_NAME_PATTERN, TemplateDefinition, TemplateInput, TemplateRuntime, defineEmail, isTemplateDefinition };
@@ -1,4 +1,4 @@
1
- import { t as Diagnostic } from "./diagnostics-CqepLcpI.js";
1
+ import { t as Diagnostic } from "./diagnostics-OcQKQYSY.js";
2
2
  import { o as TokenOverrides } from "./theme-6ApjjiBo.js";
3
3
  import { Result } from "better-result";
4
4
  //#region src/theme-css.d.ts
package/dist/theme.js CHANGED
@@ -16,7 +16,30 @@
16
16
  * quoted CSS string `\/` is identical to `/`, but the HTML tokenizer no longer
17
17
  * matches `<\/style>` as a raw-text end tag.
18
18
  */
19
- const escapeCssString = (value) => value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/<\//g, "<\\/");
19
+ const escapeCssString = (value) => value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/[\u0000-\u001f\u007f]/g, (character) => `\\${character.charCodeAt(0).toString(16)} `).replace(/<\//g, "<\\/");
20
+ const FONT_FAMILY_NAME = /^-?[a-zA-Z][a-zA-Z0-9 -]*$/;
21
+ const SINGLE_QUOTED_FONT_FAMILY = /^'[^'\\<\u0000-\u001f\u007f]*'$/;
22
+ const DOUBLE_QUOTED_FONT_FAMILY = /^"[^"\\<\u0000-\u001f\u007f]*"$/;
23
+ const splitFontStack = (value) => {
24
+ const families = [];
25
+ let start = 0;
26
+ let quote;
27
+ for (let index = 0; index < value.length; index++) {
28
+ const character = value[index];
29
+ if (quote !== void 0) {
30
+ if (character === quote) quote = void 0;
31
+ } else if (character === "'" || character === "\"") quote = character;
32
+ else if (character === ",") {
33
+ families.push(value.slice(start, index).trim());
34
+ start = index + 1;
35
+ }
36
+ }
37
+ families.push(value.slice(start).trim());
38
+ return families;
39
+ };
40
+ const safeFontStack = (value) => {
41
+ return splitFontStack(value).every((family) => FONT_FAMILY_NAME.test(family) || SINGLE_QUOTED_FONT_FAMILY.test(family) || DOUBLE_QUOTED_FONT_FAMILY.test(family)) ? value : `'${escapeCssString(value)}'`;
42
+ };
20
43
  /**
21
44
  * Flatten persisted font tokens into the compiler's two font fields, so the
22
45
  * server (apps/api) and the in-browser canvas (apps/web) produce byte-identical
@@ -31,7 +54,7 @@ const flattenFontTokens = (tokens) => {
31
54
  const fontFamilies = {};
32
55
  const fontFaces = {};
33
56
  for (const [name, token] of Object.entries(tokens)) {
34
- fontFamilies[name] = `'${escapeCssString(token.family)}', ${token.fallback}`;
57
+ fontFamilies[name] = `'${escapeCssString(token.family)}', ${safeFontStack(token.fallback)}`;
35
58
  if (token.faces != null) fontFaces[name] = {
36
59
  family: token.family,
37
60
  faces: token.faces
@@ -1,4 +1,4 @@
1
- import { a as Span } from "./diagnostics-CqepLcpI.js";
1
+ import { a as Span } from "./diagnostics-OcQKQYSY.js";
2
2
  import { SmlOp } from "./ops.js";
3
3
  import { Result } from "better-result";
4
4
  //#region src/tsx-tracer.d.ts
@@ -3,7 +3,7 @@ import { buildLineMap } from "./diagnostics.js";
3
3
  import { SML_TAGS, componentNameForSmlTag, smlTagForComponentName } from "./ast.js";
4
4
  import { decodeEntities } from "./lexer.js";
5
5
  import { parseSml } from "./parser.js";
6
- import { applyOps } from "./ops.js";
6
+ import { r as applyOps } from "./ops-2aiiYO7m.js";
7
7
  import { Result, TaggedError } from "better-result";
8
8
  import { parse } from "@babel/parser";
9
9
  //#region src/tsx-tracer.ts
@@ -1,4 +1,4 @@
1
- import { r as PredicateAst } from "./predicate-Bmvgw7Ao.js";
1
+ import { r as PredicateAst } from "./predicate-M-05Nd7R.js";
2
2
  //#region src/variables.d.ts
3
3
  /** Brand carried by every VariableRef, keyed off a private symbol. */
4
4
  declare const VARIABLE_REF: unique symbol;
@@ -74,4 +74,4 @@ declare const createVariablesProxy: <T extends Record<string, unknown>>() => {
74
74
  };
75
75
  //#endregion
76
76
  export { VariableKind as a, VariableRefBrand as c, isPredicateRef as d, isVariableRef as f, VARIABLE_REF as i, Variables as l, PREDICATE_REF as n, VariableRecorder as o, printPredicateRef as p, PredicateRef as r, VariableRef as s, CollectedVariable as t, createVariablesProxy as u };
77
- //# sourceMappingURL=variables-BnKs1iqb.d.ts.map
77
+ //# sourceMappingURL=variables-J_L3qxRa.d.ts.map
@@ -1,2 +1,2 @@
1
- import { a as VariableKind, c as VariableRefBrand, d as isPredicateRef, f as isVariableRef, i as VARIABLE_REF, l as Variables, n as PREDICATE_REF, o as VariableRecorder, p as printPredicateRef, r as PredicateRef, s as VariableRef, t as CollectedVariable, u as createVariablesProxy } from "./variables-BnKs1iqb.js";
1
+ import { a as VariableKind, c as VariableRefBrand, d as isPredicateRef, f as isVariableRef, i as VARIABLE_REF, l as Variables, n as PREDICATE_REF, o as VariableRecorder, p as printPredicateRef, r as PredicateRef, s as VariableRef, t as CollectedVariable, u as createVariablesProxy } from "./variables-J_L3qxRa.js";
2
2
  export { CollectedVariable, PREDICATE_REF, PredicateRef, VARIABLE_REF, VariableKind, VariableRecorder, VariableRef, VariableRefBrand, Variables, createVariablesProxy, isPredicateRef, isVariableRef, printPredicateRef };
package/dist/variables.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as hasProperty } from "./guards-eV1qLbf2.js";
2
- import { a as printPredicate } from "./predicate-DwXzmqIY.js";
2
+ import { a as printPredicate } from "./predicate-BI6uRRM-.js";
3
3
  //#region src/variables.ts
4
4
  const PLACEHOLDER_SPAN = {
5
5
  start: 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@samva/markup",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Type-safe authoring and compilation primitives for Samva templates",
5
5
  "keywords": [
6
6
  "email",