@samva/markup 0.4.0 → 0.5.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 +17 -0
- package/dist/{ast-63I-VLQx.d.ts → ast-BLybiDxp.d.ts} +34 -60
- package/dist/ast.d.ts +2 -2
- package/dist/ast.js +4 -52
- package/dist/{catalog-Ck1tAGwO.d.ts → catalog-Db0UcCTg.d.ts} +2 -2
- package/dist/{checks-DXuERO4B.js → checks-CmmITP6j.js} +14 -14
- package/dist/checks.d.ts +1 -1
- package/dist/checks.js +1 -1
- package/dist/classes.d.ts +1 -1
- package/dist/compile-sms.d.ts +3 -3
- package/dist/compile-whatsapp.d.ts +5 -5
- package/dist/compile-whatsapp.js +3 -3
- package/dist/compile.d.ts +5 -5
- package/dist/compile.js +5 -5
- package/dist/compiler.d.ts +4 -4
- package/dist/compiler.js +6 -6
- package/dist/components.d.ts +4 -4
- package/dist/conditionals.js +3 -3
- package/dist/corpus-CM7rKX41.d.ts +106 -0
- package/dist/{css-ar2lU3NC.d.ts → css-DoNc7CiC.d.ts} +4 -5
- package/dist/diagnostics-CqepLcpI.d.ts +47 -0
- package/dist/diagnostics-eFM9A_TU.d.ts +46 -0
- package/dist/diagnostics.d.ts +2 -2
- package/dist/diagnostics.js +15 -29
- package/dist/{elements-DtwKlFVH.d.ts → elements-ChJULZlh.d.ts} +40 -161
- package/dist/email/components.d.ts +1 -1
- package/dist/email/diagnostics.d.ts +1 -1
- package/dist/email/diagnostics.js +8 -43
- package/dist/email/elements.d.ts +1 -1
- package/dist/email/html.d.ts +2 -2
- package/dist/email/html.js +9 -9
- package/dist/email/jsx-dev-runtime.d.ts +3 -21
- package/dist/email/jsx-runtime.d.ts +1 -1
- package/dist/email/jsx-runtime.js +29 -3
- package/dist/email/render.d.ts +4 -4
- package/dist/email/render.js +1 -1
- package/dist/email/selection.d.ts +20 -31
- package/dist/email/selection.js +1 -53
- package/dist/email/source-edit.d.ts +1 -1
- package/dist/email/source-edit.js +2 -2
- package/dist/email/stylesheets.d.ts +1 -1
- package/dist/email/text.d.ts +1 -1
- package/dist/email/text.js +3 -3
- package/dist/emit.d.ts +2 -2
- package/dist/emit.js +5 -5
- package/dist/guards-eV1qLbf2.js +9 -0
- package/dist/{input-schema-BIfzI63B.d.ts → input-schema-7dPFVvNE.d.ts} +2 -2
- package/dist/input-schema-zjkgrXn2.js +455 -0
- package/dist/input-schema.d.ts +1 -1
- package/dist/input-schema.js +1 -169
- package/dist/interpolate.d.ts +9 -12
- package/dist/interpolate.js +1 -19
- package/dist/jsx-dev-runtime.d.ts +2 -2
- package/dist/{jsx-runtime-C5k_Zq0A.d.ts → jsx-runtime-BI4gI19E.d.ts} +3 -3
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/jsx-runtime.js +3 -3
- package/dist/model.d.ts +18 -33
- package/dist/model.js +4 -17
- package/dist/ops.d.ts +78 -172
- package/dist/ops.js +51 -117
- package/dist/{parser-CGBS73Gz.d.ts → parser-b_Kp5MT6.d.ts} +5 -5
- package/dist/parser.d.ts +1 -1
- package/dist/parser.js +8 -8
- package/dist/{predicate-G2SeSvoN.d.ts → predicate-Bmvgw7Ao.d.ts} +4 -4
- package/dist/{predicate-CvkzT-a2.js → predicate-DwXzmqIY.js} +11 -11
- package/dist/predicate.d.ts +1 -1
- package/dist/predicate.js +1 -1
- package/dist/presets/category-mapping.d.ts +1 -1
- package/dist/presets/corpus.d.ts +1 -1
- package/dist/presets/corpus.js +74 -117
- package/dist/presets/public-gallery.d.ts +2 -2
- package/dist/presets/public-gallery.js +7 -7
- package/dist/presets/public-handoff.d.ts +4 -4
- package/dist/presets/public-handoff.js +10 -9
- package/dist/presets/public-preview-artifacts.d.ts +5 -5
- package/dist/presets/public-preview-artifacts.js +9 -9
- package/dist/presets/showcase.d.ts +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/printer.d.ts +1 -1
- package/dist/{render-ykQhtMs_.js → render-T6IFPnP4.js} +12 -12
- package/dist/render-template.d.ts +7 -7
- package/dist/render-template.js +6 -6
- package/dist/{showcase-C_xgl6hz.d.ts → showcase-dvJMn-Lo.d.ts} +2 -2
- package/dist/{source-locations-BCJQnIfU.d.ts → source-locations-D6Te6Gy1.d.ts} +4 -26
- package/dist/source-locations.d.ts +2 -2
- package/dist/source-locations.js +3 -26
- package/dist/{template-Dy5yOPyp.d.ts → template-G-QPcfmn.d.ts} +4 -4
- package/dist/template.d.ts +1 -1
- package/dist/template.js +3 -3
- package/dist/theme-css.d.ts +3 -3
- package/dist/theme-css.js +3 -3
- package/dist/tsx-source-instrumentation.d.ts +1 -3
- package/dist/tsx-source-instrumentation.js +6 -6
- package/dist/tsx-tracer.d.ts +7 -11
- package/dist/tsx-tracer.js +164 -164
- package/dist/{variables-if1VrV34.d.ts → variables-BnKs1iqb.d.ts} +2 -2
- package/dist/variables.d.ts +1 -1
- package/dist/variables.js +4 -4
- package/package.json +4 -3
- package/dist/corpus-U2EeALvS.d.ts +0 -234
- package/dist/diagnostics-Djd9ckLg.d.ts +0 -90
- package/dist/diagnostics-oveE-laV.d.ts +0 -79
package/dist/presets/corpus.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
+
import { n as isObject } from "../guards-eV1qLbf2.js";
|
|
1
2
|
import { presetCatalog } from "../presets.js";
|
|
2
3
|
import { showcaseProject, showcaseProjects, showcaseSourcePath } from "./showcase.js";
|
|
3
|
-
import { Result
|
|
4
|
+
import { Result } from "better-result";
|
|
4
5
|
//#region presets/corpus.ts
|
|
5
|
-
const TemplateCorpusKind = Schema.Literals([
|
|
6
|
-
"owned-editable-sml",
|
|
7
|
-
"brand-recreation-sml",
|
|
8
|
-
"inspiration-reference"
|
|
9
|
-
]);
|
|
10
6
|
const templateFacetOptions = {
|
|
11
7
|
jobType: [
|
|
12
8
|
"account-access",
|
|
@@ -47,74 +43,6 @@ const templateFacetOptions = {
|
|
|
47
43
|
],
|
|
48
44
|
brandProvenance: ["samva-original", "third-party-reference"]
|
|
49
45
|
};
|
|
50
|
-
const JobTypeFacet = Schema.Literals(templateFacetOptions.jobType);
|
|
51
|
-
const LifecycleFacet = Schema.Literals(templateFacetOptions.lifecycle);
|
|
52
|
-
const IndustryFacet = Schema.Literals(templateFacetOptions.industry);
|
|
53
|
-
const SeasonFacet = Schema.Literals(templateFacetOptions.season);
|
|
54
|
-
const AudienceFacet = Schema.Literals(templateFacetOptions.audience);
|
|
55
|
-
const DesignFacet = Schema.Literals(templateFacetOptions.design);
|
|
56
|
-
const BrandProvenanceFacet = Schema.Literals(templateFacetOptions.brandProvenance);
|
|
57
|
-
const TemplateFacetSet = Schema.Struct({
|
|
58
|
-
jobType: Schema.Array(JobTypeFacet),
|
|
59
|
-
lifecycle: Schema.Array(LifecycleFacet),
|
|
60
|
-
industry: Schema.Array(IndustryFacet),
|
|
61
|
-
season: Schema.Array(SeasonFacet),
|
|
62
|
-
audience: Schema.Array(AudienceFacet),
|
|
63
|
-
design: Schema.Array(DesignFacet),
|
|
64
|
-
brandProvenance: Schema.Array(BrandProvenanceFacet)
|
|
65
|
-
});
|
|
66
|
-
const CorpusReview = Schema.Struct({
|
|
67
|
-
state: Schema.Literals([
|
|
68
|
-
"draft",
|
|
69
|
-
"approved",
|
|
70
|
-
"rejected"
|
|
71
|
-
]),
|
|
72
|
-
reviewedBy: Schema.String,
|
|
73
|
-
reviewedAt: Schema.String,
|
|
74
|
-
notes: Schema.String
|
|
75
|
-
});
|
|
76
|
-
const CorpusDisplay = Schema.Struct({
|
|
77
|
-
state: Schema.Literals(["hidden", "public"]),
|
|
78
|
-
attributionLabel: Schema.String
|
|
79
|
-
});
|
|
80
|
-
const CorpusRetention = Schema.Struct({
|
|
81
|
-
policy: Schema.Literals(["retain-until-withdrawn", "retain-while-linked"]),
|
|
82
|
-
reviewedAt: Schema.String
|
|
83
|
-
});
|
|
84
|
-
const CorpusTakedown = Schema.Struct({
|
|
85
|
-
state: Schema.Literals(["active", "removed"]),
|
|
86
|
-
contact: Schema.String,
|
|
87
|
-
procedureUrl: Schema.String
|
|
88
|
-
});
|
|
89
|
-
const OwnedEditablePreset = Schema.TaggedStruct("OwnedEditablePreset", {
|
|
90
|
-
corpusKind: Schema.Literal("owned-editable-sml"),
|
|
91
|
-
provenance: Schema.Struct({
|
|
92
|
-
owner: Schema.Literal("Samva"),
|
|
93
|
-
sourcePath: Schema.String,
|
|
94
|
-
recordedAt: Schema.String
|
|
95
|
-
}),
|
|
96
|
-
review: CorpusReview,
|
|
97
|
-
display: CorpusDisplay,
|
|
98
|
-
retention: CorpusRetention,
|
|
99
|
-
takedown: CorpusTakedown
|
|
100
|
-
});
|
|
101
|
-
const BrandRecreationPreset = Schema.TaggedStruct("BrandRecreationPreset", {
|
|
102
|
-
corpusKind: Schema.Literal("brand-recreation-sml"),
|
|
103
|
-
provenance: Schema.Struct({
|
|
104
|
-
owner: Schema.Literal("Samva"),
|
|
105
|
-
sourcePath: Schema.String,
|
|
106
|
-
recordedAt: Schema.String,
|
|
107
|
-
/** The brand whose own email is recreated, named on every public surface. */
|
|
108
|
-
brand: Schema.String,
|
|
109
|
-
/** What that brand's email does, in the customer's words. */
|
|
110
|
-
subject: Schema.String,
|
|
111
|
-
reviewedNote: Schema.String
|
|
112
|
-
}),
|
|
113
|
-
review: CorpusReview,
|
|
114
|
-
display: CorpusDisplay,
|
|
115
|
-
retention: CorpusRetention,
|
|
116
|
-
takedown: CorpusTakedown
|
|
117
|
-
});
|
|
118
46
|
/** Clean-room recreations of a named brand's own email, authored as editable Samva projects. */
|
|
119
47
|
const brandRecreationProvenance = Object.fromEntries(showcaseProjects.flatMap((project) => project.provenance.kind === "brand-recreation" ? [[project.id, {
|
|
120
48
|
owner: "Samva",
|
|
@@ -133,24 +61,6 @@ const ownedPresetSourcePath = (id) => {
|
|
|
133
61
|
const project = showcaseProject(id);
|
|
134
62
|
return project === void 0 || project.provenance.kind !== "owned" ? `packages/markup/presets/${id}.tsx` : showcaseSourcePath(project);
|
|
135
63
|
};
|
|
136
|
-
const InspirationReference = Schema.TaggedStruct("InspirationReference", {
|
|
137
|
-
corpusKind: Schema.Literal("inspiration-reference"),
|
|
138
|
-
provenance: Schema.Struct({
|
|
139
|
-
publisher: Schema.String,
|
|
140
|
-
sourceUrl: Schema.String,
|
|
141
|
-
capturedAt: Schema.String,
|
|
142
|
-
rightsBasis: Schema.Literals(["display-link-and-commentary", "permission"])
|
|
143
|
-
}),
|
|
144
|
-
review: CorpusReview,
|
|
145
|
-
display: CorpusDisplay,
|
|
146
|
-
retention: CorpusRetention,
|
|
147
|
-
takedown: CorpusTakedown
|
|
148
|
-
});
|
|
149
|
-
const TemplateCorpusRecord = Schema.Union([
|
|
150
|
-
OwnedEditablePreset,
|
|
151
|
-
BrandRecreationPreset,
|
|
152
|
-
InspirationReference
|
|
153
|
-
]);
|
|
154
64
|
const ISO_TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/;
|
|
155
65
|
const nonEmpty = (value) => value.trim().length > 0;
|
|
156
66
|
const isHttpsUrl = (value) => {
|
|
@@ -166,65 +76,112 @@ const requiredFacetDimensions = [
|
|
|
166
76
|
"design",
|
|
167
77
|
"brandProvenance"
|
|
168
78
|
];
|
|
79
|
+
/** Exact key sets: a record carrying anything else is not the shape this gate admits. */
|
|
80
|
+
const exactKeys = (value, keys) => isObject(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
81
|
+
const isStringIn = (value, values) => typeof value === "string" && values.includes(value);
|
|
82
|
+
const isStringArrayIn = (value, values) => Array.isArray(value) && value.every((entry) => isStringIn(entry, values));
|
|
83
|
+
const isReview = (value) => exactKeys(value, [
|
|
84
|
+
"state",
|
|
85
|
+
"reviewedBy",
|
|
86
|
+
"reviewedAt",
|
|
87
|
+
"notes"
|
|
88
|
+
]) && isStringIn(value.state, [
|
|
89
|
+
"draft",
|
|
90
|
+
"approved",
|
|
91
|
+
"rejected"
|
|
92
|
+
]) && typeof value.reviewedBy === "string" && typeof value.reviewedAt === "string" && typeof value.notes === "string";
|
|
93
|
+
const isDisplay = (value) => exactKeys(value, ["state", "attributionLabel"]) && isStringIn(value.state, ["hidden", "public"]) && typeof value.attributionLabel === "string";
|
|
94
|
+
const isRetention = (value) => exactKeys(value, ["policy", "reviewedAt"]) && isStringIn(value.policy, ["retain-until-withdrawn", "retain-while-linked"]) && typeof value.reviewedAt === "string";
|
|
95
|
+
const isTakedown = (value) => exactKeys(value, [
|
|
96
|
+
"state",
|
|
97
|
+
"contact",
|
|
98
|
+
"procedureUrl"
|
|
99
|
+
]) && isStringIn(value.state, ["active", "removed"]) && typeof value.contact === "string" && typeof value.procedureUrl === "string";
|
|
100
|
+
/** The four governance blocks every corpus record carries, whatever its kind. */
|
|
101
|
+
const hasGovernance = (value) => isReview(value.review) && isDisplay(value.display) && isRetention(value.retention) && isTakedown(value.takedown);
|
|
102
|
+
const CORPUS_KEYS = [
|
|
103
|
+
"type",
|
|
104
|
+
"corpusKind",
|
|
105
|
+
"provenance",
|
|
106
|
+
"review",
|
|
107
|
+
"display",
|
|
108
|
+
"retention",
|
|
109
|
+
"takedown"
|
|
110
|
+
];
|
|
111
|
+
const isCorpusRecord = (value) => {
|
|
112
|
+
if (!exactKeys(value, CORPUS_KEYS) || !hasGovernance(value)) return false;
|
|
113
|
+
const provenance = value.provenance;
|
|
114
|
+
if (value.type === "OwnedEditablePreset") return value.corpusKind === "owned-editable-sml" && exactKeys(provenance, [
|
|
115
|
+
"owner",
|
|
116
|
+
"sourcePath",
|
|
117
|
+
"recordedAt"
|
|
118
|
+
]) && provenance.owner === "Samva" && typeof provenance.sourcePath === "string" && typeof provenance.recordedAt === "string";
|
|
119
|
+
if (value.type === "BrandRecreationPreset") return value.corpusKind === "brand-recreation-sml" && exactKeys(provenance, [
|
|
120
|
+
"owner",
|
|
121
|
+
"sourcePath",
|
|
122
|
+
"recordedAt",
|
|
123
|
+
"brand",
|
|
124
|
+
"subject",
|
|
125
|
+
"reviewedNote"
|
|
126
|
+
]) && provenance.owner === "Samva" && typeof provenance.sourcePath === "string" && typeof provenance.recordedAt === "string" && typeof provenance.brand === "string" && typeof provenance.subject === "string" && typeof provenance.reviewedNote === "string";
|
|
127
|
+
return value.type === "InspirationReference" && value.corpusKind === "inspiration-reference" && exactKeys(provenance, [
|
|
128
|
+
"publisher",
|
|
129
|
+
"sourceUrl",
|
|
130
|
+
"capturedAt",
|
|
131
|
+
"rightsBasis"
|
|
132
|
+
]) && typeof provenance.publisher === "string" && typeof provenance.sourceUrl === "string" && typeof provenance.capturedAt === "string" && isStringIn(provenance.rightsBasis, ["display-link-and-commentary", "permission"]);
|
|
133
|
+
};
|
|
134
|
+
const isFacetSet = (value) => exactKeys(value, requiredFacetDimensions) && requiredFacetDimensions.every((dimension) => isStringArrayIn(value[dimension], templateFacetOptions[dimension]));
|
|
135
|
+
const isCorpusEntry = (value) => exactKeys(value, [
|
|
136
|
+
"id",
|
|
137
|
+
"corpus",
|
|
138
|
+
"facets"
|
|
139
|
+
]) && typeof value.id === "string" && isCorpusRecord(value.corpus) && isFacetSet(value.facets);
|
|
169
140
|
const canonicalOwnedPresetSources = new Map(presetCatalog.filter((preset) => preset.channel === "email" && !Object.hasOwn(brandRecreationProvenance, preset.id)).map((preset) => [preset.id, ownedPresetSourcePath(preset.id)]));
|
|
170
141
|
/** Decode and gate a record before it can enter any public projection. */
|
|
171
142
|
const registerPublicCorpusEntry = (input) => {
|
|
172
|
-
|
|
173
|
-
id: Schema.String,
|
|
174
|
-
corpus: TemplateCorpusRecord,
|
|
175
|
-
facets: TemplateFacetSet
|
|
176
|
-
}), { onExcessProperty: "error" })(input);
|
|
177
|
-
if (Result.isFailure(decoded)) return Result.fail({
|
|
143
|
+
if (!isCorpusEntry(input)) return Result.err({
|
|
178
144
|
id: "unknown",
|
|
179
145
|
message: "record does not match a corpus schema"
|
|
180
146
|
});
|
|
181
|
-
const { id, corpus, facets } =
|
|
147
|
+
const { id, corpus, facets } = input;
|
|
182
148
|
const timestamps = [
|
|
183
149
|
corpus.review.reviewedAt,
|
|
184
150
|
corpus.retention.reviewedAt,
|
|
185
|
-
corpus.
|
|
151
|
+
corpus.type === "InspirationReference" ? corpus.provenance.capturedAt : corpus.provenance.recordedAt
|
|
186
152
|
];
|
|
187
|
-
if (!nonEmpty(id) || corpus.review.state !== "approved" || !nonEmpty(corpus.review.reviewedBy) || !nonEmpty(corpus.review.notes) || corpus.display.state !== "public" || !nonEmpty(corpus.display.attributionLabel) || corpus.takedown.state !== "active" || !nonEmpty(corpus.takedown.contact) || !isHttpsUrl(corpus.takedown.procedureUrl) || timestamps.some((timestamp) => !ISO_TIMESTAMP.test(timestamp))) return Result.
|
|
153
|
+
if (!nonEmpty(id) || corpus.review.state !== "approved" || !nonEmpty(corpus.review.reviewedBy) || !nonEmpty(corpus.review.notes) || corpus.display.state !== "public" || !nonEmpty(corpus.display.attributionLabel) || corpus.takedown.state !== "active" || !nonEmpty(corpus.takedown.contact) || !isHttpsUrl(corpus.takedown.procedureUrl) || timestamps.some((timestamp) => !ISO_TIMESTAMP.test(timestamp))) return Result.err({
|
|
188
154
|
id,
|
|
189
155
|
message: "public corpus records require approved review, display, retention, and takedown metadata"
|
|
190
156
|
});
|
|
191
|
-
if (corpus.
|
|
157
|
+
if (corpus.type === "OwnedEditablePreset" && (canonicalOwnedPresetSources.get(id) !== corpus.provenance.sourcePath || corpus.retention.policy !== "retain-until-withdrawn" || facets.brandProvenance.some((value) => value !== "samva-original"))) return Result.err({
|
|
192
158
|
id,
|
|
193
159
|
message: "owned presets require a canonical editable TSX source"
|
|
194
160
|
});
|
|
195
|
-
if (corpus.
|
|
161
|
+
if (corpus.type === "BrandRecreationPreset") {
|
|
196
162
|
const canonical = Object.entries(brandRecreationProvenance).find(([presetId]) => presetId === id)?.[1];
|
|
197
|
-
if (canonical === void 0 || Object.entries(canonical).some(([key, value]) => corpus.provenance[key] !== value) || !nonEmpty(corpus.provenance.brand) || !nonEmpty(corpus.provenance.subject) || corpus.retention.policy !== "retain-until-withdrawn" || facets.brandProvenance.some((value) => value !== "third-party-reference")) return Result.
|
|
163
|
+
if (canonical === void 0 || Object.entries(canonical).some(([key, value]) => corpus.provenance[key] !== value) || !nonEmpty(corpus.provenance.brand) || !nonEmpty(corpus.provenance.subject) || corpus.retention.policy !== "retain-until-withdrawn" || facets.brandProvenance.some((value) => value !== "third-party-reference")) return Result.err({
|
|
198
164
|
id,
|
|
199
165
|
message: "brand recreations require a canonical source, a referenced brand and subject, and third-party provenance"
|
|
200
166
|
});
|
|
201
167
|
}
|
|
202
|
-
if (corpus.
|
|
168
|
+
if (corpus.type === "InspirationReference" && (!isHttpsUrl(corpus.provenance.sourceUrl) || corpus.retention.policy !== "retain-while-linked" || facets.brandProvenance.some((value) => value !== "third-party-reference"))) return Result.err({
|
|
203
169
|
id,
|
|
204
170
|
message: "inspiration references require an HTTPS source and third-party provenance facet"
|
|
205
171
|
});
|
|
206
172
|
for (const dimension of requiredFacetDimensions) {
|
|
207
173
|
const values = facets[dimension];
|
|
208
|
-
if (values.length === 0 || new Set(values).size !== values.length) return Result.
|
|
174
|
+
if (values.length === 0 || new Set(values).size !== values.length) return Result.err({
|
|
209
175
|
id,
|
|
210
176
|
message: `facet ${dimension} must be populated without duplicates`
|
|
211
177
|
});
|
|
212
178
|
}
|
|
213
|
-
return Result.
|
|
179
|
+
return Result.ok({
|
|
214
180
|
id,
|
|
215
181
|
corpus,
|
|
216
182
|
facets
|
|
217
183
|
});
|
|
218
184
|
};
|
|
219
|
-
const TemplateFacetQuery = Schema.Struct({
|
|
220
|
-
jobType: Schema.optionalKey(Schema.Array(JobTypeFacet)),
|
|
221
|
-
lifecycle: Schema.optionalKey(Schema.Array(LifecycleFacet)),
|
|
222
|
-
industry: Schema.optionalKey(Schema.Array(IndustryFacet)),
|
|
223
|
-
season: Schema.optionalKey(Schema.Array(SeasonFacet)),
|
|
224
|
-
audience: Schema.optionalKey(Schema.Array(AudienceFacet)),
|
|
225
|
-
design: Schema.optionalKey(Schema.Array(DesignFacet)),
|
|
226
|
-
brandProvenance: Schema.optionalKey(Schema.Array(BrandProvenanceFacet))
|
|
227
|
-
});
|
|
228
185
|
/** Strict intersection: every selected value in every selected dimension must match. */
|
|
229
186
|
const matchesTemplateFacets = (facets, query) => requiredFacetDimensions.every((dimension) => {
|
|
230
187
|
const selected = query[dimension];
|
|
@@ -232,6 +189,6 @@ const matchesTemplateFacets = (facets, query) => requiredFacetDimensions.every((
|
|
|
232
189
|
return selected === void 0 || selected.every((value) => available.has(value));
|
|
233
190
|
});
|
|
234
191
|
//#endregion
|
|
235
|
-
export {
|
|
192
|
+
export { brandRecreationProvenance, matchesTemplateFacets, ownedPresetSourcePath, ownedShowcasePresetSources, registerPublicCorpusEntry, templateFacetOptions };
|
|
236
193
|
|
|
237
194
|
//# sourceMappingURL=corpus.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as EmailPresetId } from "../catalog-
|
|
2
|
-
import { c as TemplateFacetQuery, l as TemplateFacetSet, r as OwnedEditablePreset, t as BrandRecreationPreset } from "../corpus-
|
|
1
|
+
import { t as EmailPresetId } from "../catalog-Db0UcCTg.js";
|
|
2
|
+
import { c as TemplateFacetQuery, l as TemplateFacetSet, r as OwnedEditablePreset, t as BrandRecreationPreset } from "../corpus-CM7rKX41.js";
|
|
3
3
|
//#region presets/public-gallery.d.ts
|
|
4
4
|
declare const templateUseCases: readonly ["account-access", "commerce", "product-communication", "lifecycle", "publishing-campaigns"];
|
|
5
5
|
declare const templateCollectionFamilies: readonly ["category", "industry", "stage", "style"];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { brandRecreationProvenance, matchesTemplateFacets, registerPublicCorpusEntry } from "./corpus.js";
|
|
2
|
-
import { Result } from "
|
|
2
|
+
import { Result } from "better-result";
|
|
3
3
|
//#region presets/public-gallery.ts
|
|
4
4
|
const templateUseCases = [
|
|
5
5
|
"account-access",
|
|
@@ -14,7 +14,7 @@ const templateCollectionFamilies = [
|
|
|
14
14
|
"stage",
|
|
15
15
|
"style"
|
|
16
16
|
];
|
|
17
|
-
const isMadeWithSamvaTemplate = (template) => template.corpus.
|
|
17
|
+
const isMadeWithSamvaTemplate = (template) => template.corpus.type === "OwnedEditablePreset" || template.corpus.type === "BrandRecreationPreset";
|
|
18
18
|
/** Explicit evidence for every owned preset reviewed in the 2026-08-31 catalog pass. */
|
|
19
19
|
const ownedPresetReviewManifest = {
|
|
20
20
|
welcome: {
|
|
@@ -260,7 +260,7 @@ const template = (value) => {
|
|
|
260
260
|
if (isBrandRecreationPresetId(value.presetId)) {
|
|
261
261
|
const provenance = brandRecreationProvenance[value.presetId];
|
|
262
262
|
return {
|
|
263
|
-
|
|
263
|
+
type: "BrandRecreationPreset",
|
|
264
264
|
corpusKind: "brand-recreation-sml",
|
|
265
265
|
provenance,
|
|
266
266
|
review: {
|
|
@@ -286,7 +286,7 @@ const template = (value) => {
|
|
|
286
286
|
}
|
|
287
287
|
const review = ownedPresetReviewManifest[value.presetId];
|
|
288
288
|
return {
|
|
289
|
-
|
|
289
|
+
type: "OwnedEditablePreset",
|
|
290
290
|
corpusKind: "owned-editable-sml",
|
|
291
291
|
provenance: {
|
|
292
292
|
owner: "Samva",
|
|
@@ -321,19 +321,19 @@ const template = (value) => {
|
|
|
321
321
|
season: value.presetId === "seasonal-sale-flyer" || value.presetId === "season-clearance-promo" ? ["seasonal"] : ["evergreen"],
|
|
322
322
|
audience: audienceFor(value.useCase),
|
|
323
323
|
design: facetValues(value.collections, "style"),
|
|
324
|
-
brandProvenance: [corpus.
|
|
324
|
+
brandProvenance: [corpus.type === "BrandRecreationPreset" ? "third-party-reference" : "samva-original"]
|
|
325
325
|
};
|
|
326
326
|
const registration = registerPublicCorpusEntry({
|
|
327
327
|
id: value.presetId,
|
|
328
328
|
corpus,
|
|
329
329
|
facets
|
|
330
330
|
});
|
|
331
|
-
if (Result.
|
|
331
|
+
if (Result.isError(registration)) throw new Error(`${registration.error.id}: ${registration.error.message}`);
|
|
332
332
|
return {
|
|
333
333
|
...value,
|
|
334
334
|
path: `/templates/${value.slug}`,
|
|
335
335
|
corpus,
|
|
336
|
-
facets: registration.
|
|
336
|
+
facets: registration.value.facets
|
|
337
337
|
};
|
|
338
338
|
};
|
|
339
339
|
const publicTemplates = [
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { r as PresetCategory } from "../catalog-
|
|
1
|
+
import { l as Channel } from "../ast-BLybiDxp.js";
|
|
2
|
+
import { r as PresetCategory } from "../catalog-Db0UcCTg.js";
|
|
3
3
|
import { TemplateCollectionId, TemplateUseCase } from "./public-gallery.js";
|
|
4
4
|
import { PublicTemplatePreview } from "./public-preview.js";
|
|
5
5
|
import { PresetProject } from "./sources.js";
|
|
6
|
-
import { Result } from "
|
|
6
|
+
import { Result } from "better-result";
|
|
7
7
|
//#region presets/public-handoff.d.ts
|
|
8
8
|
/** The brand a clean-room recreation names, and what its email does. */
|
|
9
9
|
interface TemplateBrandRecreation {
|
|
@@ -158,7 +158,7 @@ declare const emitTemplateReferencePacket: (packet: TemplateReferencePacket) =>
|
|
|
158
158
|
* the existing preset, public-gallery, preview, and editorial contracts; this
|
|
159
159
|
* function never registers or publishes it.
|
|
160
160
|
*/
|
|
161
|
-
declare const validatePublicTemplateHandoff: (artifacts: ReadonlyArray<ApprovedPublicTemplateArtifact>) => Result
|
|
161
|
+
declare const validatePublicTemplateHandoff: (artifacts: ReadonlyArray<ApprovedPublicTemplateArtifact>) => Result<ReadonlyArray<ValidatedPublicTemplateArtifact>, ReadonlyArray<PublicHandoffIssue>>;
|
|
162
162
|
//#endregion
|
|
163
163
|
export { ApprovedPublicTemplateArtifact, PUBLIC_TEMPLATE_PROJECT_FILE_MAX_BYTES, PUBLIC_TEMPLATE_PROJECT_MAX_BYTES, PUBLIC_TEMPLATE_PROJECT_MAX_FILES, PUBLIC_TEMPLATE_SOURCE_MAX_CHARACTERS, PublicHandoffIssue, PublicHandoffIssueCode, PublicTemplateAuthoredStructure, TemplateBrandRecreation, TemplateReferencePacket, TemplateReferenceProjection, TemplateReferenceProvenance, ValidatedPublicTemplateArtifact, emitTemplateReferencePacket, isSafePublicTemplateAsset, isSafePublicTemplateProject, isSafePublicTemplateProjectPath, isValidTemplateBrandRecreation, publicTemplateAuthoredStructure, publicTemplateProjectDigest, toTemplateReferencePacket, unsupportedPublicTemplateFontTokens, validatePublicTemplateHandoff };
|
|
164
164
|
//# sourceMappingURL=public-handoff.d.ts.map
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { n as isObject } from "../guards-eV1qLbf2.js";
|
|
1
2
|
import { EMAIL_ELEMENTS } from "../email/elements.js";
|
|
2
3
|
import { presetCatalog } from "../presets.js";
|
|
3
4
|
import { publicTemplates, templateCollections } from "./public-gallery.js";
|
|
4
|
-
import {
|
|
5
|
+
import { Result } from "better-result";
|
|
5
6
|
import { parse } from "@babel/parser";
|
|
6
7
|
//#region presets/public-handoff.ts
|
|
7
8
|
const SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
@@ -15,7 +16,7 @@ const BLOCKED_PUBLIC_ASSET = /(?:unsplash|placehold|assets\.example)/i;
|
|
|
15
16
|
const nonEmptySample = (value) => {
|
|
16
17
|
if (typeof value === "string") return nonEmpty(value);
|
|
17
18
|
if (Array.isArray(value)) return value.length > 0 && value.every(nonEmptySample);
|
|
18
|
-
if (
|
|
19
|
+
if (isObject(value)) {
|
|
19
20
|
const values = Object.values(value);
|
|
20
21
|
return values.length > 0 && values.every(nonEmptySample);
|
|
21
22
|
}
|
|
@@ -120,13 +121,13 @@ const publicTemplateAuthoredStructure = (source) => {
|
|
|
120
121
|
for (const item of value) walk(item, depth);
|
|
121
122
|
return;
|
|
122
123
|
}
|
|
123
|
-
if (!
|
|
124
|
+
if (!isObject(value)) return;
|
|
124
125
|
let childDepth = depth;
|
|
125
126
|
if (value.type === "JSXElement") {
|
|
126
127
|
const opening = value.openingElement;
|
|
127
|
-
if (!
|
|
128
|
+
if (!isObject(opening)) return;
|
|
128
129
|
const name = opening.name;
|
|
129
|
-
const tag =
|
|
130
|
+
const tag = isObject(name) && typeof name.name === "string" && PUBLIC_COMPONENT_TAGS.has(name.name) ? name.name : "Component";
|
|
130
131
|
const childIndex = siblings.get(depth) ?? 0;
|
|
131
132
|
siblings.set(depth, childIndex + 1);
|
|
132
133
|
siblings.set(depth + 1, 0);
|
|
@@ -137,9 +138,9 @@ const publicTemplateAuthoredStructure = (source) => {
|
|
|
137
138
|
});
|
|
138
139
|
counts.set(tag, (counts.get(tag) ?? 0) + 1);
|
|
139
140
|
if (Array.isArray(opening.attributes)) for (const attribute of opening.attributes) {
|
|
140
|
-
if (!
|
|
141
|
+
if (!isObject(attribute) || !isObject(attribute.name) || attribute.name.name !== "className") continue;
|
|
141
142
|
const literal = attribute.value;
|
|
142
|
-
if (!
|
|
143
|
+
if (!isObject(literal) || literal.type !== "StringLiteral" || typeof literal.value !== "string") continue;
|
|
143
144
|
for (const match of literal.value.matchAll(/#([a-f0-9]{8}|[a-f0-9]{6}|[a-f0-9]{3})(?=[^a-f0-9]|$)/gi)) if (palette.size < 24) palette.add(`#${match[1].toLowerCase()}`);
|
|
144
145
|
}
|
|
145
146
|
childDepth += 1;
|
|
@@ -329,8 +330,8 @@ const validatePublicTemplateHandoff = (artifacts) => {
|
|
|
329
330
|
if (new Set(artifact.gallery.relatedTemplates).size !== artifact.gallery.relatedTemplates.length) issues.push(issue(id, "reference", "related template references must be unique"));
|
|
330
331
|
for (const relatedId of artifact.gallery.relatedTemplates) if (relatedId === id || !allKnownIds.has(relatedId)) issues.push(issue(id, "reference", `related template "${relatedId}" is invalid`));
|
|
331
332
|
}
|
|
332
|
-
if (issues.length > 0) return Result.
|
|
333
|
-
return Result.
|
|
333
|
+
if (issues.length > 0) return Result.err(issues);
|
|
334
|
+
return Result.ok(artifacts.map((artifact) => {
|
|
334
335
|
const reference = toTemplateReferencePacket(artifact);
|
|
335
336
|
return {
|
|
336
337
|
approval: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as EmailPresetId } from "../catalog-
|
|
1
|
+
import { t as EmailPresetId } from "../catalog-Db0UcCTg.js";
|
|
2
2
|
import { PublicTemplate } from "./public-gallery.js";
|
|
3
3
|
import { PreviewQuality } from "./public-preview.js";
|
|
4
|
-
import { Result } from "
|
|
4
|
+
import { Result } from "better-result";
|
|
5
5
|
//#region presets/public-preview-artifacts.d.ts
|
|
6
6
|
type PreviewSurface = "card" | "detail" | "og";
|
|
7
7
|
type PreviewViewport = "desktop" | "mobile";
|
|
@@ -31,11 +31,11 @@ interface PreviewArtifactBuildIssue {
|
|
|
31
31
|
readonly message: string;
|
|
32
32
|
}
|
|
33
33
|
/** Build one static preview artifact without loading the editor runtime or performing I/O. */
|
|
34
|
-
declare const buildPublicTemplatePreviewArtifact: (template: PublicTemplate) => Result
|
|
34
|
+
declare const buildPublicTemplatePreviewArtifact: (template: PublicTemplate) => Result<PublicTemplatePreviewArtifact, PreviewArtifactBuildIssue>;
|
|
35
35
|
/** Build only the requested canonical subset, preserving manifest order and aggregated failures. */
|
|
36
|
-
declare const buildPublicTemplatePreviewArtifactsFor: (templates: ReadonlyArray<PublicTemplate>) => Result
|
|
36
|
+
declare const buildPublicTemplatePreviewArtifactsFor: (templates: ReadonlyArray<PublicTemplate>) => Result<ReadonlyArray<PublicTemplatePreviewArtifact>, ReadonlyArray<PreviewArtifactBuildIssue>>;
|
|
37
37
|
/** Build the complete canonical public gallery. */
|
|
38
|
-
declare const buildPublicTemplatePreviewArtifacts: () => Result
|
|
38
|
+
declare const buildPublicTemplatePreviewArtifacts: () => Result<readonly PublicTemplatePreviewArtifact[], readonly PreviewArtifactBuildIssue[]>;
|
|
39
39
|
//#endregion
|
|
40
40
|
export { PreviewArtifactBuildIssue, PreviewColorScheme, PreviewSurface, PreviewViewport, PublicTemplatePreviewArtifact, PublicTemplateRenderInput, buildPublicTemplatePreviewArtifact, buildPublicTemplatePreviewArtifacts, buildPublicTemplatePreviewArtifactsFor };
|
|
41
41
|
//# sourceMappingURL=public-preview-artifacts.d.ts.map
|
|
@@ -3,7 +3,7 @@ import { registerPublicCorpusEntry } from "./corpus.js";
|
|
|
3
3
|
import { publicTemplates } from "./public-gallery.js";
|
|
4
4
|
import { presetEmailAssets, presetEmailFixtures, presetModuleSource } from "./sources.js";
|
|
5
5
|
import { publicTemplatePreviews } from "./public-preview.js";
|
|
6
|
-
import { Result } from "
|
|
6
|
+
import { Result } from "better-result";
|
|
7
7
|
//#region presets/public-preview-artifacts.ts
|
|
8
8
|
const renderFrames = [
|
|
9
9
|
{
|
|
@@ -50,15 +50,15 @@ const buildPublicTemplatePreviewArtifact = (template) => {
|
|
|
50
50
|
corpus: template.corpus,
|
|
51
51
|
facets: template.facets
|
|
52
52
|
});
|
|
53
|
-
if (Result.
|
|
53
|
+
if (Result.isError(registration)) return Result.err({
|
|
54
54
|
presetId: template.presetId,
|
|
55
|
-
message: `public corpus registration failed: ${registration.
|
|
55
|
+
message: `public corpus registration failed: ${registration.error.message}`
|
|
56
56
|
});
|
|
57
57
|
const source = presetModuleSource(template.presetId);
|
|
58
58
|
const fixture = presetEmailFixtures[template.presetId]?.default;
|
|
59
59
|
const preset = presetCatalog.find((entry) => entry.id === template.presetId);
|
|
60
60
|
const preview = publicTemplatePreviews[template.presetId];
|
|
61
|
-
if (source === void 0 || preset === void 0 || fixture === void 0) return Result.
|
|
61
|
+
if (source === void 0 || preset === void 0 || fixture === void 0) return Result.err({
|
|
62
62
|
presetId: template.presetId,
|
|
63
63
|
message: "canonical preset source is missing"
|
|
64
64
|
});
|
|
@@ -66,13 +66,13 @@ const buildPublicTemplatePreviewArtifact = (template) => {
|
|
|
66
66
|
const assets = new Set(presetEmailAssets[template.presetId]);
|
|
67
67
|
for (const asset of preview.assets) {
|
|
68
68
|
const value = sampleData[asset.variable];
|
|
69
|
-
if (typeof value !== "string") return Result.
|
|
69
|
+
if (typeof value !== "string") return Result.err({
|
|
70
70
|
presetId: template.presetId,
|
|
71
71
|
message: `sample data is missing a string asset: ${asset.variable}`
|
|
72
72
|
});
|
|
73
73
|
assets.add(value);
|
|
74
74
|
}
|
|
75
|
-
return Result.
|
|
75
|
+
return Result.ok({
|
|
76
76
|
presetId: template.presetId,
|
|
77
77
|
slug: template.slug,
|
|
78
78
|
subject: fixture.subject,
|
|
@@ -90,10 +90,10 @@ const buildPublicTemplatePreviewArtifactsFor = (templates) => {
|
|
|
90
90
|
const issues = [];
|
|
91
91
|
for (const template of templates) {
|
|
92
92
|
const artifact = buildPublicTemplatePreviewArtifact(template);
|
|
93
|
-
if (Result.
|
|
94
|
-
else issues.push(artifact.
|
|
93
|
+
if (Result.isOk(artifact)) artifacts.push(artifact.value);
|
|
94
|
+
else issues.push(artifact.error);
|
|
95
95
|
}
|
|
96
|
-
return issues.length > 0 ? Result.
|
|
96
|
+
return issues.length > 0 ? Result.err(issues) : Result.ok(artifacts);
|
|
97
97
|
};
|
|
98
98
|
/** Build the complete canonical public gallery. */
|
|
99
99
|
const buildPublicTemplatePreviewArtifacts = () => buildPublicTemplatePreviewArtifactsFor(publicTemplates);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as ShowcaseProjectId, c as showcaseProject, d as showcaseSourcePath, i as ShowcaseProject, l as showcaseProjectPaths, n as OwnedShowcaseId, o as ShowcaseProvenance, r as SHOWCASE_ROOT, s as isShowcaseProjectId, t as BrandRecreationShowcaseId, u as showcaseProjects } from "../showcase-
|
|
1
|
+
import { a as ShowcaseProjectId, c as showcaseProject, d as showcaseSourcePath, i as ShowcaseProject, l as showcaseProjectPaths, n as OwnedShowcaseId, o as ShowcaseProvenance, r as SHOWCASE_ROOT, s as isShowcaseProjectId, t as BrandRecreationShowcaseId, u as showcaseProjects } from "../showcase-dvJMn-Lo.js";
|
|
2
2
|
export { BrandRecreationShowcaseId, OwnedShowcaseId, SHOWCASE_ROOT, ShowcaseProject, ShowcaseProjectId, ShowcaseProvenance, isShowcaseProjectId, showcaseProject, showcaseProjectPaths, showcaseProjects, showcaseSourcePath };
|
package/dist/presets.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as PresetMeta, c as presetCatalog, i as PresetId, n as EmailPresetVariable, o as PresetVariable, r as PresetCategory, s as RECOMMENDED_THEME, t as EmailPresetId } from "./catalog-
|
|
1
|
+
import { a as PresetMeta, c as presetCatalog, i as PresetId, n as EmailPresetVariable, o as PresetVariable, r as PresetCategory, s as RECOMMENDED_THEME, t as EmailPresetId } from "./catalog-Db0UcCTg.js";
|
|
2
2
|
export { EmailPresetId, EmailPresetVariable, PresetCategory, PresetId, PresetMeta, PresetVariable, RECOMMENDED_THEME, presetCatalog };
|
package/dist/printer.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { n as isObject } from "./guards-eV1qLbf2.js";
|
|
1
2
|
import { EmailNode, drainEmailDiagnostics } from "./email/jsx-runtime.js";
|
|
2
3
|
import { declarationValue, kebab, serializeEmailHtml } from "./email/html.js";
|
|
3
4
|
import { PREHEADER_ATTRIBUTE, preheaderNode } from "./email/components.js";
|
|
4
5
|
import { EmailCompileError, hasBlockingDiagnostic } from "./email/diagnostics.js";
|
|
5
6
|
import { snapshotStylesheets } from "./email/stylesheets.js";
|
|
6
7
|
import { deriveEmailText } from "./email/text.js";
|
|
7
|
-
import { Predicate } from "effect";
|
|
8
8
|
//#region src/email/css-values.ts
|
|
9
9
|
/** Expand `var(--x, fallback)` against the collected custom properties. */
|
|
10
10
|
const resolveVariables = (value, variables, depth = 0) => {
|
|
@@ -276,7 +276,7 @@ const compareRank = (left, right) => {
|
|
|
276
276
|
const outranks = (left, right) => compareRank(left, right) >= 0;
|
|
277
277
|
/** An authored `style` object becomes declarations with the same normalization the serializer uses. */
|
|
278
278
|
const inlineDeclarations = (style) => {
|
|
279
|
-
if (!
|
|
279
|
+
if (!isObject(style) || Array.isArray(style)) return [];
|
|
280
280
|
const output = [];
|
|
281
281
|
for (const [property, value] of Object.entries(style)) {
|
|
282
282
|
if (value === void 0 || value === null) continue;
|
|
@@ -344,7 +344,7 @@ const applyStylesheet = (root, sheet, options = {}) => {
|
|
|
344
344
|
const visitChildren = (children, ancestry, variables, writing) => {
|
|
345
345
|
const previous = [];
|
|
346
346
|
const visit = (nodes) => nodes.map((child) => {
|
|
347
|
-
if (child.
|
|
347
|
+
if (child.type === "Element") {
|
|
348
348
|
const result = applyTo(child, {
|
|
349
349
|
element: child,
|
|
350
350
|
parent: ancestry,
|
|
@@ -353,7 +353,7 @@ const applyStylesheet = (root, sheet, options = {}) => {
|
|
|
353
353
|
previous.push(child);
|
|
354
354
|
return result;
|
|
355
355
|
}
|
|
356
|
-
if (child.
|
|
356
|
+
if (child.type === "Fragment") return EmailNode.Fragment({ children: visit(child.children) });
|
|
357
357
|
return child;
|
|
358
358
|
});
|
|
359
359
|
return visit(children);
|
|
@@ -419,11 +419,11 @@ const applyStylesheet = (root, sheet, options = {}) => {
|
|
|
419
419
|
children: visitChildren(element.children, ancestry, variables, writing)
|
|
420
420
|
});
|
|
421
421
|
};
|
|
422
|
-
const tree = root.
|
|
422
|
+
const tree = root.type === "Element" ? applyTo(root, {
|
|
423
423
|
element: root,
|
|
424
424
|
parent: void 0,
|
|
425
425
|
previous: []
|
|
426
|
-
}, sheet.variables, horizontalWriting) : root.
|
|
426
|
+
}, sheet.variables, horizontalWriting) : root.type === "Fragment" ? EmailNode.Fragment({ children: visitChildren(root.children, void 0, sheet.variables, horizontalWriting) }) : root;
|
|
427
427
|
for (const [name, origins] of unmatched) diagnostics.push({
|
|
428
428
|
code: "unmatched-class",
|
|
429
429
|
severity: "warning",
|
|
@@ -457,7 +457,7 @@ const compileEmail = (node, options = {}) => {
|
|
|
457
457
|
};
|
|
458
458
|
/** The preview text already present in the tree, from `<Email preheader>`. */
|
|
459
459
|
const declaredPreheader = (node) => {
|
|
460
|
-
switch (node.
|
|
460
|
+
switch (node.type) {
|
|
461
461
|
case "Text":
|
|
462
462
|
case "Raw": return;
|
|
463
463
|
case "Fragment": return node.children.reduce((found, child) => found ?? declaredPreheader(child), void 0);
|
|
@@ -471,14 +471,14 @@ const declaredPreheader = (node) => {
|
|
|
471
471
|
/** Put the hidden preview block first inside `<body>`, or first overall when there is no shell. */
|
|
472
472
|
const withPreheader = (node, text) => {
|
|
473
473
|
const insert = (current) => {
|
|
474
|
-
if (current.
|
|
474
|
+
if (current.type === "Fragment") {
|
|
475
475
|
for (const [index, child] of current.children.entries()) {
|
|
476
476
|
const replaced = insert(child);
|
|
477
477
|
if (replaced !== void 0) return EmailNode.Fragment({ children: current.children.with(index, replaced) });
|
|
478
478
|
}
|
|
479
479
|
return;
|
|
480
480
|
}
|
|
481
|
-
if (current.
|
|
481
|
+
if (current.type !== "Element") return void 0;
|
|
482
482
|
if (current.tag === "body") return EmailNode.Element({
|
|
483
483
|
...current,
|
|
484
484
|
children: [preheaderNode(text), ...current.children]
|
|
@@ -496,14 +496,14 @@ const withPreheader = (node, text) => {
|
|
|
496
496
|
/** Put the retained rules in a `<style>` at the end of `<head>`. */
|
|
497
497
|
const withHeadCss = (node, css) => {
|
|
498
498
|
const insert = (current) => {
|
|
499
|
-
if (current.
|
|
499
|
+
if (current.type === "Fragment") {
|
|
500
500
|
for (const [index, child] of current.children.entries()) {
|
|
501
501
|
const replaced = insert(child);
|
|
502
502
|
if (replaced !== void 0) return EmailNode.Fragment({ children: current.children.with(index, replaced) });
|
|
503
503
|
}
|
|
504
504
|
return;
|
|
505
505
|
}
|
|
506
|
-
if (current.
|
|
506
|
+
if (current.type !== "Element") return void 0;
|
|
507
507
|
if (current.tag === "head") return EmailNode.Element({
|
|
508
508
|
...current,
|
|
509
509
|
children: [...current.children, EmailNode.Element({
|
|
@@ -589,4 +589,4 @@ const renderEmailWith = (stylesheet, template, data, options) => {
|
|
|
589
589
|
//#endregion
|
|
590
590
|
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
591
|
|
|
592
|
-
//# sourceMappingURL=render-
|
|
592
|
+
//# sourceMappingURL=render-T6IFPnP4.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { a as VariableKind, l as Variables } from "./variables-
|
|
5
|
-
import { a as JsxResult } from "./jsx-runtime-
|
|
6
|
-
import { Result } from "
|
|
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";
|
|
6
|
+
import { Result } from "better-result";
|
|
7
7
|
//#region src/render-template.d.ts
|
|
8
8
|
/**
|
|
9
9
|
* A template is a named function of the recording proxy returning the draft
|
|
@@ -39,7 +39,7 @@ interface RenderedTemplate {
|
|
|
39
39
|
* that is a programmer error in the user's build, so it propagates rather than
|
|
40
40
|
* becoming a diagnostic.
|
|
41
41
|
*/
|
|
42
|
-
declare const renderTemplate: <T extends Record<string, unknown>>(template: Template<T>) => Result
|
|
42
|
+
declare const renderTemplate: <T extends Record<string, unknown>>(template: Template<T>) => Result<RenderedTemplate, SmlParseError>;
|
|
43
43
|
//#endregion
|
|
44
44
|
export { RenderedTemplate, Template, TemplateVariable, renderTemplate };
|
|
45
45
|
//# sourceMappingURL=render-template.d.ts.map
|