@samva/markup 0.1.2 → 0.3.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.
Files changed (93) hide show
  1. package/AGENTS.md +25 -5
  2. package/README.md +92 -26
  3. package/dist/{ast-DAhnAvQN.d.ts → ast-63I-VLQx.d.ts} +15 -2
  4. package/dist/ast.d.ts +2 -2
  5. package/dist/ast.js +14 -1
  6. package/dist/{checks-D-zFQt5R.js → checks-DXuERO4B.js} +36 -2
  7. package/dist/checks.d.ts +8 -1
  8. package/dist/checks.js +2 -2
  9. package/dist/compile-sms.d.ts +2 -2
  10. package/dist/compile-whatsapp.d.ts +2 -2
  11. package/dist/compile.d.ts +9 -84
  12. package/dist/compile.js +11 -920
  13. package/dist/compiler.d.ts +303 -0
  14. package/dist/compiler.js +1390 -0
  15. package/dist/components.d.ts +3 -3
  16. package/dist/corpus-qrUD5O6r.d.ts +254 -0
  17. package/dist/css-ar2lU3NC.d.ts +84 -0
  18. package/dist/diagnostics-Djd9ckLg.d.ts +90 -0
  19. package/dist/diagnostics.js +4 -1
  20. package/dist/elements-DtwKlFVH.d.ts +820 -0
  21. package/dist/email/components.d.ts +125 -0
  22. package/dist/email/components.js +210 -0
  23. package/dist/email/diagnostics.d.ts +2 -0
  24. package/dist/email/diagnostics.js +56 -0
  25. package/dist/email/elements.d.ts +2 -0
  26. package/dist/email/elements.js +299 -0
  27. package/dist/email/html.d.ts +42 -0
  28. package/dist/email/html.js +266 -0
  29. package/dist/email/jsx-dev-runtime.d.ts +26 -0
  30. package/dist/email/jsx-dev-runtime.js +12 -0
  31. package/dist/email/jsx-runtime.d.ts +2 -0
  32. package/dist/email/jsx-runtime.js +60 -0
  33. package/dist/email/render.d.ts +43 -0
  34. package/dist/email/render.js +6 -0
  35. package/dist/email/selection.d.ts +102 -0
  36. package/dist/email/selection.js +143 -0
  37. package/dist/email/source-edit.d.ts +67 -0
  38. package/dist/email/source-edit.js +185 -0
  39. package/dist/email/stylesheets.d.ts +15 -0
  40. package/dist/email/stylesheets.js +45 -0
  41. package/dist/email/text.d.ts +7 -0
  42. package/dist/email/text.js +100 -0
  43. package/dist/emit.d.ts +13 -12
  44. package/dist/emit.js +63 -63
  45. package/dist/input-schema-BIfzI63B.d.ts +23 -0
  46. package/dist/input-schema.d.ts +2 -0
  47. package/dist/input-schema.js +170 -0
  48. package/dist/jsx-dev-runtime.d.ts +4 -3
  49. package/dist/jsx-dev-runtime.js +9 -1
  50. package/dist/{jsx-runtime-eNIMY87F.d.ts → jsx-runtime-C5k_Zq0A.d.ts} +3 -3
  51. package/dist/jsx-runtime.d.ts +1 -1
  52. package/dist/jsx-runtime.js +20 -1
  53. package/dist/model.d.ts +1 -1
  54. package/dist/ops.d.ts +1 -1
  55. package/dist/ops.js +1 -1
  56. package/dist/{parser-DkQKIjDa.d.ts → parser-CGBS73Gz.d.ts} +2 -2
  57. package/dist/parser.d.ts +1 -1
  58. package/dist/presets/category-mapping.d.ts +1 -1
  59. package/dist/presets/corpus.d.ts +2 -0
  60. package/dist/presets/corpus.js +247 -0
  61. package/dist/presets/public-gallery.d.ts +290 -2
  62. package/dist/presets/public-gallery.js +428 -6
  63. package/dist/presets/public-handoff.d.ts +164 -2
  64. package/dist/presets/public-handoff.js +229 -61
  65. package/dist/presets/public-preview-artifacts.d.ts +2 -2
  66. package/dist/presets/public-preview-artifacts.js +25 -31
  67. package/dist/presets/public-preview.d.ts +65 -2
  68. package/dist/presets/public-preview.js +402 -1152
  69. package/dist/presets/sources.d.ts +35 -4
  70. package/dist/presets/sources.js +2328 -43
  71. package/dist/presets.d.ts +39 -5
  72. package/dist/presets.js +96 -0
  73. package/dist/printer.d.ts +1 -1
  74. package/dist/render-template.d.ts +5 -2
  75. package/dist/render-template.js +3 -1
  76. package/dist/render-ykQhtMs_.js +592 -0
  77. package/dist/source-locations-BCJQnIfU.d.ts +89 -0
  78. package/dist/source-locations.d.ts +2 -0
  79. package/dist/source-locations.js +125 -0
  80. package/dist/template-Dy5yOPyp.d.ts +60 -0
  81. package/dist/template.d.ts +2 -0
  82. package/dist/template.js +37 -0
  83. package/dist/tsx-source-instrumentation.d.ts +23 -0
  84. package/dist/tsx-source-instrumentation.js +97 -0
  85. package/dist/tsx-tracer.d.ts +116 -0
  86. package/dist/tsx-tracer.js +985 -0
  87. package/generated/sml-agent-contract.json +574 -782
  88. package/generated/sml-email-agent-contract.json +502 -677
  89. package/generated/sml-email-language-reference.md +94 -160
  90. package/generated/sml-language-reference.md +195 -220
  91. package/package.json +111 -9
  92. package/dist/public-gallery-D0Zv0pZE.d.ts +0 -611
  93. package/dist/public-preview-u1Z9aaGq.d.ts +0 -1168
@@ -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,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 };
@@ -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