@samva/markup 0.9.0 → 0.10.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.
- package/AGENTS.md +48 -40
- package/CHANGELOG.md +345 -0
- package/README.md +6 -6
- package/dist/{brand-B-0bN_Ir.d.ts → assets-BIsyMQ92.d.ts} +41 -11
- package/dist/{email/brand.js → brand-C0MKTwmX.js} +64 -4
- package/dist/{theme-css.d.ts → brand.d.ts} +12 -3
- package/dist/brand.js +4 -0
- package/dist/compiler.d.ts +231 -11
- package/dist/compiler.js +1312 -13
- package/dist/components-BZCqegS8.js +1864 -0
- package/dist/diagnostic-model-DJtqbETd.js +38 -0
- package/dist/diagnostic-model-DxthUZBT.d.ts +31 -0
- package/dist/{email/diagnostics.js → diagnostics-CnKFefKz.js} +2 -2
- package/dist/diagnostics.d.ts +406 -27
- package/dist/diagnostics.js +402 -34
- package/dist/edit.d.ts +234 -0
- package/dist/{channel-edit.js → edit.js} +341 -3
- package/dist/email/jsx-dev-runtime.d.ts +1 -1
- package/dist/email/jsx-dev-runtime.js +1 -2
- package/dist/email/jsx-runtime.d.ts +1 -1
- package/dist/email/jsx-runtime.js +1 -85
- package/dist/{email/components.d.ts → email.d.ts} +2 -2
- package/dist/email.js +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{cascade-t6kxlgEI.js → ir-CLhlklKV.js} +8 -4
- package/dist/jsx-runtime-CBlexoeR.js +98 -0
- package/dist/{elements-cqldpaJt.d.ts → jsx-runtime-ylIOnaSf.d.ts} +74 -74
- package/dist/{profile-BH-OtdDA.js → profile-pWGtWZXF.js} +153 -20
- package/dist/render-BPonDpCl.d.ts +539 -0
- package/dist/{email/render.js → render-BQmfh94k.js} +102 -8
- package/dist/render.d.ts +35 -0
- package/dist/render.js +49 -0
- package/dist/sms.d.ts +1 -1
- package/dist/sms.js +1 -1
- package/dist/{template-_QE_rQND.d.ts → template-DMPwxMSq.d.ts} +2 -2
- package/dist/{template.js → template-zLUjcwfF.js} +2 -2
- package/dist/{theme-css-hFqcPSar.js → theme-css-JtRCm1fb.js} +2 -2
- package/dist/whatsapp.d.ts +1 -1
- package/dist/whatsapp.js +1 -1
- package/generated/contract.json +16 -10
- package/generated/reference.md +17 -10
- package/package.json +36 -119
- package/samva-brand.d.ts +4 -4
- package/skills/sml/SKILL.md +2 -2
- package/dist/assets-C5duwTya.d.ts +0 -40
- package/dist/channel-edit.d.ts +0 -121
- package/dist/channel-specs-B6M_HlaV.js +0 -29
- package/dist/compatibility-DbISoFIq.js +0 -589
- package/dist/css-BVQKICKC.d.ts +0 -109
- package/dist/diagnostic-codes.d.ts +0 -403
- package/dist/diagnostic-codes.js +0 -399
- package/dist/email/assets.d.ts +0 -2
- package/dist/email/assets.js +0 -63
- package/dist/email/brand-footer.d.ts +0 -34
- package/dist/email/brand-footer.js +0 -63
- package/dist/email/brand.d.ts +0 -2
- package/dist/email/components.js +0 -275
- package/dist/email/diagnostics.d.ts +0 -2
- package/dist/email/elements.d.ts +0 -2
- package/dist/email/elements.js +0 -299
- package/dist/email/html.d.ts +0 -2
- package/dist/email/html.js +0 -321
- package/dist/email/render.d.ts +0 -40
- package/dist/email/text.d.ts +0 -7
- package/dist/email/text.js +0 -100
- package/dist/html-BJepOwZ4.d.ts +0 -56
- package/dist/ir-aaqNE987.d.ts +0 -252
- package/dist/ir.d.ts +0 -2
- package/dist/ir.js +0 -7
- package/dist/preview-Ekdg1dXG.d.ts +0 -100
- package/dist/preview.d.ts +0 -2
- package/dist/preview.js +0 -160
- package/dist/render-ir.d.ts +0 -19
- package/dist/render-ir.js +0 -826
- package/dist/sms-segments.d.ts +0 -13
- package/dist/sms-segments.js +0 -46
- package/dist/source-edit.d.ts +0 -116
- package/dist/source-edit.js +0 -343
- package/dist/source-locations.d.ts +0 -2
- package/dist/source-locations.js +0 -16
- package/dist/static.d.ts +0 -57
- package/dist/static.js +0 -69
- package/dist/tailwind-CMYpZf1v.js +0 -614
- package/dist/template.d.ts +0 -2
- package/dist/theme-css.js +0 -2
- package/dist/theme-imports-lvBw3AD1.js +0 -109
- package/dist/transform-Ct2OMkFN.d.ts +0 -153
|
@@ -1,77 +1,5 @@
|
|
|
1
1
|
import { r as JsxSourceLocation } from "./source-locations-C8wCsiAy.js";
|
|
2
2
|
import { r as EmailDiagnostic } from "./diagnostics-B-Gym34R.js";
|
|
3
|
-
//#region src/email/jsx-runtime.d.ts
|
|
4
|
-
/** Derived authoring tree; source stays canonical. Origins run from inner element to component call sites. */
|
|
5
|
-
type EmailNode = {
|
|
6
|
-
readonly type: "Text";
|
|
7
|
-
readonly value: string;
|
|
8
|
-
} | {
|
|
9
|
-
readonly type: "Element";
|
|
10
|
-
readonly tag: string;
|
|
11
|
-
readonly props: Readonly<Record<string, unknown>>;
|
|
12
|
-
readonly children: readonly EmailNode[];
|
|
13
|
-
readonly origins: readonly JsxSourceLocation[];
|
|
14
|
-
/**
|
|
15
|
-
* True when this element is written at `origins[0]`; false when a compiler
|
|
16
|
-
* primitive generated it and `origins[0]` is the call site that asked for
|
|
17
|
-
* it. Both point at the same authoring target, but only an authored element
|
|
18
|
-
* can have its own props edited there.
|
|
19
|
-
*/
|
|
20
|
-
readonly authored: boolean;
|
|
21
|
-
} | {
|
|
22
|
-
readonly type: "Fragment";
|
|
23
|
-
readonly children: readonly EmailNode[];
|
|
24
|
-
} |
|
|
25
|
-
/**
|
|
26
|
-
* Compatibility markup a compiler primitive emits verbatim — conditional
|
|
27
|
-
* comments and VML. Only the primitives in `./components` construct it;
|
|
28
|
-
* nothing an author passes as a string reaches this node.
|
|
29
|
-
*/
|
|
30
|
-
{
|
|
31
|
-
readonly type: "Raw";
|
|
32
|
-
readonly html: string;
|
|
33
|
-
readonly text: string;
|
|
34
|
-
readonly origins: readonly JsxSourceLocation[];
|
|
35
|
-
};
|
|
36
|
-
type EmailNodeOf<Type extends EmailNode["type"]> = Extract<EmailNode, {
|
|
37
|
-
readonly type: Type;
|
|
38
|
-
}>;
|
|
39
|
-
type EmailNodeFields<Type extends EmailNode["type"]> = Omit<EmailNodeOf<Type>, "type">;
|
|
40
|
-
/** Constructors for the authoring tree. The tree is data; nothing here validates it. */
|
|
41
|
-
declare const EmailNode: {
|
|
42
|
-
readonly Text: (fields: EmailNodeFields<"Text">) => EmailNodeOf<"Text">;
|
|
43
|
-
readonly Element: (fields: EmailNodeFields<"Element">) => EmailNodeOf<"Element">;
|
|
44
|
-
readonly Fragment: (fields: EmailNodeFields<"Fragment">) => EmailNodeOf<"Fragment">;
|
|
45
|
-
readonly Raw: (fields: EmailNodeFields<"Raw">) => EmailNodeOf<"Raw">;
|
|
46
|
-
};
|
|
47
|
-
type EmailChild = EmailNode | string | number | boolean | null | undefined | readonly EmailChild[];
|
|
48
|
-
type EmailComponent<P = never> = (props: P) => EmailChild;
|
|
49
|
-
declare const Fragment: unique symbol;
|
|
50
|
-
/** Call sites enclosing the element being built, innermost first. */
|
|
51
|
-
declare const currentEmailOrigins: () => readonly JsxSourceLocation[];
|
|
52
|
-
/** Record a finding from inside a compiler primitive, located at the authoring call site. */
|
|
53
|
-
declare const reportEmailDiagnostic: (diagnostic: Omit<EmailDiagnostic, "origins">) => void;
|
|
54
|
-
/** Take and clear the findings primitives reported during a render. */
|
|
55
|
-
declare const drainEmailDiagnostics: () => readonly EmailDiagnostic[];
|
|
56
|
-
/** Normalize actual values without interpolation or recording proxies. */
|
|
57
|
-
declare const normalizeChildren: (input: unknown) => EmailNode[];
|
|
58
|
-
/** Compatibility markup emitted by a compiler primitive, with the text it stands for. */
|
|
59
|
-
declare const rawMarkup: (html: string, text?: string) => EmailNode;
|
|
60
|
-
/** Automatic JSX factory for ordinary HTML and synchronous imported components. */
|
|
61
|
-
declare const jsx: (type: string | EmailComponent<Record<string, unknown>> | typeof Fragment, props: Record<string, unknown> | null) => EmailNode;
|
|
62
|
-
declare const jsxs: typeof jsx;
|
|
63
|
-
declare namespace JSX {
|
|
64
|
-
type Element = EmailNode;
|
|
65
|
-
type ElementType = string | EmailComponent | typeof Fragment;
|
|
66
|
-
interface ElementChildrenAttribute {
|
|
67
|
-
readonly children: object;
|
|
68
|
-
}
|
|
69
|
-
interface IntrinsicAttributes {
|
|
70
|
-
readonly key?: string | number | undefined;
|
|
71
|
-
}
|
|
72
|
-
interface IntrinsicElements extends EmailIntrinsicElements {}
|
|
73
|
-
}
|
|
74
|
-
//#endregion
|
|
75
3
|
//#region src/email/elements.d.ts
|
|
76
4
|
/** How one attribute is spelled and what values it accepts. */
|
|
77
5
|
interface EmailAttributeSpec {
|
|
@@ -695,5 +623,77 @@ type ChildrenProp<Content extends EmailElementSpec["content"]> = Content extends
|
|
|
695
623
|
/** Props each supported tag accepts, derived from `EMAIL_ELEMENTS`. */
|
|
696
624
|
type EmailIntrinsicElements = { readonly [Tag in EmailTag]: EmailGlobalProps & AttributeProps<typeof EMAIL_GLOBAL_ATTRIBUTES> & AttributeProps<(typeof EMAIL_ELEMENTS)[Tag]["attributes"]> & ChildrenProp<(typeof EMAIL_ELEMENTS)[Tag]["content"]>; };
|
|
697
625
|
//#endregion
|
|
698
|
-
|
|
699
|
-
|
|
626
|
+
//#region src/email/jsx-runtime.d.ts
|
|
627
|
+
/** Derived authoring tree; source stays canonical. Origins run from inner element to component call sites. */
|
|
628
|
+
type EmailNode = {
|
|
629
|
+
readonly type: "Text";
|
|
630
|
+
readonly value: string;
|
|
631
|
+
} | {
|
|
632
|
+
readonly type: "Element";
|
|
633
|
+
readonly tag: string;
|
|
634
|
+
readonly props: Readonly<Record<string, unknown>>;
|
|
635
|
+
readonly children: readonly EmailNode[];
|
|
636
|
+
readonly origins: readonly JsxSourceLocation[];
|
|
637
|
+
/**
|
|
638
|
+
* True when this element is written at `origins[0]`; false when a compiler
|
|
639
|
+
* primitive generated it and `origins[0]` is the call site that asked for
|
|
640
|
+
* it. Both point at the same authoring target, but only an authored element
|
|
641
|
+
* can have its own props edited there.
|
|
642
|
+
*/
|
|
643
|
+
readonly authored: boolean;
|
|
644
|
+
} | {
|
|
645
|
+
readonly type: "Fragment";
|
|
646
|
+
readonly children: readonly EmailNode[];
|
|
647
|
+
} |
|
|
648
|
+
/**
|
|
649
|
+
* Compatibility markup a compiler primitive emits verbatim — conditional
|
|
650
|
+
* comments and VML. Only the primitives in `./components` construct it;
|
|
651
|
+
* nothing an author passes as a string reaches this node.
|
|
652
|
+
*/
|
|
653
|
+
{
|
|
654
|
+
readonly type: "Raw";
|
|
655
|
+
readonly html: string;
|
|
656
|
+
readonly text: string;
|
|
657
|
+
readonly origins: readonly JsxSourceLocation[];
|
|
658
|
+
};
|
|
659
|
+
type EmailNodeOf<Type extends EmailNode["type"]> = Extract<EmailNode, {
|
|
660
|
+
readonly type: Type;
|
|
661
|
+
}>;
|
|
662
|
+
type EmailNodeFields<Type extends EmailNode["type"]> = Omit<EmailNodeOf<Type>, "type">;
|
|
663
|
+
/** Constructors for the authoring tree. The tree is data; nothing here validates it. */
|
|
664
|
+
declare const EmailNode: {
|
|
665
|
+
readonly Text: (fields: EmailNodeFields<"Text">) => EmailNodeOf<"Text">;
|
|
666
|
+
readonly Element: (fields: EmailNodeFields<"Element">) => EmailNodeOf<"Element">;
|
|
667
|
+
readonly Fragment: (fields: EmailNodeFields<"Fragment">) => EmailNodeOf<"Fragment">;
|
|
668
|
+
readonly Raw: (fields: EmailNodeFields<"Raw">) => EmailNodeOf<"Raw">;
|
|
669
|
+
};
|
|
670
|
+
type EmailChild = EmailNode | string | number | boolean | null | undefined | readonly EmailChild[];
|
|
671
|
+
type EmailComponent<P = never> = (props: P) => EmailChild;
|
|
672
|
+
declare const Fragment: unique symbol;
|
|
673
|
+
/** Call sites enclosing the element being built, innermost first. */
|
|
674
|
+
declare const currentEmailOrigins: () => readonly JsxSourceLocation[];
|
|
675
|
+
/** Record a finding from inside a compiler primitive, located at the authoring call site. */
|
|
676
|
+
declare const reportEmailDiagnostic: (diagnostic: Omit<EmailDiagnostic, "origins">) => void;
|
|
677
|
+
/** Take and clear the findings primitives reported during a render. */
|
|
678
|
+
declare const drainEmailDiagnostics: () => readonly EmailDiagnostic[];
|
|
679
|
+
/** Normalize actual values without interpolation or recording proxies. */
|
|
680
|
+
declare const normalizeChildren: (input: unknown) => EmailNode[];
|
|
681
|
+
/** Compatibility markup emitted by a compiler primitive, with the text it stands for. */
|
|
682
|
+
declare const rawMarkup: (html: string, text?: string) => EmailNode;
|
|
683
|
+
/** Automatic JSX factory for ordinary HTML and synchronous imported components. */
|
|
684
|
+
declare const jsx: (type: string | EmailComponent<Record<string, unknown>> | typeof Fragment, props: Record<string, unknown> | null) => EmailNode;
|
|
685
|
+
declare const jsxs: typeof jsx;
|
|
686
|
+
declare namespace JSX {
|
|
687
|
+
type Element = EmailNode;
|
|
688
|
+
type ElementType = string | EmailComponent | typeof Fragment;
|
|
689
|
+
interface ElementChildrenAttribute {
|
|
690
|
+
readonly children: object;
|
|
691
|
+
}
|
|
692
|
+
interface IntrinsicAttributes {
|
|
693
|
+
readonly key?: string | number | undefined;
|
|
694
|
+
}
|
|
695
|
+
interface IntrinsicElements extends EmailIntrinsicElements {}
|
|
696
|
+
}
|
|
697
|
+
//#endregion
|
|
698
|
+
export { isUrlAttribute as C, emailElement as S, EmailGlobalProps as _, JSX as a, EmailStyle as b, jsx as c, rawMarkup as d, reportEmailDiagnostic as f, EmailElementSpec as g, EmailAttributeSpec as h, Fragment as i, jsxs as l, EMAIL_GLOBAL_ATTRIBUTES as m, EmailComponent as n, currentEmailOrigins as o, EMAIL_ELEMENTS as p, EmailNode as r, drainEmailDiagnostics as s, EmailChild as t, normalizeChildren as u, EmailIntrinsicElements as v, EmailTag as x, EmailLayout as y };
|
|
699
|
+
//# sourceMappingURL=jsx-runtime-ylIOnaSf.d.ts.map
|
|
@@ -1,20 +1,119 @@
|
|
|
1
1
|
import { n as isObject } from "./guards-eV1qLbf2.js";
|
|
2
2
|
import { n as inputSchema, r as jsonSchema } from "./input-schema-zjkgrXn2.js";
|
|
3
|
-
import {
|
|
4
|
-
import { FORMATTER_NAMES } from "./fmt.js";
|
|
5
|
-
import { isAssetPath } from "./email/assets.js";
|
|
6
|
-
import { buildLineMap, lineColumn } from "./diagnostics.js";
|
|
3
|
+
import { n as TEMPLATE_NAME_PATTERN, t as TEMPLATE_ID_PATTERN } from "./template-zLUjcwfF.js";
|
|
7
4
|
import { n as RESERVED_FOOTER_ATTRIBUTES, t as BRAND_FOOTER_MARKER } from "./unsubscribe-link-CoesnQDU.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { t as
|
|
11
|
-
import {
|
|
12
|
-
import "./
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
5
|
+
import { M as EMAIL_ELEMENTS, P as emailElement, a as Email, d as equalColumnWidth, i as Divider, l as Section, n as Column, o as Image, p as checkAttribute, r as Columns, s as Link, t as Button, u as Spacer, y as serializeStyle } from "./components-BZCqegS8.js";
|
|
6
|
+
import { FORMATTER_NAMES } from "./fmt.js";
|
|
7
|
+
import { i as drainEmailDiagnostics, t as EmailNode } from "./jsx-runtime-CBlexoeR.js";
|
|
8
|
+
import { n as applyStylesheet } from "./ir-CLhlklKV.js";
|
|
9
|
+
import { i as lineColumn, t as buildLineMap } from "./diagnostic-model-DJtqbETd.js";
|
|
10
|
+
import { d as isAssetPath, i as brandComponents } from "./brand-C0MKTwmX.js";
|
|
11
|
+
import { parse } from "css-tree";
|
|
12
|
+
import { parse as parse$1 } from "@babel/parser";
|
|
13
|
+
//#region src/email/theme-imports.ts
|
|
14
|
+
/** The CSS and TSX specifier a template uses to reach its organization's brand. */
|
|
15
|
+
const BRAND_SPECIFIER = "samva:brand";
|
|
16
|
+
const BRAND_IMPORT = /^samva:brand(?:\/([a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?))?$/;
|
|
17
|
+
/** The brand a `samva:brand` specifier names: `undefined` slug means the default brand. */
|
|
18
|
+
const parseBrandSpecifier = (specifier) => {
|
|
19
|
+
const match = BRAND_IMPORT.exec(specifier);
|
|
20
|
+
return match === null ? void 0 : { slug: match[1] };
|
|
21
|
+
};
|
|
22
|
+
/** The directory part of a project path, with no trailing slash (`""` at the root). */
|
|
23
|
+
const projectDirectory = (path) => path.includes("/") ? path.slice(0, path.lastIndexOf("/")) : "";
|
|
24
|
+
/** A relative or root-absolute stylesheet reference, resolved from a project directory. */
|
|
25
|
+
const resolveFromDirectory = (directory, reference) => {
|
|
26
|
+
const segments = reference.startsWith("/") || directory === "" ? [] : directory.split("/");
|
|
27
|
+
for (const segment of reference.split("/")) {
|
|
28
|
+
if (segment === "" || segment === ".") continue;
|
|
29
|
+
if (segment === "..") {
|
|
30
|
+
if (segments.length === 0) return void 0;
|
|
31
|
+
segments.pop();
|
|
32
|
+
} else segments.push(segment);
|
|
33
|
+
}
|
|
34
|
+
return segments.length === 0 ? void 0 : segments.join("/");
|
|
35
|
+
};
|
|
36
|
+
const importTarget = (node) => {
|
|
37
|
+
if (node.type !== "Atrule" || node.prelude === null || node.prelude.type !== "AtrulePrelude") return { extra: true };
|
|
38
|
+
const parts = [...node.prelude.children].filter((part) => part.type !== "WhiteSpace");
|
|
39
|
+
const first = parts[0];
|
|
40
|
+
const target = first?.type === "String" ? first.value : first?.type === "Url" ? first.value : void 0;
|
|
41
|
+
return target === void 0 ? { extra: true } : {
|
|
42
|
+
target,
|
|
43
|
+
extra: parts.length > 1
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Walk the theme's `@import` graph. Project `.css` files resolve from the
|
|
48
|
+
* importing file's directory; `samva:brand` and `samva:brand/<slug>` are
|
|
49
|
+
* recorded for the brand the build supplies. Anything else is an error.
|
|
50
|
+
*/
|
|
51
|
+
const resolveThemeImports = (themePath, themeCss, files) => {
|
|
52
|
+
const stylesheets = /* @__PURE__ */ new Map([[themePath, themeCss]]);
|
|
53
|
+
const brandSpecifiers = /* @__PURE__ */ new Set();
|
|
54
|
+
const diagnostics = [];
|
|
55
|
+
const visit = (path, source, chain) => {
|
|
56
|
+
const lineMap = buildLineMap(source);
|
|
57
|
+
const ast = parse(source, {
|
|
58
|
+
positions: true,
|
|
59
|
+
parseValue: false,
|
|
60
|
+
parseRulePrelude: false
|
|
61
|
+
});
|
|
62
|
+
if (ast.type !== "StyleSheet") return;
|
|
63
|
+
for (const node of ast.children) {
|
|
64
|
+
if (node.type !== "Atrule" || node.name.toLowerCase() !== "import") continue;
|
|
65
|
+
const position = lineColumn(lineMap, node.loc?.start.offset ?? 0);
|
|
66
|
+
const origins = [{
|
|
67
|
+
fileName: path,
|
|
68
|
+
lineNumber: position.line,
|
|
69
|
+
columnNumber: position.column
|
|
70
|
+
}];
|
|
71
|
+
const refuse = (message) => diagnostics.push({
|
|
72
|
+
code: "css-import-unresolved",
|
|
73
|
+
severity: "error",
|
|
74
|
+
message,
|
|
75
|
+
origins
|
|
76
|
+
});
|
|
77
|
+
const { target, extra } = importTarget(node);
|
|
78
|
+
if (target === void 0) {
|
|
79
|
+
refuse(`${path}: @import needs a quoted stylesheet path or "samva:brand".`);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (extra) {
|
|
83
|
+
refuse(`${path}: @import ${JSON.stringify(target)} takes no layer, supports or media conditions; the import order is the layering.`);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (parseBrandSpecifier(target) !== void 0) {
|
|
87
|
+
brandSpecifiers.add(target);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (!/^\.{0,2}\//.test(target) || !/\.css$/i.test(target.replace(/[?#].*$/, ""))) {
|
|
91
|
+
refuse(`${path}: @import ${JSON.stringify(target)} is not a project stylesheet or "samva:brand". The compiler supplies Tailwind itself; import project .css files by relative path.`);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const resolved = resolveFromDirectory(projectDirectory(path), target.replace(/[?#].*$/, ""));
|
|
95
|
+
const content = resolved === void 0 ? void 0 : files[resolved];
|
|
96
|
+
if (resolved === void 0 || typeof content !== "string") {
|
|
97
|
+
refuse(`${path}: @import ${JSON.stringify(target)} names no stylesheet in the project.`);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (chain.includes(resolved)) {
|
|
101
|
+
refuse(`${path}: @import ${JSON.stringify(target)} imports itself through ${chain.join(" → ")}.`);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (stylesheets.has(resolved)) continue;
|
|
105
|
+
stylesheets.set(resolved, content);
|
|
106
|
+
visit(resolved, content, [...chain, resolved]);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
visit(themePath, themeCss, [themePath]);
|
|
110
|
+
return {
|
|
111
|
+
stylesheets,
|
|
112
|
+
brandSpecifiers: [...brandSpecifiers].sort(),
|
|
113
|
+
diagnostics
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
//#endregion
|
|
18
117
|
//#region src/sml/diagnostics.ts
|
|
19
118
|
/** Collects the findings of one compile. Every finding carries a code, a location and a fix. */
|
|
20
119
|
var Findings = class {
|
|
@@ -125,7 +224,7 @@ const parseSource = (path, source) => {
|
|
|
125
224
|
const position = (offset) => lineColumn(lines, offset);
|
|
126
225
|
let program;
|
|
127
226
|
try {
|
|
128
|
-
program = parse(source, {
|
|
227
|
+
program = parse$1(source, {
|
|
129
228
|
plugins: ["typescript", "jsx"],
|
|
130
229
|
sourceType: "module"
|
|
131
230
|
}).program;
|
|
@@ -163,6 +262,32 @@ const isValueNode = (node) => {
|
|
|
163
262
|
return true;
|
|
164
263
|
};
|
|
165
264
|
//#endregion
|
|
265
|
+
//#region src/channel-specs.ts
|
|
266
|
+
const SMS_CATEGORIES = [
|
|
267
|
+
"transactional",
|
|
268
|
+
"promotional",
|
|
269
|
+
"service_implicit"
|
|
270
|
+
];
|
|
271
|
+
const WHATSAPP_CATEGORIES = [
|
|
272
|
+
"marketing",
|
|
273
|
+
"utility",
|
|
274
|
+
"authentication"
|
|
275
|
+
];
|
|
276
|
+
const WHATSAPP_HEADER_TYPES = [
|
|
277
|
+
"text",
|
|
278
|
+
"image",
|
|
279
|
+
"video",
|
|
280
|
+
"document"
|
|
281
|
+
];
|
|
282
|
+
/** The attributes `<Sms>` accepts. */
|
|
283
|
+
const SMS_ATTRIBUTES = ["category"];
|
|
284
|
+
/** The attributes `<WhatsApp>` accepts. */
|
|
285
|
+
const WHATSAPP_ATTRIBUTES = [
|
|
286
|
+
"name",
|
|
287
|
+
"language",
|
|
288
|
+
"category"
|
|
289
|
+
];
|
|
290
|
+
//#endregion
|
|
166
291
|
//#region src/whatsapp-template.ts
|
|
167
292
|
const isConcat = (value) => typeof value === "object" && value !== null && "concat" in value;
|
|
168
293
|
/**
|
|
@@ -976,10 +1101,10 @@ const runBuiltinComponent = (call) => {
|
|
|
976
1101
|
return [];
|
|
977
1102
|
}
|
|
978
1103
|
const exported = binding.imported;
|
|
979
|
-
const isEmail = binding.kind === "markup" && specifier === "@samva/markup/email
|
|
1104
|
+
const isEmail = binding.kind === "markup" && specifier === "@samva/markup/email";
|
|
980
1105
|
const isBrand = binding.kind === "brand";
|
|
981
1106
|
if (!(isEmail || isBrand)) {
|
|
982
|
-
lowerer.error(ctx, node, "unknown-component", `<${call.name}> is not a component the profile can read.`, "Import components from @samva/markup/email
|
|
1107
|
+
lowerer.error(ctx, node, "unknown-component", `<${call.name}> is not a component the profile can read.`, "Import components from @samva/markup/email, samva:brand, or the project.");
|
|
983
1108
|
return [];
|
|
984
1109
|
}
|
|
985
1110
|
let fn;
|
|
@@ -2187,7 +2312,7 @@ var Lowerer = class {
|
|
|
2187
2312
|
value: local.value
|
|
2188
2313
|
};
|
|
2189
2314
|
if (fn === void 0 || !/Function|Arrow/.test(fn.value.type)) {
|
|
2190
|
-
this.error(ctx, node, "unknown-component", `<${name}> is not a component the profile can read.`, "Import it from @samva/markup/email
|
|
2315
|
+
this.error(ctx, node, "unknown-component", `<${name}> is not a component the profile can read.`, "Import it from @samva/markup/email, or from a project file that exports it as a function.");
|
|
2191
2316
|
return [];
|
|
2192
2317
|
}
|
|
2193
2318
|
return this.partial(ctx, node, attributes, name, fn.module, fn.value);
|
|
@@ -3407,6 +3532,8 @@ const lowerProject = (options, project, findings, inputs) => {
|
|
|
3407
3532
|
//#region src/sml/project.ts
|
|
3408
3533
|
const MARKUP_SPECIFIER = "@samva/markup";
|
|
3409
3534
|
const MARKUP_PREFIX = "@samva/markup/";
|
|
3535
|
+
/** Entries a template could import that moved; each is reported with its replacement. */
|
|
3536
|
+
const MOVED_MARKUP_ENTRIES = { "@samva/markup/email/components": "@samva/markup/email" };
|
|
3410
3537
|
const SCRIPT_EXTENSIONS = [".tsx", ".ts"];
|
|
3411
3538
|
/** Resolve a relative specifier to a project file, or `undefined`. */
|
|
3412
3539
|
const resolveSpecifier = (from, specifier, files) => {
|
|
@@ -3486,6 +3613,12 @@ const loadProject = (files, entryPath, findings, loadOptions = {}) => {
|
|
|
3486
3613
|
const imported = child(node, "imported");
|
|
3487
3614
|
return imported === void 0 ? local(node) : text(imported, "name") ?? text(imported, "value") ?? local(node);
|
|
3488
3615
|
};
|
|
3616
|
+
const moved = MOVED_MARKUP_ENTRIES[specifier];
|
|
3617
|
+
if (moved !== void 0) {
|
|
3618
|
+
findings.add(parsed, child(statement, "source") ?? statement, "moved-import", `\`${specifier}\` moved to \`${moved}\`; the imported names are unchanged.`, `Import from "${moved}".`);
|
|
3619
|
+
failed = true;
|
|
3620
|
+
break;
|
|
3621
|
+
}
|
|
3489
3622
|
if (specifier === MARKUP_SPECIFIER || specifier.startsWith(MARKUP_PREFIX)) {
|
|
3490
3623
|
for (const item of specifiers) {
|
|
3491
3624
|
if (text(item, "importKind") === "type") continue;
|
|
@@ -3665,6 +3798,6 @@ const introducedProfileErrors = (before, after) => {
|
|
|
3665
3798
|
return added;
|
|
3666
3799
|
};
|
|
3667
3800
|
//#endregion
|
|
3668
|
-
export { lowerProject as a, completed as i, introducedProfileErrors as n,
|
|
3801
|
+
export { lowerProject as a, WHATSAPP_HEADER_TYPES as c, parseBrandSpecifier as d, projectDirectory as f, completed as i, Findings as l, resolveThemeImports as m, introducedProfileErrors as n, SMS_CATEGORIES as o, resolveFromDirectory as p, loadProject as r, WHATSAPP_CATEGORIES as s, checkStaticProfile as t, BRAND_SPECIFIER as u };
|
|
3669
3802
|
|
|
3670
|
-
//# sourceMappingURL=profile-
|
|
3803
|
+
//# sourceMappingURL=profile-pWGtWZXF.js.map
|