@samva/markup 0.1.1 → 0.2.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 +25 -5
- package/README.md +92 -26
- package/dist/{ast-DAhnAvQN.d.ts → ast-63I-VLQx.d.ts} +15 -2
- package/dist/ast.d.ts +2 -2
- package/dist/ast.js +15 -2
- package/dist/{checks-CW0nFj5n.js → checks-DXuERO4B.js} +37 -3
- package/dist/checks.d.ts +8 -1
- package/dist/checks.js +2 -2
- package/dist/compile-sms.d.ts +2 -2
- package/dist/compile-whatsapp.d.ts +2 -2
- package/dist/compile.d.ts +9 -84
- package/dist/compile.js +11 -920
- package/dist/compiler.d.ts +301 -0
- package/dist/compiler.js +1389 -0
- package/dist/components.d.ts +4 -4
- package/dist/conditionals.js +1 -1
- package/dist/corpus-Dz5irJ9x.d.ts +161 -0
- package/dist/diagnostics-Djd9ckLg.d.ts +90 -0
- package/dist/diagnostics.js +6 -3
- package/dist/elements-DtwKlFVH.d.ts +820 -0
- package/dist/email/components.d.ts +119 -0
- package/dist/email/components.js +207 -0
- package/dist/email/diagnostics.d.ts +2 -0
- package/dist/email/diagnostics.js +56 -0
- package/dist/email/elements.d.ts +2 -0
- package/dist/email/elements.js +299 -0
- package/dist/email/html.d.ts +42 -0
- package/dist/email/html.js +266 -0
- package/dist/email/jsx-dev-runtime.d.ts +26 -0
- package/dist/email/jsx-dev-runtime.js +12 -0
- package/dist/email/jsx-runtime.d.ts +2 -0
- package/dist/email/jsx-runtime.js +60 -0
- package/dist/email/render.d.ts +36 -0
- package/dist/email/render.js +6 -0
- package/dist/email/selection.d.ts +102 -0
- package/dist/email/selection.js +143 -0
- package/dist/email/source-edit.d.ts +67 -0
- package/dist/email/source-edit.js +185 -0
- package/dist/email/stylesheets.d.ts +2 -0
- package/dist/email/stylesheets.js +43 -0
- package/dist/email/text.d.ts +7 -0
- package/dist/email/text.js +92 -0
- package/dist/emit.d.ts +13 -12
- package/dist/emit.js +63 -63
- package/dist/input-schema-BIfzI63B.d.ts +23 -0
- package/dist/input-schema.d.ts +2 -0
- package/dist/input-schema.js +170 -0
- package/dist/jsx-dev-runtime.d.ts +4 -3
- package/dist/jsx-dev-runtime.js +9 -1
- package/dist/{jsx-runtime-fSxcvlx4.d.ts → jsx-runtime-C5k_Zq0A.d.ts} +4 -4
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/jsx-runtime.js +20 -1
- package/dist/model.d.ts +1 -1
- package/dist/ops.d.ts +1 -1
- package/dist/ops.js +2 -2
- package/dist/{parser-yzjUOGhc.d.ts → parser-CGBS73Gz.d.ts} +12 -3
- package/dist/parser.d.ts +2 -2
- package/dist/parser.js +48 -9
- package/dist/predicate-CvkzT-a2.js +539 -0
- package/dist/{predicate-DTtVtLK7.d.ts → predicate-G2SeSvoN.d.ts} +9 -2
- package/dist/predicate.d.ts +2 -2
- package/dist/predicate.js +2 -417
- package/dist/presets/corpus.d.ts +2 -0
- package/dist/presets/corpus.js +186 -0
- package/dist/presets/public-gallery.d.ts +241 -459
- package/dist/presets/public-gallery.js +305 -5
- package/dist/presets/public-handoff.d.ts +75 -3
- package/dist/presets/public-handoff.js +220 -37
- package/dist/presets/public-preview-artifacts.js +20 -26
- package/dist/presets/public-preview.d.ts +40 -1152
- package/dist/presets/public-preview.js +388 -1152
- package/dist/presets/sources.d.ts +17 -4
- package/dist/presets/sources.js +1212 -43
- package/dist/presets.d.ts +2 -2
- package/dist/printer.d.ts +1 -1
- package/dist/render-Cddsy_XF.js +585 -0
- package/dist/render-template.d.ts +6 -3
- package/dist/render-template.js +4 -2
- package/dist/source-locations-BCJQnIfU.d.ts +89 -0
- package/dist/source-locations.d.ts +2 -0
- package/dist/source-locations.js +125 -0
- package/dist/stylesheets-oDRAnYA3.d.ts +94 -0
- package/dist/template-Dy5yOPyp.d.ts +60 -0
- package/dist/template.d.ts +2 -0
- package/dist/template.js +37 -0
- package/dist/tsx-source-instrumentation.d.ts +23 -0
- package/dist/tsx-source-instrumentation.js +97 -0
- package/dist/tsx-tracer.d.ts +116 -0
- package/dist/tsx-tracer.js +985 -0
- package/dist/{variables-3NGLpNTB.d.ts → variables-if1VrV34.d.ts} +2 -2
- package/dist/variables.d.ts +1 -1
- package/dist/variables.js +1 -1
- package/generated/sml-agent-contract.json +574 -782
- package/generated/sml-email-agent-contract.json +502 -677
- package/generated/sml-email-language-reference.md +94 -160
- package/generated/sml-language-reference.md +195 -220
- package/package.json +111 -8
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { E as SmlNode, m as ElementNode } from "./ast-63I-VLQx.js";
|
|
2
|
+
import { Schema } from "effect";
|
|
3
|
+
//#region src/source-locations.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The source payload emitted by the JSX development transform. The transform
|
|
6
|
+
* may omit any field for synthetic calls; only a complete payload can identify
|
|
7
|
+
* a source origin safely.
|
|
8
|
+
*/
|
|
9
|
+
interface JsxSource {
|
|
10
|
+
readonly fileName?: string | undefined;
|
|
11
|
+
readonly lineNumber?: number | undefined;
|
|
12
|
+
readonly columnNumber?: number | undefined;
|
|
13
|
+
}
|
|
14
|
+
/** A complete, normalized source origin for a JSX element. */
|
|
15
|
+
interface JsxSourceLocation {
|
|
16
|
+
readonly fileName: string;
|
|
17
|
+
readonly lineNumber: number;
|
|
18
|
+
readonly columnNumber: number;
|
|
19
|
+
}
|
|
20
|
+
/** JSON-safe source location shape shared by preview and editor contracts. */
|
|
21
|
+
declare const JsxSourceLocation: Schema.Struct<{
|
|
22
|
+
readonly fileName: Schema.String;
|
|
23
|
+
readonly lineNumber: Schema.Int;
|
|
24
|
+
readonly columnNumber: Schema.Int;
|
|
25
|
+
}>;
|
|
26
|
+
/** Reasons a preview cannot safely expose an authored source map. */
|
|
27
|
+
declare const SourceLocationUnavailableReason: Schema.Literals<readonly ["no-source-metadata", "structure-mismatch", "duplicate-source-origin", "render-failed", "stale-preview"]>;
|
|
28
|
+
/**
|
|
29
|
+
* Runtime-only carrier for JSX source metadata. It is global so separately
|
|
30
|
+
* bundled `jsx-dev-runtime` and `render-template` entries still agree on the
|
|
31
|
+
* sidecar key, and it is a Symbol so it cannot enter SML, HTML, or JSON.
|
|
32
|
+
*/
|
|
33
|
+
declare const JSX_SOURCE_LOCATION: unique symbol;
|
|
34
|
+
/** Internal JSX prop used only by an editor preview source transform. */
|
|
35
|
+
declare const JSX_SOURCE_LOCATION_PROP: "__samva_source_location";
|
|
36
|
+
/**
|
|
37
|
+
* A source map is useful only when it is trustworthy. Production `jsx`/`jsxs`
|
|
38
|
+
* currently provide no source metadata, so that path reports a typed absence
|
|
39
|
+
* rather than guessing from output order.
|
|
40
|
+
*/
|
|
41
|
+
type SourceLocationUnavailableReason = typeof SourceLocationUnavailableReason.Type;
|
|
42
|
+
type UnboundTemplateSourceLocations = {
|
|
43
|
+
readonly kind: "available";
|
|
44
|
+
/** Parsed SML node id → the JSX origin that produced that element. */
|
|
45
|
+
readonly byNodeId: Readonly<Record<string, JsxSourceLocation>>;
|
|
46
|
+
} | {
|
|
47
|
+
readonly kind: "unavailable";
|
|
48
|
+
readonly reason: SourceLocationUnavailableReason;
|
|
49
|
+
};
|
|
50
|
+
/** Revision-fenced source map exposed by a mutable workspace preview. */
|
|
51
|
+
type TemplateSourceLocations = {
|
|
52
|
+
readonly kind: "available";
|
|
53
|
+
readonly revision: string;
|
|
54
|
+
/** Parsed SML node id → the JSX origin that produced that element. */
|
|
55
|
+
readonly byNodeId: Readonly<Record<string, JsxSourceLocation>>;
|
|
56
|
+
} | {
|
|
57
|
+
readonly kind: "unavailable";
|
|
58
|
+
readonly reason: SourceLocationUnavailableReason;
|
|
59
|
+
};
|
|
60
|
+
/** JSON-safe schema for a parsed-node-id → JSX-origin map. */
|
|
61
|
+
declare const TemplateSourceLocationsSchema: Schema.Union<readonly [Schema.Struct<{
|
|
62
|
+
readonly kind: Schema.Literal<"available">;
|
|
63
|
+
readonly revision: Schema.String;
|
|
64
|
+
readonly byNodeId: Schema.$Record<Schema.String, Schema.Struct<{
|
|
65
|
+
readonly fileName: Schema.String;
|
|
66
|
+
readonly lineNumber: Schema.Int;
|
|
67
|
+
readonly columnNumber: Schema.Int;
|
|
68
|
+
}>>;
|
|
69
|
+
}>, Schema.Struct<{
|
|
70
|
+
readonly kind: Schema.Literal<"unavailable">;
|
|
71
|
+
readonly reason: Schema.Literals<readonly ["no-source-metadata", "structure-mismatch", "duplicate-source-origin", "render-failed", "stale-preview"]>;
|
|
72
|
+
}>]>;
|
|
73
|
+
/** Normalize the optional payload accepted by `jsxDEV`. */
|
|
74
|
+
declare const completeJsxSourceLocation: (source: JsxSource | null | undefined) => JsxSourceLocation | undefined;
|
|
75
|
+
/** Attach a source origin without changing the serialized draft shape. */
|
|
76
|
+
declare const attachJsxSourceLocation: (node: ElementNode, source: JsxSourceLocation) => void;
|
|
77
|
+
/** Read the ephemeral origin, if this draft element has one. */
|
|
78
|
+
declare const jsxSourceLocationOf: (node: SmlNode) => JsxSourceLocation | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* Pair a draft tree with its parsed SML tree by element preorder. Text nodes
|
|
81
|
+
* are intentionally ignored: the SML parser normalizes inline whitespace, so
|
|
82
|
+
* only the element structure is stable enough to be a source-map contract.
|
|
83
|
+
*/
|
|
84
|
+
declare const mapJsxSourceLocations: (draft: ElementNode, parsed: ElementNode) => UnboundTemplateSourceLocations;
|
|
85
|
+
/** Compare source-map statuses for the emission determinism guard. */
|
|
86
|
+
declare const sameTemplateSourceLocations: (left: UnboundTemplateSourceLocations, right: UnboundTemplateSourceLocations) => boolean;
|
|
87
|
+
//#endregion
|
|
88
|
+
export { SourceLocationUnavailableReason as a, UnboundTemplateSourceLocations as c, jsxSourceLocationOf as d, mapJsxSourceLocations as f, JsxSourceLocation as i, attachJsxSourceLocation as l, JSX_SOURCE_LOCATION_PROP as n, TemplateSourceLocations as o, sameTemplateSourceLocations as p, JsxSource as r, TemplateSourceLocationsSchema as s, JSX_SOURCE_LOCATION as t, completeJsxSourceLocation as u };
|
|
89
|
+
//# sourceMappingURL=source-locations-BCJQnIfU.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as SourceLocationUnavailableReason, c as UnboundTemplateSourceLocations, d as jsxSourceLocationOf, f as mapJsxSourceLocations, i as JsxSourceLocation, l as attachJsxSourceLocation, n as JSX_SOURCE_LOCATION_PROP, o as TemplateSourceLocations, p as sameTemplateSourceLocations, r as JsxSource, s as TemplateSourceLocationsSchema, t as JSX_SOURCE_LOCATION, u as completeJsxSourceLocation } from "./source-locations-BCJQnIfU.js";
|
|
2
|
+
export { JSX_SOURCE_LOCATION, JSX_SOURCE_LOCATION_PROP, JsxSource, JsxSourceLocation, SourceLocationUnavailableReason, TemplateSourceLocations, TemplateSourceLocationsSchema, UnboundTemplateSourceLocations, attachJsxSourceLocation, completeJsxSourceLocation, jsxSourceLocationOf, mapJsxSourceLocations, sameTemplateSourceLocations };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { Predicate, Schema } from "effect";
|
|
2
|
+
//#region src/source-locations.ts
|
|
3
|
+
/** JSON-safe source location shape shared by preview and editor contracts. */
|
|
4
|
+
const JsxSourceLocation = Schema.Struct({
|
|
5
|
+
fileName: Schema.String,
|
|
6
|
+
lineNumber: Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)),
|
|
7
|
+
columnNumber: Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))
|
|
8
|
+
});
|
|
9
|
+
/** Reasons a preview cannot safely expose an authored source map. */
|
|
10
|
+
const SourceLocationUnavailableReason = Schema.Literals([
|
|
11
|
+
"no-source-metadata",
|
|
12
|
+
"structure-mismatch",
|
|
13
|
+
"duplicate-source-origin",
|
|
14
|
+
"render-failed",
|
|
15
|
+
"stale-preview"
|
|
16
|
+
]);
|
|
17
|
+
/**
|
|
18
|
+
* Runtime-only carrier for JSX source metadata. It is global so separately
|
|
19
|
+
* bundled `jsx-dev-runtime` and `render-template` entries still agree on the
|
|
20
|
+
* sidecar key, and it is a Symbol so it cannot enter SML, HTML, or JSON.
|
|
21
|
+
*/
|
|
22
|
+
const JSX_SOURCE_LOCATION = Symbol.for("@samva/markup/jsx-source-location");
|
|
23
|
+
/** Internal JSX prop used only by an editor preview source transform. */
|
|
24
|
+
const JSX_SOURCE_LOCATION_PROP = "__samva_source_location";
|
|
25
|
+
/** JSON-safe schema for a parsed-node-id → JSX-origin map. */
|
|
26
|
+
const TemplateSourceLocationsSchema = Schema.Union([Schema.Struct({
|
|
27
|
+
kind: Schema.Literal("available"),
|
|
28
|
+
revision: Schema.String,
|
|
29
|
+
byNodeId: Schema.Record(Schema.String, JsxSourceLocation)
|
|
30
|
+
}), Schema.Struct({
|
|
31
|
+
kind: Schema.Literal("unavailable"),
|
|
32
|
+
reason: SourceLocationUnavailableReason
|
|
33
|
+
})]);
|
|
34
|
+
/** Normalize the optional payload accepted by `jsxDEV`. */
|
|
35
|
+
const completeJsxSourceLocation = (source) => {
|
|
36
|
+
if (source?.fileName === void 0 || source.lineNumber === void 0 || source.columnNumber === void 0) return;
|
|
37
|
+
return Object.freeze({
|
|
38
|
+
fileName: source.fileName,
|
|
39
|
+
lineNumber: source.lineNumber,
|
|
40
|
+
columnNumber: source.columnNumber
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
/** Attach a source origin without changing the serialized draft shape. */
|
|
44
|
+
const attachJsxSourceLocation = (node, source) => {
|
|
45
|
+
if (Object.hasOwn(node, JSX_SOURCE_LOCATION)) return;
|
|
46
|
+
Object.defineProperty(node, JSX_SOURCE_LOCATION, {
|
|
47
|
+
configurable: false,
|
|
48
|
+
enumerable: false,
|
|
49
|
+
value: source,
|
|
50
|
+
writable: false
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const isJsxSourceLocation = (value) => Predicate.hasProperty(value, "fileName") && typeof value.fileName === "string" && Predicate.hasProperty(value, "lineNumber") && typeof value.lineNumber === "number" && Number.isInteger(value.lineNumber) && Predicate.hasProperty(value, "columnNumber") && typeof value.columnNumber === "number" && Number.isInteger(value.columnNumber);
|
|
54
|
+
/** Read the ephemeral origin, if this draft element has one. */
|
|
55
|
+
const jsxSourceLocationOf = (node) => {
|
|
56
|
+
if (node.kind !== "element") return void 0;
|
|
57
|
+
const value = Object.getOwnPropertyDescriptor(node, JSX_SOURCE_LOCATION)?.value;
|
|
58
|
+
return isJsxSourceLocation(value) ? value : void 0;
|
|
59
|
+
};
|
|
60
|
+
const elementChildren = (node) => node.children.filter((child) => child.kind === "element");
|
|
61
|
+
const sourceOriginKey = (source) => JSON.stringify([
|
|
62
|
+
source.fileName,
|
|
63
|
+
source.lineNumber,
|
|
64
|
+
source.columnNumber
|
|
65
|
+
]);
|
|
66
|
+
/**
|
|
67
|
+
* Pair a draft tree with its parsed SML tree by element preorder. Text nodes
|
|
68
|
+
* are intentionally ignored: the SML parser normalizes inline whitespace, so
|
|
69
|
+
* only the element structure is stable enough to be a source-map contract.
|
|
70
|
+
*/
|
|
71
|
+
const mapJsxSourceLocations = (draft, parsed) => {
|
|
72
|
+
const byNodeId = {};
|
|
73
|
+
const origins = /* @__PURE__ */ new Set();
|
|
74
|
+
let duplicateOrigin = false;
|
|
75
|
+
const visit = (draftNode, parsedNode) => {
|
|
76
|
+
if (draftNode.tag !== parsedNode.tag) return false;
|
|
77
|
+
const source = jsxSourceLocationOf(draftNode);
|
|
78
|
+
if (source !== void 0) {
|
|
79
|
+
const origin = sourceOriginKey(source);
|
|
80
|
+
if (origins.has(origin)) duplicateOrigin = true;
|
|
81
|
+
origins.add(origin);
|
|
82
|
+
if (Object.hasOwn(byNodeId, parsedNode.id)) return false;
|
|
83
|
+
byNodeId[parsedNode.id] = source;
|
|
84
|
+
}
|
|
85
|
+
const draftChildren = elementChildren(draftNode);
|
|
86
|
+
const parsedChildren = elementChildren(parsedNode);
|
|
87
|
+
if (draftChildren.length !== parsedChildren.length) return false;
|
|
88
|
+
for (let index = 0; index < draftChildren.length; index++) if (!visit(draftChildren[index], parsedChildren[index])) return false;
|
|
89
|
+
return true;
|
|
90
|
+
};
|
|
91
|
+
if (!visit(draft, parsed)) return {
|
|
92
|
+
kind: "unavailable",
|
|
93
|
+
reason: "structure-mismatch"
|
|
94
|
+
};
|
|
95
|
+
if (duplicateOrigin) return {
|
|
96
|
+
kind: "unavailable",
|
|
97
|
+
reason: "duplicate-source-origin"
|
|
98
|
+
};
|
|
99
|
+
if (Object.keys(byNodeId).length === 0) return {
|
|
100
|
+
kind: "unavailable",
|
|
101
|
+
reason: "no-source-metadata"
|
|
102
|
+
};
|
|
103
|
+
return {
|
|
104
|
+
kind: "available",
|
|
105
|
+
byNodeId: Object.freeze(byNodeId)
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
/** Compare source-map statuses for the emission determinism guard. */
|
|
109
|
+
const sameTemplateSourceLocations = (left, right) => {
|
|
110
|
+
if (left.kind !== right.kind) return false;
|
|
111
|
+
if (left.kind === "unavailable") return right.kind === "unavailable" && left.reason === right.reason;
|
|
112
|
+
if (right.kind === "unavailable") return false;
|
|
113
|
+
const leftEntries = Object.entries(left.byNodeId);
|
|
114
|
+
const rightEntries = Object.entries(right.byNodeId);
|
|
115
|
+
if (leftEntries.length !== rightEntries.length) return false;
|
|
116
|
+
for (const [nodeId, source] of leftEntries) {
|
|
117
|
+
const other = right.byNodeId[nodeId];
|
|
118
|
+
if (other === void 0 || other.fileName !== source.fileName || other.lineNumber !== source.lineNumber || other.columnNumber !== source.columnNumber) return false;
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
};
|
|
122
|
+
//#endregion
|
|
123
|
+
export { JSX_SOURCE_LOCATION, JSX_SOURCE_LOCATION_PROP, JsxSourceLocation, SourceLocationUnavailableReason, TemplateSourceLocationsSchema, attachJsxSourceLocation, completeJsxSourceLocation, jsxSourceLocationOf, mapJsxSourceLocations, sameTemplateSourceLocations };
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=source-locations.js.map
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import "./source-locations-BCJQnIfU.js";
|
|
2
|
+
import { r as EmailDiagnostic } from "./diagnostics-Djd9ckLg.js";
|
|
3
|
+
import { m as EmailNode } from "./elements-DtwKlFVH.js";
|
|
4
|
+
import "css-tree";
|
|
5
|
+
//#region src/email/selectors.d.ts
|
|
6
|
+
type EmailElementNode = Extract<EmailNode, {
|
|
7
|
+
_tag: "Element";
|
|
8
|
+
}>;
|
|
9
|
+
interface AttributeTest {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly operator?: string | undefined;
|
|
12
|
+
readonly value?: string | undefined;
|
|
13
|
+
}
|
|
14
|
+
interface Compound {
|
|
15
|
+
readonly tag?: string | undefined;
|
|
16
|
+
readonly id?: string | undefined;
|
|
17
|
+
readonly classes: readonly string[];
|
|
18
|
+
readonly attributes: readonly AttributeTest[];
|
|
19
|
+
/** A compound the matcher cannot evaluate — a pseudo-class, say — never matches. */
|
|
20
|
+
readonly opaque: boolean;
|
|
21
|
+
}
|
|
22
|
+
type Combinator = "descendant" | "child" | "adjacent" | "sibling";
|
|
23
|
+
interface CompiledSelector {
|
|
24
|
+
/** Document order, left to right; each part names the combinator that follows it. */
|
|
25
|
+
readonly parts: readonly {
|
|
26
|
+
readonly compound: Compound;
|
|
27
|
+
readonly after?: Combinator;
|
|
28
|
+
}[];
|
|
29
|
+
}
|
|
30
|
+
/** An element together with the ancestors and preceding siblings a combinator needs. */
|
|
31
|
+
interface Ancestry {
|
|
32
|
+
readonly element: EmailElementNode;
|
|
33
|
+
readonly parent: Ancestry | undefined;
|
|
34
|
+
readonly previous: readonly EmailElementNode[];
|
|
35
|
+
}
|
|
36
|
+
declare const classListOf: (element: EmailElementNode) => readonly string[];
|
|
37
|
+
/** Match a compiled selector against one element in its tree position. */
|
|
38
|
+
declare const matchesSelector: (selector: CompiledSelector | undefined, ancestry: Ancestry) => boolean;
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/email/css.d.ts
|
|
41
|
+
interface CssDeclaration {
|
|
42
|
+
/** Kebab-case property name, as authored. */
|
|
43
|
+
readonly property: string;
|
|
44
|
+
readonly value: string;
|
|
45
|
+
readonly important: boolean;
|
|
46
|
+
}
|
|
47
|
+
/** Specificity as the CSS triple (id, class/attribute/pseudo-class, type). */
|
|
48
|
+
type Specificity = readonly [number, number, number];
|
|
49
|
+
interface CssRule {
|
|
50
|
+
/** Exactly one selector; a selector list is split into one rule each. */
|
|
51
|
+
readonly selector: string;
|
|
52
|
+
/** Decoded class identifiers mentioned by this selector, including nested pseudo selectors. */
|
|
53
|
+
readonly classes: readonly string[];
|
|
54
|
+
readonly specificity: Specificity;
|
|
55
|
+
readonly declarations: readonly CssDeclaration[];
|
|
56
|
+
/** Position across every stylesheet, in the order they were imported. */
|
|
57
|
+
readonly order: number;
|
|
58
|
+
/** Declared `@layer` index; unlayered declarations sort above every layer. */
|
|
59
|
+
readonly layer: number;
|
|
60
|
+
/** Enclosing conditional at-rule preludes, outermost first. */
|
|
61
|
+
readonly conditions: readonly string[];
|
|
62
|
+
/** Unconditional and pseudo-free rules are the only ones that can become an inline style. */
|
|
63
|
+
readonly inlinable: boolean;
|
|
64
|
+
/** Compiled at build time so the render lane needs no CSS parser. */
|
|
65
|
+
readonly matcher: CompiledSelector | undefined;
|
|
66
|
+
}
|
|
67
|
+
interface Stylesheet {
|
|
68
|
+
readonly rules: readonly CssRule[];
|
|
69
|
+
/** `@font-face` and other at-rules kept verbatim in `<head>`. */
|
|
70
|
+
readonly headAtRules: readonly string[];
|
|
71
|
+
/** Unconditional custom properties, for resolving `var()` before inlining. */
|
|
72
|
+
readonly variables: Readonly<Record<string, string>>;
|
|
73
|
+
readonly diagnostics: readonly EmailDiagnostic[];
|
|
74
|
+
}
|
|
75
|
+
/** Compile a selector into the plain-data matcher the render lane uses. */
|
|
76
|
+
declare const compileSelector: (selector: string) => CompiledSelector | undefined;
|
|
77
|
+
/** Parse one stylesheet into rules, keeping layer, order and conditions. */
|
|
78
|
+
declare const parseStylesheet: (source: string, options?: {
|
|
79
|
+
readonly origin?: string;
|
|
80
|
+
readonly startOrder?: number;
|
|
81
|
+
}) => Stylesheet;
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/email/stylesheets.d.ts
|
|
84
|
+
/** Called by a compiler-generated stylesheet module at import time. */
|
|
85
|
+
declare const registerStylesheet: (sheet: Stylesheet) => void;
|
|
86
|
+
/** Drop every registration. The render entry calls this before a render. */
|
|
87
|
+
declare const resetStylesheets: () => void;
|
|
88
|
+
/** Every registered sheet flattened into one, with order preserved across sheets. */
|
|
89
|
+
declare const collectStylesheets: () => Stylesheet;
|
|
90
|
+
/** True when a template registered no styles at all, so the render can skip the pass. */
|
|
91
|
+
declare const hasStylesheets: () => boolean;
|
|
92
|
+
//#endregion
|
|
93
|
+
export { CssDeclaration as a, Stylesheet as c, Ancestry as d, CompiledSelector as f, matchesSelector as h, resetStylesheets as i, compileSelector as l, classListOf as m, hasStylesheets as n, CssRule as o, Compound as p, registerStylesheet as r, Specificity as s, collectStylesheets as t, parseStylesheet as u };
|
|
94
|
+
//# sourceMappingURL=stylesheets-oDRAnYA3.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { m as EmailNode } from "./elements-DtwKlFVH.js";
|
|
2
|
+
import { r as InputSchema } from "./input-schema-BIfzI63B.js";
|
|
3
|
+
import { StandardJSONSchemaV1 } from "effect/StandardSchema";
|
|
4
|
+
//#region src/template.d.ts
|
|
5
|
+
/** One actual-input render owns all of a message's authored content. */
|
|
6
|
+
interface EmailContent {
|
|
7
|
+
readonly subject: string;
|
|
8
|
+
readonly preheader?: string;
|
|
9
|
+
readonly body: EmailNode;
|
|
10
|
+
readonly text?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Fixed ambient values a template declares. Rendering has no clock and no entropy source: reading
|
|
14
|
+
* the current instant or a random value throws unless the matching value is declared here, so a
|
|
15
|
+
* message either takes time and randomness from its input or states them once as configuration.
|
|
16
|
+
*/
|
|
17
|
+
interface TemplateRuntime {
|
|
18
|
+
readonly now?: number;
|
|
19
|
+
readonly randomSeed?: number;
|
|
20
|
+
}
|
|
21
|
+
/** Explicit template identity distinguishes entries from imported helper modules. */
|
|
22
|
+
interface TemplateDefinition<Input> {
|
|
23
|
+
readonly id: string;
|
|
24
|
+
readonly schema: InputSchema<Input>;
|
|
25
|
+
readonly fixtures: Readonly<Record<string, Input>>;
|
|
26
|
+
readonly render: (input: Input) => EmailContent;
|
|
27
|
+
readonly runtime?: TemplateRuntime;
|
|
28
|
+
}
|
|
29
|
+
/** Classify an evaluated module export without executing helpers as templates. */
|
|
30
|
+
declare const isTemplateDefinition: (value: unknown) => value is TemplateDefinition<unknown>;
|
|
31
|
+
/**
|
|
32
|
+
* The one naming contract for a template id and a fixture key: a letter, a digit or `_` first,
|
|
33
|
+
* then those plus `.`, `_` and `-`.
|
|
34
|
+
*
|
|
35
|
+
* Both names are written into file paths — a local export writes one page at
|
|
36
|
+
* `templates/<id>/<fixture>.html` — so each has to be a single plain path segment. The rule lives
|
|
37
|
+
* at the declaration, so a project that could not be exported is refused where the name is
|
|
38
|
+
* written rather than at the end of a build. Consumers that resolve a path from these names
|
|
39
|
+
* import this pattern; they do not restate it.
|
|
40
|
+
*/
|
|
41
|
+
declare const TEMPLATE_NAME_PATTERN: RegExp;
|
|
42
|
+
/**
|
|
43
|
+
* Define an email template with caller-input inference from a Standard JSON Schema converter. The
|
|
44
|
+
* helper is named for its channel because its render result is email content; `TemplateDefinition`
|
|
45
|
+
* and `TemplateInput` stay channel-neutral.
|
|
46
|
+
*/
|
|
47
|
+
declare const defineEmail: <S extends StandardJSONSchemaV1>(definition: {
|
|
48
|
+
readonly id: string;
|
|
49
|
+
readonly schema: S;
|
|
50
|
+
readonly fixtures: Readonly<Record<string, NoInfer<StandardJSONSchemaV1.InferInput<S>>>>;
|
|
51
|
+
readonly render: (input: NoInfer<StandardJSONSchemaV1.InferInput<S>>) => EmailContent;
|
|
52
|
+
readonly runtime?: TemplateRuntime;
|
|
53
|
+
}) => TemplateDefinition<StandardJSONSchemaV1.InferInput<S>>;
|
|
54
|
+
/** Caller input for generated references and separate authoring consumers. */
|
|
55
|
+
type TemplateInput<T extends {
|
|
56
|
+
readonly render: (input: never) => EmailContent;
|
|
57
|
+
}> = Parameters<T["render"]>[0];
|
|
58
|
+
//#endregion
|
|
59
|
+
export { TemplateRuntime as a, TemplateInput as i, TEMPLATE_NAME_PATTERN as n, defineEmail as o, TemplateDefinition as r, isTemplateDefinition as s, EmailContent as t };
|
|
60
|
+
//# sourceMappingURL=template-Dy5yOPyp.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as TemplateRuntime, i as TemplateInput, n as TEMPLATE_NAME_PATTERN, o as defineEmail, r as TemplateDefinition, s as isTemplateDefinition, t as EmailContent } from "./template-Dy5yOPyp.js";
|
|
2
|
+
export { EmailContent, TEMPLATE_NAME_PATTERN, TemplateDefinition, TemplateInput, TemplateRuntime, defineEmail, isTemplateDefinition };
|
package/dist/template.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { inputSchema } from "./input-schema.js";
|
|
2
|
+
import { Predicate } from "effect";
|
|
3
|
+
//#region src/template.ts
|
|
4
|
+
/** Classify an evaluated module export without executing helpers as templates. */
|
|
5
|
+
const isTemplateDefinition = (value) => Predicate.isObject(value) && typeof value.id === "string" && typeof value.render === "function" && Predicate.isObject(value.schema);
|
|
6
|
+
/**
|
|
7
|
+
* The one naming contract for a template id and a fixture key: a letter, a digit or `_` first,
|
|
8
|
+
* then those plus `.`, `_` and `-`.
|
|
9
|
+
*
|
|
10
|
+
* Both names are written into file paths — a local export writes one page at
|
|
11
|
+
* `templates/<id>/<fixture>.html` — so each has to be a single plain path segment. The rule lives
|
|
12
|
+
* at the declaration, so a project that could not be exported is refused where the name is
|
|
13
|
+
* written rather than at the end of a build. Consumers that resolve a path from these names
|
|
14
|
+
* import this pattern; they do not restate it.
|
|
15
|
+
*/
|
|
16
|
+
const TEMPLATE_NAME_PATTERN = /^[A-Za-z0-9_][A-Za-z0-9._-]*$/;
|
|
17
|
+
const checkTemplateName = (kind, value) => {
|
|
18
|
+
if (TEMPLATE_NAME_PATTERN.test(value)) return;
|
|
19
|
+
throw new TypeError(`${kind} ${JSON.stringify(value)} is not one path segment. A template id and a fixture key are written into file paths, so each must start with a letter, a digit or "_" and continue with letters, digits, ".", "_" or "-".`);
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Define an email template with caller-input inference from a Standard JSON Schema converter. The
|
|
23
|
+
* helper is named for its channel because its render result is email content; `TemplateDefinition`
|
|
24
|
+
* and `TemplateInput` stay channel-neutral.
|
|
25
|
+
*/
|
|
26
|
+
const defineEmail = (definition) => {
|
|
27
|
+
checkTemplateName("Template id", definition.id);
|
|
28
|
+
for (const fixture of Object.keys(definition.fixtures)) checkTemplateName("Fixture key", fixture);
|
|
29
|
+
return {
|
|
30
|
+
...definition,
|
|
31
|
+
schema: inputSchema(definition.schema)
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
//#endregion
|
|
35
|
+
export { TEMPLATE_NAME_PATTERN, defineEmail, isTemplateDefinition };
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=template.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/tsx-source-instrumentation.d.ts
|
|
2
|
+
declare const TsxSourceInstrumentationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
3
|
+
readonly _tag: "TsxSourceInstrumentationError";
|
|
4
|
+
} & Readonly<A>;
|
|
5
|
+
declare class TsxSourceInstrumentationError extends TsxSourceInstrumentationError_base<{
|
|
6
|
+
readonly message: string;
|
|
7
|
+
readonly cause?: unknown;
|
|
8
|
+
}> {}
|
|
9
|
+
/**
|
|
10
|
+
* Add ephemeral source-origin props to one known TSX entry before a hosted
|
|
11
|
+
* editor preview is bundled. The returned source is a build input only: the
|
|
12
|
+
* caller must never persist it or expose it as authored source.
|
|
13
|
+
*
|
|
14
|
+
* Every JSX element is marked, including custom components. The markup runtime
|
|
15
|
+
* strips the marker and keeps an inner element's sidecar when a custom
|
|
16
|
+
* component renders JSX of its own. JSX fragments have no element output and
|
|
17
|
+
* are therefore intentionally skipped. Pass a null import source to preserve
|
|
18
|
+
* authored JSX pragmas in executable email builds.
|
|
19
|
+
*/
|
|
20
|
+
declare const instrumentTsxSourceForPreview: (source: string, fileName: string, token?: string, jsxImportSource?: string | null) => string;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { TsxSourceInstrumentationError, instrumentTsxSourceForPreview };
|
|
23
|
+
//# sourceMappingURL=tsx-source-instrumentation.d.ts.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { JSX_SOURCE_LOCATION_PROP } from "./source-locations.js";
|
|
2
|
+
import { buildLineMap, lineColumn } from "./diagnostics.js";
|
|
3
|
+
import { Data, Predicate } from "effect";
|
|
4
|
+
import { parse } from "@babel/parser";
|
|
5
|
+
//#region src/tsx-source-instrumentation.ts
|
|
6
|
+
var TsxSourceInstrumentationError = class extends Data.TaggedError("TsxSourceInstrumentationError") {};
|
|
7
|
+
const isRecord = (value) => Predicate.isObject(value) && !Array.isArray(value);
|
|
8
|
+
const isAstNode = (value) => isRecord(value) && typeof value.type === "string" && typeof value.start === "number" && typeof value.end === "number";
|
|
9
|
+
const walkAst = (value, visit) => {
|
|
10
|
+
if (Array.isArray(value)) {
|
|
11
|
+
for (const item of value) walkAst(item, visit);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (!isRecord(value)) return;
|
|
15
|
+
if (isAstNode(value)) visit(value);
|
|
16
|
+
for (const [key, child] of Object.entries(value)) {
|
|
17
|
+
if (key === "loc" || key === "extra" || key === "comments" || key === "tokens") continue;
|
|
18
|
+
walkAst(child, visit);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const jsxIdentifier = (value) => {
|
|
22
|
+
if (!isAstNode(value) || value.type !== "JSXIdentifier") return void 0;
|
|
23
|
+
return typeof value.name === "string" ? value.name : void 0;
|
|
24
|
+
};
|
|
25
|
+
const parseErrorMessage = (error) => isRecord(error) && typeof error.message === "string" ? error.message : "The authored TSX could not be parsed for preview instrumentation.";
|
|
26
|
+
const marker = (fileName, source, offset, token) => {
|
|
27
|
+
const position = lineColumn(buildLineMap(source), offset);
|
|
28
|
+
return ` ${JSX_SOURCE_LOCATION_PROP}={${JSON.stringify({
|
|
29
|
+
fileName,
|
|
30
|
+
lineNumber: position.line,
|
|
31
|
+
columnNumber: position.column,
|
|
32
|
+
...token === void 0 ? {} : { token }
|
|
33
|
+
})}}`;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Add ephemeral source-origin props to one known TSX entry before a hosted
|
|
37
|
+
* editor preview is bundled. The returned source is a build input only: the
|
|
38
|
+
* caller must never persist it or expose it as authored source.
|
|
39
|
+
*
|
|
40
|
+
* Every JSX element is marked, including custom components. The markup runtime
|
|
41
|
+
* strips the marker and keeps an inner element's sidecar when a custom
|
|
42
|
+
* component renders JSX of its own. JSX fragments have no element output and
|
|
43
|
+
* are therefore intentionally skipped. Pass a null import source to preserve
|
|
44
|
+
* authored JSX pragmas in executable email builds.
|
|
45
|
+
*/
|
|
46
|
+
const instrumentTsxSourceForPreview = (source, fileName, token, jsxImportSource = "@samva/preview-runtime") => {
|
|
47
|
+
let parsed;
|
|
48
|
+
try {
|
|
49
|
+
parsed = parse(source, {
|
|
50
|
+
plugins: ["typescript", "jsx"],
|
|
51
|
+
sourceType: "module"
|
|
52
|
+
});
|
|
53
|
+
} catch (error) {
|
|
54
|
+
throw new TsxSourceInstrumentationError({
|
|
55
|
+
cause: error,
|
|
56
|
+
message: parseErrorMessage(error)
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
const edits = [];
|
|
60
|
+
for (const comment of jsxImportSource === null ? [] : parsed.comments ?? []) {
|
|
61
|
+
const commentStart = comment.start;
|
|
62
|
+
const commentEnd = comment.end;
|
|
63
|
+
if (commentStart === void 0 || commentEnd === void 0) continue;
|
|
64
|
+
const commentSource = source.slice(commentStart, commentEnd);
|
|
65
|
+
for (const match of commentSource.matchAll(/@jsxImportSource\s+[^\s*]+/gu)) {
|
|
66
|
+
if (match.index === void 0) continue;
|
|
67
|
+
edits.push({
|
|
68
|
+
start: commentStart + match.index,
|
|
69
|
+
end: commentStart + match.index + match[0].length,
|
|
70
|
+
value: `@jsxImportSource ${jsxImportSource}`
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
walkAst(parsed.program, (node) => {
|
|
75
|
+
if (node.type !== "JSXElement") return;
|
|
76
|
+
const openingElement = node.openingElement;
|
|
77
|
+
if (!isAstNode(openingElement)) return;
|
|
78
|
+
const attributes = openingElement.attributes;
|
|
79
|
+
if (Array.isArray(attributes)) for (const attribute of attributes) {
|
|
80
|
+
if (!isAstNode(attribute) || attribute.type !== "JSXAttribute") continue;
|
|
81
|
+
if (jsxIdentifier(attribute.name) === "__samva_source_location") throw new TsxSourceInstrumentationError({ message: `The reserved JSX prop ${JSX_SOURCE_LOCATION_PROP} cannot be authored directly.` });
|
|
82
|
+
}
|
|
83
|
+
const closingLength = source.slice(openingElement.end - 2, openingElement.end) === "/>" ? 2 : 1;
|
|
84
|
+
edits.push({
|
|
85
|
+
start: openingElement.end - closingLength,
|
|
86
|
+
end: openingElement.end - closingLength,
|
|
87
|
+
value: marker(fileName, source, openingElement.start, token)
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
let instrumented = source;
|
|
91
|
+
for (const edit of edits.toSorted((left, right) => right.start - left.start)) instrumented = instrumented.slice(0, edit.start) + edit.value + instrumented.slice(edit.end);
|
|
92
|
+
return instrumented;
|
|
93
|
+
};
|
|
94
|
+
//#endregion
|
|
95
|
+
export { TsxSourceInstrumentationError, instrumentTsxSourceForPreview };
|
|
96
|
+
|
|
97
|
+
//# sourceMappingURL=tsx-source-instrumentation.js.map
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { s as Span } from "./diagnostics-oveE-laV.js";
|
|
2
|
+
import { SmlOp } from "./ops.js";
|
|
3
|
+
import { Result } from "effect";
|
|
4
|
+
//#region src/tsx-tracer.d.ts
|
|
5
|
+
/** The closed set of reasons a rendered heading cannot be mapped safely. */
|
|
6
|
+
type TsxHeadingDiagnosticCode = "tsx-invalid-authored-source" | "tsx-invalid-emitted-source" | "tsx-target-not-found" | "tsx-unsupported-target" | "tsx-ambiguous-target" | "tsx-dynamic-target";
|
|
7
|
+
interface TsxHeadingDiagnostic {
|
|
8
|
+
readonly code: TsxHeadingDiagnosticCode;
|
|
9
|
+
readonly message: string;
|
|
10
|
+
readonly span: Span;
|
|
11
|
+
}
|
|
12
|
+
declare const TsxHeadingTraceError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
13
|
+
readonly _tag: "TsxHeadingTraceError";
|
|
14
|
+
} & Readonly<A>;
|
|
15
|
+
declare class TsxHeadingTraceError extends TsxHeadingTraceError_base<{
|
|
16
|
+
readonly diagnostics: ReadonlyArray<TsxHeadingDiagnostic>;
|
|
17
|
+
}> {}
|
|
18
|
+
/**
|
|
19
|
+
* Source metadata attached to a rendered JSX node by the development JSX
|
|
20
|
+
* transform, or an equivalent exact source span from a host.
|
|
21
|
+
*
|
|
22
|
+
* `lineNumber`/`columnNumber` use the JSX transform convention: both are
|
|
23
|
+
* one-based and identify the opening `<` of the element. A span locator is
|
|
24
|
+
* useful to hosts that already have absolute offsets and must match the whole
|
|
25
|
+
* JSX element span exactly.
|
|
26
|
+
*/
|
|
27
|
+
type TsxSourceLocator = {
|
|
28
|
+
readonly fileName: string;
|
|
29
|
+
readonly lineNumber: number;
|
|
30
|
+
readonly columnNumber: number;
|
|
31
|
+
} | {
|
|
32
|
+
readonly fileName: string;
|
|
33
|
+
readonly span: Span;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* How an authored static text child spells itself. `jsx-text` is bare text
|
|
37
|
+
* between tags; `string-literal` is a `{"…"}` expression container holding a
|
|
38
|
+
* string literal, or a template literal with no expressions. An edit writes a
|
|
39
|
+
* child back in the form it already had.
|
|
40
|
+
*/
|
|
41
|
+
type StaticTextForm = "jsx-text" | "string-literal";
|
|
42
|
+
/** A source range containing only the text bytes that an edit is allowed to replace. */
|
|
43
|
+
interface TsxHeadingSourceTarget {
|
|
44
|
+
readonly nodeId: string;
|
|
45
|
+
readonly text: string;
|
|
46
|
+
readonly span: Span;
|
|
47
|
+
/** The spelling to preserve when the range is rewritten. */
|
|
48
|
+
readonly form: StaticTextForm;
|
|
49
|
+
}
|
|
50
|
+
interface TraceTsxHeadingInput {
|
|
51
|
+
/** The canonical TSX entry file path. */
|
|
52
|
+
readonly authoredFile: string;
|
|
53
|
+
/** The canonical TSX entry file. */
|
|
54
|
+
readonly authoredSource: string;
|
|
55
|
+
/** The last-good SML preview derived from that entry file. */
|
|
56
|
+
readonly emittedSource: string;
|
|
57
|
+
/** The selected semantic SML node id. */
|
|
58
|
+
readonly nodeId: string;
|
|
59
|
+
/** Exact runtime/source-map provenance for the selected JSX node. */
|
|
60
|
+
readonly sourceLocator?: TsxSourceLocator | undefined;
|
|
61
|
+
}
|
|
62
|
+
interface ReplaceTsxHeadingTextInput extends TraceTsxHeadingInput {
|
|
63
|
+
readonly text: string;
|
|
64
|
+
}
|
|
65
|
+
type TsxHeadingTrace = Result.Result<TsxHeadingSourceTarget, TsxHeadingTraceError>;
|
|
66
|
+
type TsxHeadingEdit = Result.Result<string, TsxHeadingTraceError>;
|
|
67
|
+
/** Resolve one rendered Heading to one direct-literal JSX text range. */
|
|
68
|
+
declare const traceTsxHeadingTarget: (input: TraceTsxHeadingInput) => TsxHeadingTrace;
|
|
69
|
+
/** Replace only the mapped literal bytes; all other authored TSX stays untouched. */
|
|
70
|
+
declare const replaceTsxHeadingText: (input: ReplaceTsxHeadingTextInput) => TsxHeadingEdit;
|
|
71
|
+
/**
|
|
72
|
+
* The closed set of failures returned by {@link applyTsxSmlOps}. The editor
|
|
73
|
+
* deliberately treats these as a typed "not safe to edit" response: it can
|
|
74
|
+
* keep showing the preview and offer source editing without guessing at a
|
|
75
|
+
* byte range in a user's project.
|
|
76
|
+
*/
|
|
77
|
+
type TsxSmlDiagnosticCode = TsxHeadingDiagnosticCode | "tsx-invalid-snippet" | "tsx-unsupported-operation";
|
|
78
|
+
interface TsxSmlDiagnostic {
|
|
79
|
+
readonly code: TsxSmlDiagnosticCode;
|
|
80
|
+
readonly message: string;
|
|
81
|
+
readonly span: Span;
|
|
82
|
+
}
|
|
83
|
+
declare const TsxSmlOpsError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
84
|
+
readonly _tag: "TsxSmlOpsError";
|
|
85
|
+
} & Readonly<A>;
|
|
86
|
+
declare class TsxSmlOpsError extends TsxSmlOpsError_base<{
|
|
87
|
+
readonly diagnostics: ReadonlyArray<TsxSmlDiagnostic>;
|
|
88
|
+
}> {}
|
|
89
|
+
interface ApplyTsxSmlOpsInput {
|
|
90
|
+
/** The canonical TSX entry file path. */
|
|
91
|
+
readonly authoredFile: string;
|
|
92
|
+
/** The canonical TSX entry file. */
|
|
93
|
+
readonly authoredSource: string;
|
|
94
|
+
/** The last-good SML preview derived from that entry file. */
|
|
95
|
+
readonly emittedSource: string;
|
|
96
|
+
/** Revision-fenced JSX origins for the SML ids in `emittedSource`. */
|
|
97
|
+
readonly sourceLocations: {
|
|
98
|
+
readonly byNodeId: Readonly<Record<string, TsxSourceLocator>>;
|
|
99
|
+
};
|
|
100
|
+
/** SML operations evaluated against the emitted-source id snapshot. */
|
|
101
|
+
readonly ops: ReadonlyArray<SmlOp>;
|
|
102
|
+
}
|
|
103
|
+
type TsxSmlOpsResult = Result.Result<string, TsxSmlOpsError>;
|
|
104
|
+
/**
|
|
105
|
+
* Apply semantic editor operations to the authored TSX entry.
|
|
106
|
+
*
|
|
107
|
+
* The emitted SML document remains the validation oracle: operations are
|
|
108
|
+
* preflighted through the same markup op implementation first, then each
|
|
109
|
+
* mapped target is checked against the authored JSX AST and exact source
|
|
110
|
+
* provenance. The mutable source tree below only moves original AST nodes or
|
|
111
|
+
* inserts validated raw fragments; it never reprints the user's module.
|
|
112
|
+
*/
|
|
113
|
+
declare const applyTsxSmlOps: (input: ApplyTsxSmlOpsInput) => TsxSmlOpsResult;
|
|
114
|
+
//#endregion
|
|
115
|
+
export { ApplyTsxSmlOpsInput, ReplaceTsxHeadingTextInput, StaticTextForm, TraceTsxHeadingInput, TsxHeadingDiagnostic, TsxHeadingDiagnosticCode, TsxHeadingEdit, TsxHeadingSourceTarget, TsxHeadingTrace, TsxHeadingTraceError, TsxSmlDiagnostic, TsxSmlDiagnosticCode, TsxSmlOpsError, TsxSmlOpsResult, TsxSourceLocator, applyTsxSmlOps, replaceTsxHeadingText, traceTsxHeadingTarget };
|
|
116
|
+
//# sourceMappingURL=tsx-tracer.d.ts.map
|