@samva/markup 0.6.0 → 0.8.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 +94 -47
- package/README.md +1 -1
- package/dist/brand-DcoVkh_S.d.ts +88 -0
- package/dist/{catalog-60eaYC7b.d.ts → catalog-CKuOooB8.d.ts} +13 -15
- package/dist/{checks-DBweSIPN.js → checks-D73Xizbw.js} +414 -2
- package/dist/checks.js +1 -1
- package/dist/classes.d.ts +2 -3
- package/dist/compile-sms.d.ts +1 -1
- package/dist/compile-whatsapp.d.ts +1 -1
- package/dist/compiler.d.ts +62 -45
- package/dist/compiler.js +206 -863
- package/dist/components.d.ts +2 -2
- package/dist/{corpus-BjYMqOoY.d.ts → corpus-CPPfgAHN.d.ts} +14 -14
- package/dist/{css-COcFOT1y.d.ts → css-CS2jLID6.d.ts} +28 -2
- package/dist/email/assets.d.ts +40 -0
- package/dist/email/assets.js +63 -0
- package/dist/email/brand-footer.d.ts +34 -0
- package/dist/email/brand-footer.js +62 -0
- package/dist/email/brand.d.ts +2 -0
- package/dist/email/brand.js +148 -0
- package/dist/email/html.d.ts +2 -42
- package/dist/email/html.js +11 -0
- package/dist/email/render.d.ts +12 -5
- package/dist/email/render.js +2 -5
- package/dist/email/selection.d.ts +2 -91
- package/dist/email/stylesheets.d.ts +1 -1
- package/dist/email/stylesheets.js +3 -0
- package/dist/emit.js +2 -2
- package/dist/html-Bl9BAdqc.d.ts +42 -0
- package/dist/{ops-2aiiYO7m.js → ops-BvwqHl7V.js} +2 -2
- package/dist/ops.js +1 -1
- package/dist/{parser-CQcASEyy.d.ts → parser-t29cHLVL.d.ts} +2 -2
- package/dist/parser.d.ts +1 -1
- package/dist/parser.js +1 -2
- package/dist/registry-Dcp6QEK_.d.ts +73 -0
- package/dist/registry.d.ts +2 -42
- package/dist/{render-aaJBnsXK.js → render-vAv_4r9v.js} +174 -17
- package/dist/selection-CCArx9lU.d.ts +91 -0
- package/dist/{showcase-DGZAWn4Z.d.ts → showcase-egkusQBf.d.ts} +15 -56
- package/dist/{presets → starters}/category-mapping.d.ts +5 -5
- package/dist/{presets → starters}/category-mapping.js +5 -5
- package/dist/starters/corpus.d.ts +2 -0
- package/dist/{presets → starters}/corpus.js +15 -15
- package/dist/starters/library.d.ts +18 -0
- package/dist/starters/library.js +692 -0
- package/dist/{presets → starters}/public-gallery.d.ts +47 -47
- package/dist/{presets → starters}/public-gallery.js +92 -92
- package/dist/{presets → starters}/public-handoff.d.ts +14 -14
- package/dist/{presets → starters}/public-handoff.js +40 -40
- package/dist/{presets → starters}/public-preview-artifacts.d.ts +4 -4
- package/dist/{presets → starters}/public-preview-artifacts.js +15 -15
- package/dist/{presets → starters}/public-preview.d.ts +1 -1
- package/dist/{presets → starters}/public-preview.js +3 -3
- package/dist/starters/showcase.d.ts +2 -0
- package/dist/starters/showcase.js +335 -0
- package/dist/starters/sources.d.ts +45 -0
- package/dist/{presets → starters}/sources.js +1951 -272
- package/dist/starters/theme.d.ts +45 -0
- package/dist/starters/theme.js +77 -0
- package/dist/starters.d.ts +2 -0
- package/dist/{presets.js → starters.js} +4 -11
- package/dist/tailwind-BYq7Lo6u.js +727 -0
- package/dist/theme-css-hFqcPSar.js +587 -0
- package/dist/theme-css.d.ts +56 -15
- package/dist/theme-css.js +2 -509
- package/dist/tsx-source-instrumentation.d.ts +9 -0
- package/dist/tsx-source-instrumentation.js +20 -2
- package/dist/tsx-tracer.js +3 -3
- package/dist/unsubscribe-link-CoesnQDU.js +26 -0
- package/package.json +56 -44
- package/samva-brand.d.ts +14 -0
- package/dist/footer.d.ts +0 -66
- package/dist/footer.js +0 -93
- package/dist/presets/corpus.d.ts +0 -2
- package/dist/presets/showcase.d.ts +0 -2
- package/dist/presets/showcase.js +0 -627
- package/dist/presets/sources.d.ts +0 -38
- package/dist/presets.d.ts +0 -2
- package/dist/theme-6ApjjiBo.d.ts +0 -116
- package/dist/theme.d.ts +0 -2
- package/dist/theme.js +0 -118
- package/dist/tokens.d.ts +0 -6
- package/dist/tokens.js +0 -417
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { l as Channel } from "../ast-BrDtApwS.js";
|
|
2
|
-
import { r as
|
|
2
|
+
import { r as StarterCategory } from "../catalog-CKuOooB8.js";
|
|
3
3
|
import { TemplateCollectionId, TemplateUseCase } from "./public-gallery.js";
|
|
4
4
|
import { PublicTemplatePreview } from "./public-preview.js";
|
|
5
|
-
import {
|
|
5
|
+
import { StarterProject } from "./sources.js";
|
|
6
6
|
import { Result } from "better-result";
|
|
7
|
-
//#region
|
|
7
|
+
//#region starters/public-handoff.d.ts
|
|
8
8
|
/** The brand a clean-room recreation names, and what its email does. */
|
|
9
9
|
interface TemplateBrandRecreation {
|
|
10
10
|
readonly brand: string;
|
|
@@ -26,15 +26,15 @@ interface ApprovedPublicTemplateArtifact {
|
|
|
26
26
|
/** Stable ISO-8601 timestamp supplied by the owner. */
|
|
27
27
|
readonly approvedAt: string;
|
|
28
28
|
};
|
|
29
|
-
readonly
|
|
29
|
+
readonly starter: {
|
|
30
30
|
readonly id: string;
|
|
31
31
|
readonly channel: Channel;
|
|
32
|
-
readonly category:
|
|
32
|
+
readonly category: StarterCategory;
|
|
33
33
|
readonly name: string;
|
|
34
34
|
readonly description: string;
|
|
35
35
|
readonly variables: ReadonlyArray<string>;
|
|
36
36
|
readonly source: string;
|
|
37
|
-
readonly project?:
|
|
37
|
+
readonly project?: StarterProject;
|
|
38
38
|
};
|
|
39
39
|
readonly gallery: {
|
|
40
40
|
readonly slug: string;
|
|
@@ -61,7 +61,7 @@ interface ApprovedPublicTemplateArtifact {
|
|
|
61
61
|
*/
|
|
62
62
|
interface TemplateReferencePacket {
|
|
63
63
|
readonly version: 1;
|
|
64
|
-
readonly
|
|
64
|
+
readonly starter: ApprovedPublicTemplateArtifact["starter"];
|
|
65
65
|
readonly gallery: ApprovedPublicTemplateArtifact["gallery"] & {
|
|
66
66
|
readonly path: `/templates/${string}`;
|
|
67
67
|
};
|
|
@@ -70,9 +70,9 @@ interface TemplateReferencePacket {
|
|
|
70
70
|
readonly provenance: TemplateReferenceProvenance;
|
|
71
71
|
}
|
|
72
72
|
interface ValidatedPublicTemplateArtifact {
|
|
73
|
-
readonly
|
|
73
|
+
readonly starter: Omit<ApprovedPublicTemplateArtifact["starter"], "source" | "project">;
|
|
74
74
|
readonly source: string;
|
|
75
|
-
readonly project?:
|
|
75
|
+
readonly project?: StarterProject;
|
|
76
76
|
readonly gallery: ApprovedPublicTemplateArtifact["gallery"] & {
|
|
77
77
|
readonly path: `/templates/${string}`;
|
|
78
78
|
};
|
|
@@ -97,10 +97,10 @@ declare const PUBLIC_TEMPLATE_PROJECT_FILE_MAX_BYTES: number;
|
|
|
97
97
|
declare const PUBLIC_TEMPLATE_PROJECT_MAX_FILES = 64;
|
|
98
98
|
declare const isSafePublicTemplateProjectPath: (path: string) => boolean;
|
|
99
99
|
/** Reject traversal, collisions, malformed base64 and oversized authored projects. */
|
|
100
|
-
declare const isSafePublicTemplateProject: (project:
|
|
100
|
+
declare const isSafePublicTemplateProject: (project: StarterProject) => boolean;
|
|
101
101
|
/** Digest the complete authored graph independently of caller file ordering. */
|
|
102
|
-
declare const publicTemplateProjectDigest: (project: Pick<
|
|
103
|
-
declare const isValidTemplateBrandRecreation: (brandRecreation: TemplateBrandRecreation | undefined, project:
|
|
102
|
+
declare const publicTemplateProjectDigest: (project: Pick<StarterProject, "entryPath" | "files">) => Promise<string>;
|
|
103
|
+
declare const isValidTemplateBrandRecreation: (brandRecreation: TemplateBrandRecreation | undefined, project: StarterProject | undefined) => boolean;
|
|
104
104
|
/** Static syntax inventory; loops, branches and component expansion are not evaluated. */
|
|
105
105
|
interface PublicTemplateAuthoredStructure {
|
|
106
106
|
readonly basis: "authored-jsx";
|
|
@@ -133,7 +133,7 @@ declare const isSafePublicTemplateAsset: (value: string) => boolean;
|
|
|
133
133
|
declare const toTemplateReferencePacket: (artifact: ApprovedPublicTemplateArtifact) => TemplateReferencePacket;
|
|
134
134
|
type TemplateReferenceProjection = {
|
|
135
135
|
readonly kind: "source";
|
|
136
|
-
readonly relativePath: "
|
|
136
|
+
readonly relativePath: "starter.tsx";
|
|
137
137
|
readonly contents: string;
|
|
138
138
|
} | {
|
|
139
139
|
readonly kind: "project-file";
|
|
@@ -155,7 +155,7 @@ declare const emitTemplateReferencePacket: (packet: TemplateReferencePacket) =>
|
|
|
155
155
|
* verifies schema, fixtures and rendered content before writing projections.
|
|
156
156
|
* Validates explicitly supplied, owner-approved artifacts without filesystem,
|
|
157
157
|
* network, persistence, or discovery. Successful output is a projection for
|
|
158
|
-
* the existing
|
|
158
|
+
* the existing starter, public-gallery, preview, and editorial contracts; this
|
|
159
159
|
* function never registers or publishes it.
|
|
160
160
|
*/
|
|
161
161
|
declare const validatePublicTemplateHandoff: (artifacts: ReadonlyArray<ApprovedPublicTemplateArtifact>) => Result<ReadonlyArray<ValidatedPublicTemplateArtifact>, ReadonlyArray<PublicHandoffIssue>>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as isObject } from "../guards-eV1qLbf2.js";
|
|
2
2
|
import { EMAIL_ELEMENTS } from "../email/elements.js";
|
|
3
|
-
import {
|
|
3
|
+
import { starterCatalog } from "../starters.js";
|
|
4
4
|
import { publicTemplates, templateCollections } from "./public-gallery.js";
|
|
5
5
|
import { Result } from "better-result";
|
|
6
6
|
import { parse } from "@babel/parser";
|
|
7
|
-
//#region
|
|
7
|
+
//#region starters/public-handoff.ts
|
|
8
8
|
const SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
9
9
|
const ISO_TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/;
|
|
10
10
|
const MAX_HTTPS_ASSET_LENGTH = 2048;
|
|
@@ -206,7 +206,7 @@ const isSafePublicTemplateAsset = (value) => {
|
|
|
206
206
|
/** Normalizes one approved handoff for gallery and future agent consumers. */
|
|
207
207
|
const toTemplateReferencePacket = (artifact) => ({
|
|
208
208
|
version: 1,
|
|
209
|
-
|
|
209
|
+
starter: artifact.starter,
|
|
210
210
|
gallery: {
|
|
211
211
|
...artifact.gallery,
|
|
212
212
|
path: `/templates/${artifact.gallery.slug}`
|
|
@@ -225,8 +225,8 @@ const jsonProjection = (kind, value) => ({
|
|
|
225
225
|
* owns no checked-in destination files; callers choose an explicit output dir.
|
|
226
226
|
*/
|
|
227
227
|
const emitTemplateReferencePacket = (packet) => {
|
|
228
|
-
const project = packet.
|
|
229
|
-
if (project !== void 0 && (!isSafePublicTemplateProject(project) || project.files.find((file) => file.path === project.entryPath)?.content !== packet.
|
|
228
|
+
const project = packet.starter.project;
|
|
229
|
+
if (project !== void 0 && (!isSafePublicTemplateProject(project) || project.files.find((file) => file.path === project.entryPath)?.content !== packet.starter.source)) throw new Error("Invalid public template project");
|
|
230
230
|
if (packet.provenance.source === "brand-recreation" && !isValidTemplateBrandRecreation(packet.provenance.brandRecreation, project)) throw new Error("Invalid public template brand recreation attribution");
|
|
231
231
|
return [
|
|
232
232
|
...project === void 0 ? [] : [jsonProjection("project", {
|
|
@@ -240,19 +240,19 @@ const emitTemplateReferencePacket = (packet) => {
|
|
|
240
240
|
}))],
|
|
241
241
|
{
|
|
242
242
|
kind: "source",
|
|
243
|
-
relativePath: "
|
|
244
|
-
contents: packet.
|
|
243
|
+
relativePath: "starter.tsx",
|
|
244
|
+
contents: packet.starter.source
|
|
245
245
|
},
|
|
246
246
|
jsonProjection("catalog", {
|
|
247
|
-
id: packet.
|
|
248
|
-
channel: packet.
|
|
249
|
-
category: packet.
|
|
250
|
-
name: packet.
|
|
251
|
-
description: packet.
|
|
252
|
-
variables: packet.
|
|
247
|
+
id: packet.starter.id,
|
|
248
|
+
channel: packet.starter.channel,
|
|
249
|
+
category: packet.starter.category,
|
|
250
|
+
name: packet.starter.name,
|
|
251
|
+
description: packet.starter.description,
|
|
252
|
+
variables: packet.starter.variables
|
|
253
253
|
}),
|
|
254
254
|
jsonProjection("gallery", {
|
|
255
|
-
|
|
255
|
+
starterId: packet.starter.id,
|
|
256
256
|
...packet.gallery,
|
|
257
257
|
provenance: packet.provenance
|
|
258
258
|
}),
|
|
@@ -271,35 +271,35 @@ const emitTemplateReferencePacket = (packet) => {
|
|
|
271
271
|
* verifies schema, fixtures and rendered content before writing projections.
|
|
272
272
|
* Validates explicitly supplied, owner-approved artifacts without filesystem,
|
|
273
273
|
* network, persistence, or discovery. Successful output is a projection for
|
|
274
|
-
* the existing
|
|
274
|
+
* the existing starter, public-gallery, preview, and editorial contracts; this
|
|
275
275
|
* function never registers or publishes it.
|
|
276
276
|
*/
|
|
277
277
|
const validatePublicTemplateHandoff = (artifacts) => {
|
|
278
278
|
const issues = [];
|
|
279
|
-
const existingIds = new Set(
|
|
279
|
+
const existingIds = new Set(starterCatalog.map((starter) => starter.id));
|
|
280
280
|
const existingSlugs = new Set(publicTemplates.map((template) => template.slug));
|
|
281
281
|
const suppliedIds = /* @__PURE__ */ new Set();
|
|
282
282
|
const suppliedSlugs = /* @__PURE__ */ new Set();
|
|
283
|
-
const allKnownIds = /* @__PURE__ */ new Set([...publicTemplates.map((template) => template.
|
|
283
|
+
const allKnownIds = /* @__PURE__ */ new Set([...publicTemplates.map((template) => template.starterId), ...artifacts.map((artifact) => artifact.starter.id)]);
|
|
284
284
|
const knownCollections = new Set(templateCollections.map((collection) => collection.id));
|
|
285
285
|
for (const artifact of artifacts) {
|
|
286
|
-
const id = artifact.
|
|
286
|
+
const id = artifact.starter.id;
|
|
287
287
|
if (artifact.approval.state !== "approved" || !nonEmpty(artifact.approval.approvedBy) || !ISO_TIMESTAMP.test(artifact.approval.approvedAt)) issues.push(issue(id, "approval", "owner approval and an ISO-8601 approval timestamp are required"));
|
|
288
288
|
if (artifact.provenance === void 0 || !isTemplateReferenceProvenanceSource(artifact.provenance.source) || !nonEmpty(artifact.provenance.referenceId) || !ISO_TIMESTAMP.test(artifact.provenance.recordedAt)) issues.push(issue(id, "provenance", "provenance requires a supported source, identifier, and ISO-8601 timestamp"));
|
|
289
|
-
if (!SLUG.test(id) || !SLUG.test(artifact.gallery.slug)) issues.push(issue(id, "identity", "
|
|
290
|
-
if (existingIds.has(id) || suppliedIds.has(id)) issues.push(issue(id, "duplicate-id", `
|
|
289
|
+
if (!SLUG.test(id) || !SLUG.test(artifact.gallery.slug)) issues.push(issue(id, "identity", "starter id and canonical slug must be lowercase kebab-case"));
|
|
290
|
+
if (existingIds.has(id) || suppliedIds.has(id)) issues.push(issue(id, "duplicate-id", `starter id "${id}" is already present`));
|
|
291
291
|
if (existingSlugs.has(artifact.gallery.slug) || suppliedSlugs.has(artifact.gallery.slug)) issues.push(issue(id, "duplicate-slug", `canonical slug "${artifact.gallery.slug}" is already present`));
|
|
292
292
|
suppliedIds.add(id);
|
|
293
293
|
suppliedSlugs.add(artifact.gallery.slug);
|
|
294
|
-
const project = artifact.
|
|
295
|
-
if (project !== void 0 && (!isSafePublicTemplateProject(project) || project.files.find((file) => file.path === project.entryPath)?.content !== artifact.
|
|
294
|
+
const project = artifact.starter.project;
|
|
295
|
+
if (project !== void 0 && (!isSafePublicTemplateProject(project) || project.files.find((file) => file.path === project.entryPath)?.content !== artifact.starter.source)) issues.push(issue(id, "source", "project must contain safe bounded unique files and the matching UTF-8 entry source"));
|
|
296
296
|
if (artifact.provenance?.source === "brand-recreation" && !isValidTemplateBrandRecreation(artifact.provenance.brandRecreation, project)) issues.push(issue(id, "provenance", "brand recreations require a complete project, a referenced brand, and its email subject"));
|
|
297
|
-
if (parsePublicTemplateSource(artifact.
|
|
298
|
-
if (artifact.
|
|
299
|
-
if (new Set(artifact.
|
|
300
|
-
const unsupportedFontTokens = unsupportedPublicTemplateFontTokens(artifact.
|
|
297
|
+
if (parsePublicTemplateSource(artifact.starter.source) === void 0) issues.push(issue(id, "source", "source must be a bounded TSX module with a default export; execution is verified by the importer"));
|
|
298
|
+
if (artifact.starter.channel !== "email") issues.push(issue(id, "channel", "public template source must be an executable email"));
|
|
299
|
+
if (new Set(artifact.starter.variables).size !== artifact.starter.variables.length || artifact.starter.variables.some((value) => !nonEmpty(value))) issues.push(issue(id, "variables", "declared input fields must be non-empty and unique"));
|
|
300
|
+
const unsupportedFontTokens = unsupportedPublicTemplateFontTokens(artifact.starter.source);
|
|
301
301
|
if (unsupportedFontTokens.length > 0) issues.push(issue(id, "font-token", `unsupported public font token: ${unsupportedFontTokens.join(", ")}`));
|
|
302
|
-
const declaredVariables = new Set(artifact.
|
|
302
|
+
const declaredVariables = new Set(artifact.starter.variables);
|
|
303
303
|
const undeclaredSample = Object.keys(artifact.preview.sampleData).filter((variable) => !declaredVariables.has(variable));
|
|
304
304
|
if (undeclaredSample.length > 0) issues.push(issue(id, "sample-data", `sample data supplies undeclared variables: ${sortedUnique(undeclaredSample).join(", ")}`));
|
|
305
305
|
if (Object.values(artifact.preview.sampleData).some((value) => !nonEmptySample(value))) issues.push(issue(id, "sample-data", "sample data values must be non-empty"));
|
|
@@ -307,13 +307,13 @@ const validatePublicTemplateHandoff = (artifacts) => {
|
|
|
307
307
|
if (new Set(assetVariables).size !== assetVariables.length) issues.push(issue(id, "assets", "asset variable references must be unique"));
|
|
308
308
|
for (const asset of artifact.preview.assets) {
|
|
309
309
|
const value = artifact.preview.sampleData[asset.variable];
|
|
310
|
-
if (!artifact.
|
|
310
|
+
if (!artifact.starter.variables.includes(asset.variable)) issues.push(issue(id, "assets", `asset "${asset.variable}" is not a declared starter variable`));
|
|
311
311
|
if (typeof value !== "string" || !isSafePublicTemplateAsset(value)) issues.push(issue(id, "assets", `asset "${asset.variable}" must reference a bounded HTTPS, /templates/assets, or data:image sample URL`));
|
|
312
312
|
}
|
|
313
313
|
const metadata = artifact.publicMetadata;
|
|
314
314
|
const metadataStrings = [
|
|
315
|
-
artifact.
|
|
316
|
-
artifact.
|
|
315
|
+
artifact.starter.name,
|
|
316
|
+
artifact.starter.description,
|
|
317
317
|
artifact.preview.subject,
|
|
318
318
|
artifact.preview.preheader,
|
|
319
319
|
metadata.cardTitle,
|
|
@@ -324,7 +324,7 @@ const validatePublicTemplateHandoff = (artifacts) => {
|
|
|
324
324
|
...Object.values(metadata.variableDescriptions)
|
|
325
325
|
];
|
|
326
326
|
if (metadata.guidance.length === 0 || metadataStrings.some((value) => !nonEmpty(value))) issues.push(issue(id, "public-metadata", "public metadata fields must be non-empty"));
|
|
327
|
-
if (!sameStrings(Object.keys(metadata.variableDescriptions), artifact.
|
|
327
|
+
if (!sameStrings(Object.keys(metadata.variableDescriptions), artifact.starter.variables)) issues.push(issue(id, "public-metadata", "variable descriptions must cover every declared variable exactly"));
|
|
328
328
|
if (new Set(artifact.gallery.collections).size !== artifact.gallery.collections.length) issues.push(issue(id, "reference", "collection references must be unique"));
|
|
329
329
|
for (const collectionId of artifact.gallery.collections) if (!knownCollections.has(collectionId)) issues.push(issue(id, "reference", `collection "${collectionId}" is invalid`));
|
|
330
330
|
if (new Set(artifact.gallery.relatedTemplates).size !== artifact.gallery.relatedTemplates.length) issues.push(issue(id, "reference", "related template references must be unique"));
|
|
@@ -338,16 +338,16 @@ const validatePublicTemplateHandoff = (artifacts) => {
|
|
|
338
338
|
...artifact.approval,
|
|
339
339
|
state: "approved"
|
|
340
340
|
},
|
|
341
|
-
|
|
342
|
-
id: artifact.
|
|
343
|
-
channel: artifact.
|
|
344
|
-
category: artifact.
|
|
345
|
-
name: artifact.
|
|
346
|
-
description: artifact.
|
|
347
|
-
variables: artifact.
|
|
341
|
+
starter: {
|
|
342
|
+
id: artifact.starter.id,
|
|
343
|
+
channel: artifact.starter.channel,
|
|
344
|
+
category: artifact.starter.category,
|
|
345
|
+
name: artifact.starter.name,
|
|
346
|
+
description: artifact.starter.description,
|
|
347
|
+
variables: artifact.starter.variables
|
|
348
348
|
},
|
|
349
|
-
source: artifact.
|
|
350
|
-
...artifact.
|
|
349
|
+
source: artifact.starter.source,
|
|
350
|
+
...artifact.starter.project === void 0 ? {} : { project: artifact.starter.project },
|
|
351
351
|
gallery: reference.gallery,
|
|
352
352
|
preview: artifact.preview,
|
|
353
353
|
publicMetadata: artifact.publicMetadata,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as
|
|
1
|
+
import { t as EmailStarterId } from "../catalog-CKuOooB8.js";
|
|
2
2
|
import { PublicTemplate } from "./public-gallery.js";
|
|
3
3
|
import { PreviewQuality } from "./public-preview.js";
|
|
4
4
|
import { Result } from "better-result";
|
|
5
|
-
//#region
|
|
5
|
+
//#region starters/public-preview-artifacts.d.ts
|
|
6
6
|
type PreviewSurface = "card" | "detail" | "og";
|
|
7
7
|
type PreviewViewport = "desktop" | "mobile";
|
|
8
8
|
type PreviewColorScheme = "light" | "dark";
|
|
@@ -16,7 +16,7 @@ interface PublicTemplateRenderInput {
|
|
|
16
16
|
readonly html: string;
|
|
17
17
|
}
|
|
18
18
|
interface PublicTemplatePreviewArtifact {
|
|
19
|
-
readonly
|
|
19
|
+
readonly starterId: EmailStarterId;
|
|
20
20
|
readonly slug: string;
|
|
21
21
|
readonly subject: string;
|
|
22
22
|
readonly preheader: string;
|
|
@@ -29,7 +29,7 @@ interface PublicTemplatePreviewArtifact {
|
|
|
29
29
|
readonly renders: ReadonlyArray<PublicTemplateRenderInput>;
|
|
30
30
|
}
|
|
31
31
|
interface PreviewArtifactBuildIssue {
|
|
32
|
-
readonly
|
|
32
|
+
readonly starterId: EmailStarterId;
|
|
33
33
|
readonly message: string;
|
|
34
34
|
}
|
|
35
35
|
/** Build one static preview artifact without loading the editor runtime or performing I/O. */
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { starterCatalog } from "../starters.js";
|
|
2
2
|
import { registerPublicCorpusEntry } from "./corpus.js";
|
|
3
3
|
import { publicTemplates } from "./public-gallery.js";
|
|
4
|
-
import {
|
|
4
|
+
import { starterEmailAssets, starterEmailFixtures, starterModuleSource } from "./sources.js";
|
|
5
5
|
import { publicTemplatePreviews } from "./public-preview.js";
|
|
6
6
|
import { Result } from "better-result";
|
|
7
|
-
//#region
|
|
7
|
+
//#region starters/public-preview-artifacts.ts
|
|
8
8
|
const renderFrames = [
|
|
9
9
|
{
|
|
10
10
|
surface: "card",
|
|
@@ -46,34 +46,34 @@ const renderInputs = (slug, html) => renderFrames.flatMap((frame) => ["light", "
|
|
|
46
46
|
/** Build one static preview artifact without loading the editor runtime or performing I/O. */
|
|
47
47
|
const buildPublicTemplatePreviewArtifact = (template) => {
|
|
48
48
|
const registration = registerPublicCorpusEntry({
|
|
49
|
-
id: template.
|
|
49
|
+
id: template.starterId,
|
|
50
50
|
corpus: template.corpus,
|
|
51
51
|
facets: template.facets
|
|
52
52
|
});
|
|
53
53
|
if (Result.isError(registration)) return Result.err({
|
|
54
|
-
|
|
54
|
+
starterId: template.starterId,
|
|
55
55
|
message: `public corpus registration failed: ${registration.error.message}`
|
|
56
56
|
});
|
|
57
|
-
const source =
|
|
58
|
-
const fixture =
|
|
59
|
-
const
|
|
60
|
-
const preview = publicTemplatePreviews[template.
|
|
61
|
-
if (source === void 0 ||
|
|
62
|
-
|
|
63
|
-
message: "canonical
|
|
57
|
+
const source = starterModuleSource(template.starterId);
|
|
58
|
+
const fixture = starterEmailFixtures[template.starterId]?.default;
|
|
59
|
+
const starter = starterCatalog.find((entry) => entry.id === template.starterId);
|
|
60
|
+
const preview = publicTemplatePreviews[template.starterId];
|
|
61
|
+
if (source === void 0 || starter === void 0 || fixture === void 0) return Result.err({
|
|
62
|
+
starterId: template.starterId,
|
|
63
|
+
message: "canonical starter source is missing"
|
|
64
64
|
});
|
|
65
65
|
const sampleData = fixture.input;
|
|
66
|
-
const assets = new Set(
|
|
66
|
+
const assets = new Set(starterEmailAssets[template.starterId]);
|
|
67
67
|
for (const asset of preview.assets) {
|
|
68
68
|
const value = sampleData[asset.variable];
|
|
69
69
|
if (typeof value !== "string") return Result.err({
|
|
70
|
-
|
|
70
|
+
starterId: template.starterId,
|
|
71
71
|
message: `sample data is missing a string asset: ${asset.variable}`
|
|
72
72
|
});
|
|
73
73
|
assets.add(value);
|
|
74
74
|
}
|
|
75
75
|
return Result.ok({
|
|
76
|
-
|
|
76
|
+
starterId: template.starterId,
|
|
77
77
|
slug: template.slug,
|
|
78
78
|
subject: fixture.subject,
|
|
79
79
|
preheader: fixture.preheader,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region
|
|
1
|
+
//#region starters/public-preview.d.ts
|
|
2
2
|
type PreviewQuality = "ready" | "asset-free";
|
|
3
3
|
/** A declared fixture value: JSON, so a template can take a list of stories as well as a string. */
|
|
4
4
|
type PreviewSampleValue = string | number | boolean | null | ReadonlyArray<PreviewSampleValue> | {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
//#region
|
|
1
|
+
import { starterEmailFixtures } from "./sources.js";
|
|
2
|
+
//#region starters/public-preview.ts
|
|
3
3
|
const preview = (id, quality, assets) => {
|
|
4
|
-
const fixture =
|
|
4
|
+
const fixture = starterEmailFixtures[id]?.default;
|
|
5
5
|
if (fixture === void 0) throw new Error(`Missing generated gallery fixture: ${id}`);
|
|
6
6
|
return {
|
|
7
7
|
subject: fixture.subject,
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as ShowcaseProjectId, c as showcaseProject, i as ShowcaseProject, l as showcaseProjects, n as OwnedShowcaseId, o as ShowcaseProvenance, r as SHOWCASE_ROOT, s as isShowcaseProjectId, t as BrandRecreationShowcaseId, u as showcaseSourcePath } from "../showcase-egkusQBf.js";
|
|
2
|
+
export { BrandRecreationShowcaseId, OwnedShowcaseId, SHOWCASE_ROOT, ShowcaseProject, ShowcaseProjectId, ShowcaseProvenance, isShowcaseProjectId, showcaseProject, showcaseProjects, showcaseSourcePath };
|