@samva/markup 0.18.1 → 0.19.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 +11 -4
- package/CHANGELOG.md +36 -0
- package/README.md +89 -5
- package/dist/assets-BSpgZOSR.js +61 -0
- package/dist/assets-k7_v3IOJ.d.ts +39 -0
- package/dist/{assets-CS5Xa_mr.d.ts → brand-Bxb6Sm7y.d.ts} +34 -41
- package/dist/brand.d.ts +2 -2
- package/dist/brand.js +3 -3
- package/dist/compatibility.d.ts +15 -5
- package/dist/compatibility.js +48 -5
- package/dist/compile-C1GWLQ5C.js +490 -0
- package/dist/compile-CIeuGmP-.d.ts +98 -0
- package/dist/{compiled-template-Bc4Dq9zy.d.ts → compiled-template-CPDHvFlt.d.ts} +157 -6
- package/dist/compiler.d.ts +4 -89
- package/dist/compiler.js +8 -486
- package/dist/components-DNBCz20_.js +3267 -0
- package/dist/{css-color-DLM12Osu.js → dark-scheme-BGDCCaUq.js} +12 -1
- package/dist/{diagnostic-codes-DZKb0Xcg.js → diagnostic-codes-BCwfUgnF.js} +33 -36
- package/dist/diagnostic-model-DJtqbETd.js +36 -0
- package/dist/{diagnostics-D4vSLQrO.d.ts → diagnostics-C3TSx6SU.d.ts} +22 -2
- package/dist/diagnostics.d.ts +33 -1
- package/dist/diagnostics.js +2 -1
- package/dist/edit.d.ts +15 -4
- package/dist/edit.js +67 -4
- package/dist/email/jsx-dev-runtime.d.ts +2 -2
- package/dist/email/jsx-runtime.d.ts +1 -1
- package/dist/email.d.ts +6 -2
- package/dist/email.js +6 -2
- package/dist/index.d.ts +1 -1
- package/dist/{jsx-runtime-DL8NVF1f.d.ts → jsx-runtime-HHfrVZEf.d.ts} +1 -2
- package/dist/markdown.d.ts +69 -0
- package/dist/markdown.js +95 -0
- package/dist/parse-Bex7QFqj.js +921 -0
- package/dist/{preview-rNoJBEIY.d.ts → preview-DRLWgmfg.d.ts} +3 -3
- package/dist/profile-DFk4gs7o.js +56 -0
- package/dist/{profile-JTvgCD6X.js → project-B6D64SZS.js} +497 -234
- package/dist/render.d.ts +8 -8
- package/dist/render.js +1 -2
- package/dist/{css-B_aVKrDo.js → selectors-CKGuc9MO.js} +158 -4
- package/dist/sms.d.ts +1 -1
- package/dist/{template-DmNcoH4Q.d.ts → template-4Dse7_OC.d.ts} +1 -1
- package/dist/{theme-css-P9F5S7Ic.js → theme-css-BujDuuEA.js} +1 -2
- package/dist/whatsapp.d.ts +1 -1
- package/generated/contract.json +41 -1
- package/generated/reference.md +97 -89
- package/package.json +15 -4
- package/dist/brand-CIiEqkU7.js +0 -193
- package/dist/brand-plugin-Dj9SMpfS.d.ts +0 -33
- package/dist/components-C5850-Qg.js +0 -409
- package/dist/dark-scheme-CbCwGDWH.js +0 -12
- package/dist/html-DJUK2YJF.js +0 -483
- package/dist/render-template-DwPDm3Hq.js +0 -1226
- package/dist/selectors-CYWCoxZr.js +0 -157
- package/dist/source-locations-C8wCsiAy.d.ts +0 -22
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
//#region src/email/font-stacks.ts
|
|
2
|
-
/** Generic families every email client understands as the last resort in a stack. */
|
|
3
|
-
const GENERIC_FAMILIES = /* @__PURE__ */ new Set([
|
|
4
|
-
"serif",
|
|
5
|
-
"sans-serif",
|
|
6
|
-
"monospace",
|
|
7
|
-
"cursive",
|
|
8
|
-
"fantasy"
|
|
9
|
-
]);
|
|
10
|
-
/** One family name as written, without its quotes and with runs of spaces collapsed. */
|
|
11
|
-
const unquote = (value) => {
|
|
12
|
-
const trimmed = value.trim();
|
|
13
|
-
const quote = trimmed[0];
|
|
14
|
-
return (quote === "\"" || quote === "'") && trimmed.endsWith(quote) && trimmed.length >= 2 ? trimmed.slice(1, -1) : trimmed.replace(/\s+/g, " ");
|
|
15
|
-
};
|
|
16
|
-
/** The families of a `font-family` value, unquoted, in stack order. */
|
|
17
|
-
const fontStackFamilies = (value) => {
|
|
18
|
-
const families = [];
|
|
19
|
-
let start = 0;
|
|
20
|
-
let quote;
|
|
21
|
-
for (let index = 0; index < value.length; index++) {
|
|
22
|
-
const character = value[index];
|
|
23
|
-
if (quote !== void 0) {
|
|
24
|
-
if (character === quote) quote = void 0;
|
|
25
|
-
} else if (character === "'" || character === "\"") quote = character;
|
|
26
|
-
else if (character === ",") {
|
|
27
|
-
families.push(unquote(value.slice(start, index)));
|
|
28
|
-
start = index + 1;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
families.push(unquote(value.slice(start)));
|
|
32
|
-
return families.filter((family) => family !== "");
|
|
33
|
-
};
|
|
34
|
-
const FONT_SIZE = /^(?:xx-small|x-small|small|medium|large|x-large|xx-large|xxx-large|larger|smaller|[+-]?(?:\d+\.?\d*|\.\d+)(?:[a-z]+|%)|(?:calc|clamp|min|max|var)\(.*\))$/i;
|
|
35
|
-
/** Whitespace-separated tokens at the top level, keeping parentheses and quotes whole. */
|
|
36
|
-
const shorthandTokens = (value) => {
|
|
37
|
-
const tokens = [];
|
|
38
|
-
let current = "";
|
|
39
|
-
let depth = 0;
|
|
40
|
-
let quote;
|
|
41
|
-
for (const character of value.trim()) {
|
|
42
|
-
if (quote !== void 0) {
|
|
43
|
-
if (character === quote) quote = void 0;
|
|
44
|
-
} else if (character === "'" || character === "\"") quote = character;
|
|
45
|
-
else if (character === "(") depth++;
|
|
46
|
-
else if (character === ")") depth--;
|
|
47
|
-
else if (/\s/.test(character) && depth === 0) {
|
|
48
|
-
if (current !== "") tokens.push(current);
|
|
49
|
-
current = "";
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
current += character;
|
|
53
|
-
}
|
|
54
|
-
if (current !== "") tokens.push(current);
|
|
55
|
-
return tokens;
|
|
56
|
-
};
|
|
57
|
-
/**
|
|
58
|
-
* The family list of a `font` shorthand: everything after the size (and its
|
|
59
|
-
* optional line height), or `undefined` for a system-font keyword that names
|
|
60
|
-
* no family.
|
|
61
|
-
*/
|
|
62
|
-
const fontShorthandFamilies = (value) => {
|
|
63
|
-
const tokens = shorthandTokens(value);
|
|
64
|
-
const size = tokens.findIndex((token) => FONT_SIZE.test(token.replace(/\/.*$/, "")));
|
|
65
|
-
if (size < 0) return void 0;
|
|
66
|
-
let next = size + 1;
|
|
67
|
-
const sizeToken = tokens[size];
|
|
68
|
-
if (sizeToken.endsWith("/")) next += 1;
|
|
69
|
-
else if (!sizeToken.includes("/") && tokens[next]?.startsWith("/")) next += tokens[next] === "/" ? 2 : 1;
|
|
70
|
-
const family = tokens.slice(next).join(" ");
|
|
71
|
-
return family === "" ? void 0 : family;
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* True when a stack names a declared project family without ending in a
|
|
75
|
-
* generic. `declared` holds lowercased family names. A quoted `"sans-serif"`
|
|
76
|
-
* names a font called sans-serif, not the generic, so it does not count.
|
|
77
|
-
*/
|
|
78
|
-
const lacksGenericFallback = (value, declared) => {
|
|
79
|
-
const stack = value.replace(/\s*!important\s*$/i, "");
|
|
80
|
-
if (!fontStackFamilies(stack).some((family) => declared.has(family.toLowerCase()))) return false;
|
|
81
|
-
const last = stack.slice(stack.lastIndexOf(",") + 1).trim();
|
|
82
|
-
return !GENERIC_FAMILIES.has(last.toLowerCase());
|
|
83
|
-
};
|
|
84
|
-
const fontFallbackDiagnostic = (value) => ({
|
|
85
|
-
code: "email-font-fallback",
|
|
86
|
-
severity: "error",
|
|
87
|
-
message: `font-family ${JSON.stringify(value)} uses a project font without a generic fallback. Clients that drop webfonts (Gmail, classic Outlook) render this stack as written, so end it with sans-serif, serif or monospace.`
|
|
88
|
-
});
|
|
89
|
-
//#endregion
|
|
90
|
-
//#region src/email/selectors.ts
|
|
91
|
-
const classListOf = (element) => {
|
|
92
|
-
const value = element.props.class ?? element.props.className;
|
|
93
|
-
return typeof value === "string" ? value.split(/\s+/).filter((name) => name !== "") : [];
|
|
94
|
-
};
|
|
95
|
-
const attributeOf = (element, name) => {
|
|
96
|
-
const value = element.props[name];
|
|
97
|
-
if (value === void 0 || value === null || value === false) return void 0;
|
|
98
|
-
if (value === true) return "";
|
|
99
|
-
return typeof value === "string" || typeof value === "number" ? String(value) : void 0;
|
|
100
|
-
};
|
|
101
|
-
const matchesAttribute = (element, test) => {
|
|
102
|
-
const actual = test.name === "class" ? classListOf(element).join(" ") : attributeOf(element, test.name);
|
|
103
|
-
if (actual === void 0) return false;
|
|
104
|
-
if (test.operator === void 0 || test.value === void 0) return true;
|
|
105
|
-
switch (test.operator) {
|
|
106
|
-
case "=": return actual === test.value;
|
|
107
|
-
case "~=": return actual.split(/\s+/).includes(test.value);
|
|
108
|
-
case "^=": return actual.startsWith(test.value);
|
|
109
|
-
case "$=": return actual.endsWith(test.value);
|
|
110
|
-
case "*=": return actual.includes(test.value);
|
|
111
|
-
case "|=": return actual === test.value || actual.startsWith(`${test.value}-`);
|
|
112
|
-
default: return false;
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
const matchesCompound = (element, compound) => {
|
|
116
|
-
if (compound.opaque) return false;
|
|
117
|
-
if (compound.tag !== void 0 && compound.tag !== element.tag) return false;
|
|
118
|
-
if (compound.id !== void 0 && attributeOf(element, "id") !== compound.id) return false;
|
|
119
|
-
if (compound.classes.length > 0) {
|
|
120
|
-
const classes = classListOf(element);
|
|
121
|
-
if (!compound.classes.every((name) => classes.includes(name))) return false;
|
|
122
|
-
}
|
|
123
|
-
return compound.attributes.every((test) => matchesAttribute(element, test));
|
|
124
|
-
};
|
|
125
|
-
const matchesFrom = (selector, index, ancestry) => {
|
|
126
|
-
if (ancestry === void 0) return false;
|
|
127
|
-
const part = selector.parts[index];
|
|
128
|
-
if (part === void 0) return false;
|
|
129
|
-
if (!matchesCompound(ancestry.element, part.compound)) return false;
|
|
130
|
-
const left = selector.parts[index - 1];
|
|
131
|
-
if (left === void 0) return true;
|
|
132
|
-
switch (left.after ?? "descendant") {
|
|
133
|
-
case "child": return matchesFrom(selector, index - 1, ancestry.parent);
|
|
134
|
-
case "descendant":
|
|
135
|
-
for (let parent = ancestry.parent; parent !== void 0; parent = parent.parent) if (matchesFrom(selector, index - 1, parent)) return true;
|
|
136
|
-
return false;
|
|
137
|
-
case "adjacent": {
|
|
138
|
-
const sibling = ancestry.previous.at(-1);
|
|
139
|
-
return sibling === void 0 ? false : matchesFrom(selector, index - 1, {
|
|
140
|
-
element: sibling,
|
|
141
|
-
parent: ancestry.parent,
|
|
142
|
-
previous: ancestry.previous.slice(0, -1)
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
case "sibling":
|
|
146
|
-
for (let position = ancestry.previous.length - 1; position >= 0; position--) if (matchesFrom(selector, index - 1, {
|
|
147
|
-
element: ancestry.previous[position],
|
|
148
|
-
parent: ancestry.parent,
|
|
149
|
-
previous: ancestry.previous.slice(0, position)
|
|
150
|
-
})) return true;
|
|
151
|
-
return false;
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
/** Match a compiled selector against one element in its tree position. */
|
|
155
|
-
const matchesSelector = (selector, ancestry) => selector === void 0 || selector.parts.length === 0 ? false : matchesFrom(selector, selector.parts.length - 1, ancestry);
|
|
156
|
-
//#endregion
|
|
157
|
-
export { lacksGenericFallback as a, fontShorthandFamilies as i, matchesSelector as n, unquote as o, fontFallbackDiagnostic as r, classListOf as t };
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
//#region src/source-locations.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* The source payload a JSX transform may attach to an element. The transform may omit any field
|
|
4
|
-
* for synthetic calls; only a complete payload can identify a source origin safely.
|
|
5
|
-
*/
|
|
6
|
-
interface JsxSource {
|
|
7
|
-
readonly fileName?: string | undefined;
|
|
8
|
-
readonly lineNumber?: number | undefined;
|
|
9
|
-
readonly columnNumber?: number | undefined;
|
|
10
|
-
}
|
|
11
|
-
/** A complete, normalized source origin for a JSX element. */
|
|
12
|
-
interface JsxSourceLocation {
|
|
13
|
-
readonly fileName: string;
|
|
14
|
-
readonly lineNumber: number;
|
|
15
|
-
readonly columnNumber: number;
|
|
16
|
-
}
|
|
17
|
-
/** The JSX prop that carries a {@link JsxSource} to the email JSX runtime. */
|
|
18
|
-
declare const JSX_SOURCE_LOCATION_PROP: "__samva_source_location";
|
|
19
|
-
/** Normalize the optional payload a JSX transform attaches. */
|
|
20
|
-
declare const completeJsxSourceLocation: (source: JsxSource | null | undefined) => JsxSourceLocation | undefined;
|
|
21
|
-
//#endregion
|
|
22
|
-
export { completeJsxSourceLocation as i, JsxSource as n, JsxSourceLocation as r, JSX_SOURCE_LOCATION_PROP as t };
|