tachyon-dom 0.1.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 (120) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +339 -0
  3. package/dist/adapters/lambda.d.ts +65 -0
  4. package/dist/adapters/lambda.js +211 -0
  5. package/dist/adapters/node.d.ts +25 -0
  6. package/dist/adapters/node.js +360 -0
  7. package/dist/adapters/workers.d.ts +149 -0
  8. package/dist/adapters/workers.js +272 -0
  9. package/dist/adapters.d.ts +3 -0
  10. package/dist/adapters.js +3 -0
  11. package/dist/app.d.ts +98 -0
  12. package/dist/app.js +306 -0
  13. package/dist/cli.d.ts +55 -0
  14. package/dist/cli.js +711 -0
  15. package/dist/compiler/expression.d.ts +55 -0
  16. package/dist/compiler/expression.js +858 -0
  17. package/dist/compiler/index.d.ts +8 -0
  18. package/dist/compiler/index.js +50 -0
  19. package/dist/compiler/ir.d.ts +4 -0
  20. package/dist/compiler/ir.js +255 -0
  21. package/dist/compiler/parser.d.ts +3 -0
  22. package/dist/compiler/parser.js +236 -0
  23. package/dist/compiler/sfc.d.ts +33 -0
  24. package/dist/compiler/sfc.js +439 -0
  25. package/dist/compiler/targets/client.d.ts +3 -0
  26. package/dist/compiler/targets/client.js +568 -0
  27. package/dist/compiler/targets/server.d.ts +7 -0
  28. package/dist/compiler/targets/server.js +396 -0
  29. package/dist/compiler/targets/stream.d.ts +2 -0
  30. package/dist/compiler/targets/stream.js +204 -0
  31. package/dist/compiler/types.d.ts +185 -0
  32. package/dist/compiler/types.js +1 -0
  33. package/dist/compiler/utils.d.ts +40 -0
  34. package/dist/compiler/utils.js +185 -0
  35. package/dist/compiler/whitespace.d.ts +2 -0
  36. package/dist/compiler/whitespace.js +66 -0
  37. package/dist/compiler.d.ts +1 -0
  38. package/dist/compiler.js +1 -0
  39. package/dist/constant-time.d.ts +1 -0
  40. package/dist/constant-time.js +26 -0
  41. package/dist/cookies.d.ts +44 -0
  42. package/dist/cookies.js +199 -0
  43. package/dist/diagnostics.d.ts +22 -0
  44. package/dist/diagnostics.js +45 -0
  45. package/dist/env.d.ts +27 -0
  46. package/dist/env.js +37 -0
  47. package/dist/html-escape.d.ts +2 -0
  48. package/dist/html-escape.js +20 -0
  49. package/dist/html-whitespace.d.ts +6 -0
  50. package/dist/html-whitespace.js +83 -0
  51. package/dist/i18n.d.ts +19 -0
  52. package/dist/i18n.js +93 -0
  53. package/dist/index.d.ts +20 -0
  54. package/dist/index.js +18 -0
  55. package/dist/language-server.d.ts +17 -0
  56. package/dist/language-server.js +79 -0
  57. package/dist/package-integrity.d.ts +9 -0
  58. package/dist/package-integrity.js +64 -0
  59. package/dist/result.d.ts +13 -0
  60. package/dist/result.js +4 -0
  61. package/dist/router-node.d.ts +2 -0
  62. package/dist/router-node.js +12 -0
  63. package/dist/router.d.ts +324 -0
  64. package/dist/router.js +1024 -0
  65. package/dist/runtime/attr.d.ts +3 -0
  66. package/dist/runtime/attr.js +66 -0
  67. package/dist/runtime/class.d.ts +2 -0
  68. package/dist/runtime/class.js +10 -0
  69. package/dist/runtime/conditional.d.ts +78 -0
  70. package/dist/runtime/conditional.js +140 -0
  71. package/dist/runtime/enhancement.d.ts +11 -0
  72. package/dist/runtime/enhancement.js +70 -0
  73. package/dist/runtime/error-boundary.d.ts +8 -0
  74. package/dist/runtime/error-boundary.js +27 -0
  75. package/dist/runtime/event.d.ts +1 -0
  76. package/dist/runtime/event.js +11 -0
  77. package/dist/runtime/form.d.ts +41 -0
  78. package/dist/runtime/form.js +167 -0
  79. package/dist/runtime/fragment.d.ts +6 -0
  80. package/dist/runtime/fragment.js +18 -0
  81. package/dist/runtime/html.d.ts +8 -0
  82. package/dist/runtime/html.js +6 -0
  83. package/dist/runtime/hydrate.d.ts +68 -0
  84. package/dist/runtime/hydrate.js +205 -0
  85. package/dist/runtime/keyed-rows.d.ts +61 -0
  86. package/dist/runtime/keyed-rows.js +192 -0
  87. package/dist/runtime/list.d.ts +84 -0
  88. package/dist/runtime/list.js +424 -0
  89. package/dist/runtime/portal.d.ts +6 -0
  90. package/dist/runtime/portal.js +12 -0
  91. package/dist/runtime/router.d.ts +102 -0
  92. package/dist/runtime/router.js +649 -0
  93. package/dist/runtime/signal.d.ts +30 -0
  94. package/dist/runtime/signal.js +275 -0
  95. package/dist/runtime/store.d.ts +1 -0
  96. package/dist/runtime/store.js +1 -0
  97. package/dist/runtime/stream-client.d.ts +8 -0
  98. package/dist/runtime/stream-client.js +33 -0
  99. package/dist/runtime/text.d.ts +2 -0
  100. package/dist/runtime/text.js +10 -0
  101. package/dist/runtime/virtual-list.d.ts +15 -0
  102. package/dist/runtime/virtual-list.js +89 -0
  103. package/dist/security.d.ts +27 -0
  104. package/dist/security.js +173 -0
  105. package/dist/server/form-action.d.ts +52 -0
  106. package/dist/server/form-action.js +102 -0
  107. package/dist/server/html.d.ts +19 -0
  108. package/dist/server/html.js +101 -0
  109. package/dist/server/stream.d.ts +4 -0
  110. package/dist/server/stream.js +72 -0
  111. package/dist/source-map.d.ts +17 -0
  112. package/dist/source-map.js +18 -0
  113. package/dist/tachyon-html.d.ts +110 -0
  114. package/dist/testing.d.ts +14 -0
  115. package/dist/testing.js +36 -0
  116. package/dist/typed.d.ts +9 -0
  117. package/dist/typed.js +4 -0
  118. package/dist/vite.d.ts +84 -0
  119. package/dist/vite.js +426 -0
  120. package/package.json +604 -0
@@ -0,0 +1,185 @@
1
+ export type CompilerError = {
2
+ message: string;
3
+ offset: number;
4
+ endOffset?: number;
5
+ };
6
+ export type TemplateWhitespacePolicy = "preserve" | "condense";
7
+ export type CompileTemplateOptions = {
8
+ whitespace?: TemplateWhitespacePolicy;
9
+ };
10
+ export type Attribute = {
11
+ name: string;
12
+ value: string | true;
13
+ start?: number;
14
+ end?: number;
15
+ nameStart?: number;
16
+ nameEnd?: number;
17
+ valueStart?: number;
18
+ valueEnd?: number;
19
+ };
20
+ export type ElementNode = {
21
+ type: "element";
22
+ start?: number;
23
+ end?: number;
24
+ openEnd?: number;
25
+ tagName: string;
26
+ attrs: Attribute[];
27
+ children: TemplateNode[];
28
+ };
29
+ export type TextNode = {
30
+ type: "text";
31
+ value: string;
32
+ start?: number;
33
+ end?: number;
34
+ };
35
+ export type TemplateNode = ElementNode | TextNode;
36
+ export type TextBinding = {
37
+ kind: "text";
38
+ path: number[];
39
+ expression: string;
40
+ };
41
+ export type ClassBinding = {
42
+ kind: "class";
43
+ path: number[];
44
+ className: string;
45
+ expression: string;
46
+ };
47
+ export type EventBinding = {
48
+ kind: "event";
49
+ path: number[];
50
+ eventName: string;
51
+ handler: string;
52
+ };
53
+ export type AttributeBinding = {
54
+ kind: "attr";
55
+ path: number[];
56
+ name: string;
57
+ expression: string;
58
+ };
59
+ export type StyleBinding = {
60
+ kind: "style";
61
+ path: number[];
62
+ name: string;
63
+ expression: string;
64
+ };
65
+ export type RefBinding = {
66
+ kind: "ref";
67
+ path: number[];
68
+ expression: string;
69
+ };
70
+ export type ModelBinding = {
71
+ kind: "model";
72
+ path: number[];
73
+ property: "value" | "checked";
74
+ expression: string;
75
+ };
76
+ export type ListBinding = {
77
+ kind: "list";
78
+ path: number[];
79
+ each: string;
80
+ itemName: string;
81
+ key: string;
82
+ templateHtml: string;
83
+ bindings: ClientBinding[];
84
+ };
85
+ export type ConditionalBinding = {
86
+ kind: "if";
87
+ path: number[];
88
+ test: string;
89
+ templateHtml: string;
90
+ bindings: ClientBinding[];
91
+ };
92
+ export type ClientBinding = TextBinding | ClassBinding | EventBinding | AttributeBinding | StyleBinding | RefBinding | ModelBinding | ListBinding | ConditionalBinding;
93
+ export type StoreDefinition = {
94
+ name: string;
95
+ initial: string;
96
+ };
97
+ export type HydrationBoundary = {
98
+ path: number[];
99
+ id: string;
100
+ idKind?: "expression" | "static";
101
+ strategy?: "load" | "idle" | "visible" | "media" | "interaction";
102
+ media?: string;
103
+ interaction?: string;
104
+ rootMargin?: string;
105
+ };
106
+ export type ComponentProp = {
107
+ name: string;
108
+ expression: string;
109
+ };
110
+ export type ComponentBoundary = {
111
+ path: number[];
112
+ name: string;
113
+ props: ComponentProp[];
114
+ stores: StoreDefinition[];
115
+ };
116
+ export type TemplateDirective = {
117
+ kind: "for";
118
+ path: number[];
119
+ each: string;
120
+ key: string;
121
+ itemName: string;
122
+ } | {
123
+ kind: "if";
124
+ path: number[];
125
+ test: string;
126
+ } | {
127
+ kind: "store";
128
+ path: number[];
129
+ stores: StoreDefinition[];
130
+ } | {
131
+ kind: "event";
132
+ path: number[];
133
+ eventName: string;
134
+ handler: string;
135
+ } | {
136
+ kind: "component";
137
+ path: number[];
138
+ name: string;
139
+ props: ComponentProp[];
140
+ stores: StoreDefinition[];
141
+ } | {
142
+ kind: "await";
143
+ path: number[];
144
+ value: string;
145
+ thenName: string;
146
+ fallback?: string;
147
+ error?: string;
148
+ reorder?: "preserve" | "resolve";
149
+ } | {
150
+ kind: "hydrate";
151
+ path: number[];
152
+ id: string;
153
+ idKind?: "expression" | "static";
154
+ strategy?: "load" | "idle" | "visible" | "media" | "interaction";
155
+ media?: string;
156
+ interaction?: string;
157
+ rootMargin?: string;
158
+ };
159
+ export type TemplateIr = {
160
+ kind: "template";
161
+ root: ElementNode;
162
+ directives: TemplateDirective[];
163
+ };
164
+ export type CompiledTemplate = {
165
+ source: string;
166
+ ir: TemplateIr;
167
+ root: ElementNode;
168
+ client: {
169
+ templateHtml: string;
170
+ bindings: ClientBinding[];
171
+ stores: StoreDefinition[];
172
+ hydrationBoundaries: HydrationBoundary[];
173
+ components: ComponentBoundary[];
174
+ };
175
+ };
176
+ export type LoweringContext = {
177
+ bindings: ClientBinding[];
178
+ stores: StoreDefinition[];
179
+ hydrationBoundaries: HydrationBoundary[];
180
+ components: ComponentBoundary[];
181
+ };
182
+ export type GenerateClientModuleOptions = {
183
+ reactive?: boolean;
184
+ defaultScopeName?: string;
185
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,40 @@
1
+ import type { Attribute, ElementNode, HydrationBoundary, TemplateNode } from "./types.js";
2
+ export { escapeHtml } from "../html-escape.js";
3
+ export declare const expressionPattern: RegExp;
4
+ export declare const identifierNamePattern: RegExp;
5
+ export declare const identifierPattern: RegExp;
6
+ export type TextExpressionSegment = {
7
+ kind: "text";
8
+ value: string;
9
+ start: number;
10
+ end: number;
11
+ } | {
12
+ kind: "expression";
13
+ value: string;
14
+ start: number;
15
+ end: number;
16
+ };
17
+ export declare const textExpressionSegments: (value: string) => TextExpressionSegment[];
18
+ export declare const readExpressionAttribute: (value: string | true) => string | undefined;
19
+ export declare const attrExpression: (node: ElementNode, name: string) => string | undefined;
20
+ export declare const attrString: (node: ElementNode, name: string) => string | undefined;
21
+ export declare const isHydrationAttribute: (name: string) => boolean;
22
+ export declare const isKnownHydrationAttribute: (name: string) => boolean;
23
+ export declare const automaticHydrationId: (path: readonly number[]) => string;
24
+ export declare const hydrationBoundaryFor: (node: ElementNode, path: readonly number[]) => HydrationBoundary | undefined;
25
+ export declare const childPathEntries: (children: readonly TemplateNode[], basePath: readonly number[]) => Array<{
26
+ child: TemplateNode;
27
+ path: number[];
28
+ }>;
29
+ export declare const isForNode: (node: TemplateNode) => node is ElementNode;
30
+ export declare const isStoreNode: (node: TemplateNode) => node is ElementNode;
31
+ export declare const itemNameFromKey: (key: string) => string;
32
+ export declare const renderableChildren: (node: ElementNode) => TemplateNode[];
33
+ export declare const escapeMarker: (value: unknown) => string;
34
+ export declare const readPath: (scope: Record<string, unknown>, expression: string) => unknown;
35
+ export declare const serializeStaticAttr: (attr: Attribute) => string;
36
+ export declare const voidElementNames: Set<string>;
37
+ export declare const isVoidElement: (node: ElementNode) => boolean;
38
+ export declare const expressionToScopeAccess: (expression: string, locals?: ReadonlySet<string>, scopeName?: string) => string;
39
+ export declare const jsString: (value: string) => string;
40
+ export declare const jsOptionalPropertyAccess: (objectExpression: string, propertyName: string) => string;
@@ -0,0 +1,185 @@
1
+ import { evaluateExpression, expressionToJs } from "./expression.js";
2
+ import { escapeHtml } from "../html-escape.js";
3
+ export { escapeHtml } from "../html-escape.js";
4
+ export const expressionPattern = /\{([^{}]+)\}/g;
5
+ export const identifierNamePattern = /^[A-Za-z_$][\w$]*$/;
6
+ export const identifierPattern = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/;
7
+ const findExpressionEnd = (value, start) => {
8
+ let depth = 0;
9
+ let quote;
10
+ let escaped = false;
11
+ for (let index = start; index < value.length; index++) {
12
+ const char = value[index];
13
+ if (escaped) {
14
+ escaped = false;
15
+ continue;
16
+ }
17
+ if (quote) {
18
+ if (char === "\\") {
19
+ escaped = true;
20
+ continue;
21
+ }
22
+ if (quote === "`" && char === "$" && value[index + 1] === "{") {
23
+ depth++;
24
+ index++;
25
+ continue;
26
+ }
27
+ if (quote === "`" && char === "}" && depth > 0) {
28
+ depth--;
29
+ continue;
30
+ }
31
+ if (char === quote) {
32
+ quote = undefined;
33
+ }
34
+ continue;
35
+ }
36
+ if (char === `"` || char === "'" || char === "`") {
37
+ quote = char;
38
+ continue;
39
+ }
40
+ if (char === "{") {
41
+ depth++;
42
+ continue;
43
+ }
44
+ if (char === "}") {
45
+ if (depth === 0) {
46
+ return index;
47
+ }
48
+ depth--;
49
+ }
50
+ }
51
+ return -1;
52
+ };
53
+ export const textExpressionSegments = (value) => {
54
+ const segments = [];
55
+ let cursor = 0;
56
+ while (cursor < value.length) {
57
+ const start = value.indexOf("{", cursor);
58
+ if (start < 0) {
59
+ segments.push({ kind: "text", value: value.slice(cursor), start: cursor, end: value.length });
60
+ break;
61
+ }
62
+ if (start > cursor) {
63
+ segments.push({ kind: "text", value: value.slice(cursor, start), start: cursor, end: start });
64
+ }
65
+ const end = findExpressionEnd(value, start + 1);
66
+ if (end < 0) {
67
+ segments.push({ kind: "text", value: value.slice(start), start, end: value.length });
68
+ break;
69
+ }
70
+ segments.push({ kind: "expression", value: value.slice(start + 1, end).trim(), start, end: end + 1 });
71
+ cursor = end + 1;
72
+ }
73
+ return segments;
74
+ };
75
+ export const readExpressionAttribute = (value) => {
76
+ if (value === true) {
77
+ return undefined;
78
+ }
79
+ const trimmed = value.trim();
80
+ if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) {
81
+ return undefined;
82
+ }
83
+ return trimmed.slice(1, -1).trim();
84
+ };
85
+ export const attrExpression = (node, name) => {
86
+ const attr = node.attrs.find((candidate) => candidate.name === name);
87
+ return attr ? readExpressionAttribute(attr.value) : undefined;
88
+ };
89
+ export const attrString = (node, name) => {
90
+ const attr = node.attrs.find((candidate) => candidate.name === name);
91
+ return typeof attr?.value === "string" ? attr.value : undefined;
92
+ };
93
+ export const isHydrationAttribute = (name) => name === "hydrate" || name.startsWith("hydrate:");
94
+ const hydrationStrategies = new Set(["load", "idle", "visible", "media", "interaction"]);
95
+ export const isKnownHydrationAttribute = (name) => name === "hydrate" ||
96
+ name === "hydrate:id" ||
97
+ (name.startsWith("hydrate:") && hydrationStrategies.has(name.slice("hydrate:".length)));
98
+ export const automaticHydrationId = (path) => `td-h-${path.length === 0 ? "root" : path.join("-")}`;
99
+ export const hydrationBoundaryFor = (node, path) => {
100
+ const explicitId = attrExpression(node, "hydrate:id");
101
+ const strategyAttr = node.attrs.find((attr) => attr.name.startsWith("hydrate:") && attr.name !== "hydrate:id" && hydrationStrategies.has(attr.name.slice(8)));
102
+ const hasAutoHydrate = node.attrs.some((attr) => attr.name === "hydrate" || (attr.name.startsWith("hydrate:") && attr.name !== "hydrate:id"));
103
+ if (!explicitId && !hasAutoHydrate) {
104
+ return undefined;
105
+ }
106
+ const boundary = explicitId
107
+ ? { path: [...path], id: explicitId }
108
+ : { path: [...path], id: automaticHydrationId(path), idKind: "static" };
109
+ if (!strategyAttr) {
110
+ return boundary;
111
+ }
112
+ const strategy = strategyAttr.name.slice(8);
113
+ boundary.strategy = strategy;
114
+ if (strategy === "visible") {
115
+ const rootMargin = typeof strategyAttr.value === "string" ? strategyAttr.value : undefined;
116
+ if (rootMargin) {
117
+ boundary.rootMargin = rootMargin;
118
+ }
119
+ }
120
+ if (strategy === "interaction") {
121
+ const interaction = typeof strategyAttr.value === "string" ? strategyAttr.value : undefined;
122
+ if (interaction) {
123
+ boundary.interaction = interaction;
124
+ }
125
+ }
126
+ if (strategy === "media") {
127
+ const media = typeof strategyAttr.value === "string" ? strategyAttr.value : undefined;
128
+ if (media) {
129
+ boundary.media = media;
130
+ }
131
+ }
132
+ return boundary;
133
+ };
134
+ export const childPathEntries = (children, basePath) => {
135
+ let domIndex = 0;
136
+ return children.map((child) => {
137
+ const path = child.type === "element" && (child.tagName === "store" || child.tagName === "for")
138
+ ? [...basePath]
139
+ : [...basePath, domIndex++];
140
+ return { child, path };
141
+ });
142
+ };
143
+ export const isForNode = (node) => node.type === "element" && node.tagName === "for";
144
+ export const isStoreNode = (node) => node.type === "element" && node.tagName === "store";
145
+ export const itemNameFromKey = (key) => {
146
+ const [itemName] = key.split(".");
147
+ return itemName && identifierPattern.test(itemName) ? itemName : "item";
148
+ };
149
+ export const renderableChildren = (node) => node.children.filter((child) => child.type !== "text" || child.value.length > 0);
150
+ export const escapeMarker = (value) => String(value ?? "")
151
+ .replaceAll("--", "- -")
152
+ .replaceAll(">", "&gt;");
153
+ export const readPath = (scope, expression) => {
154
+ return evaluateExpression(expression, scope);
155
+ };
156
+ export const serializeStaticAttr = (attr) => {
157
+ if (attr.value === true) {
158
+ return ` ${attr.name}`;
159
+ }
160
+ return ` ${attr.name}="${escapeHtml(attr.value)}"`;
161
+ };
162
+ export const voidElementNames = new Set([
163
+ "area",
164
+ "base",
165
+ "br",
166
+ "col",
167
+ "embed",
168
+ "hr",
169
+ "img",
170
+ "input",
171
+ "link",
172
+ "meta",
173
+ "param",
174
+ "source",
175
+ "track",
176
+ "wbr",
177
+ ]);
178
+ export const isVoidElement = (node) => voidElementNames.has(node.tagName);
179
+ export const expressionToScopeAccess = (expression, locals = new Set(), scopeName = "scope") => {
180
+ return expressionToJs(expression, locals, scopeName);
181
+ };
182
+ export const jsString = (value) => JSON.stringify(value);
183
+ export const jsOptionalPropertyAccess = (objectExpression, propertyName) => identifierNamePattern.test(propertyName)
184
+ ? `${objectExpression}?.${propertyName}`
185
+ : `${objectExpression}?.[${jsString(propertyName)}]`;
@@ -0,0 +1,2 @@
1
+ import type { ElementNode, TemplateWhitespacePolicy } from "./types.js";
2
+ export declare const applyTemplateWhitespace: (root: ElementNode, policy: TemplateWhitespacePolicy) => ElementNode;
@@ -0,0 +1,66 @@
1
+ import { textExpressionSegments } from "./utils.js";
2
+ const protectedTextElements = new Set([
3
+ "iframe",
4
+ "listing",
5
+ "noembed",
6
+ "noframes",
7
+ "plaintext",
8
+ "pre",
9
+ "script",
10
+ "style",
11
+ "textarea",
12
+ "title",
13
+ "xmp",
14
+ ]);
15
+ const asciiWhitespaceOnly = /^[\t\n\f\r ]+$/;
16
+ const internalFormattingLine = /[\t\f\r ]*(?:\r\n?|\n)[\t\n\f\r ]*/g;
17
+ const condenseStaticTextValue = (value) => {
18
+ if (!value.includes("\n") && !value.includes("\r"))
19
+ return value;
20
+ if (asciiWhitespaceOnly.test(value))
21
+ return " ";
22
+ return value.replace(internalFormattingLine, " ");
23
+ };
24
+ const condenseTextValue = (value) => textExpressionSegments(value)
25
+ .map((segment) => segment.kind === "text" ? condenseStaticTextValue(segment.value) : value.slice(segment.start, segment.end))
26
+ .join("");
27
+ const childForeignContent = (parent, tagName) => {
28
+ if (parent === "svg" && tagName === "foreignobject")
29
+ return "html";
30
+ if (parent === "html" && tagName === "svg")
31
+ return "svg";
32
+ if (parent === "html" && tagName === "math")
33
+ return "math";
34
+ return parent;
35
+ };
36
+ const staticXmlSpace = (node) => {
37
+ const attribute = node.attrs.find((candidate) => candidate.name === "xml:space");
38
+ return attribute?.value === "preserve" || attribute?.value === "default" ? attribute.value : undefined;
39
+ };
40
+ const transformNode = (node, context) => {
41
+ if (node.type === "text") {
42
+ const text = { ...node };
43
+ if (!context.protectedHtmlText && context.xmlSpace !== "preserve")
44
+ text.value = condenseTextValue(text.value);
45
+ return text;
46
+ }
47
+ const tagName = node.tagName.toLowerCase();
48
+ const foreignContent = childForeignContent(context.foreignContent, tagName);
49
+ const entersForeignContent = context.foreignContent === "html" && foreignContent !== "html";
50
+ const xmlSpace = foreignContent === "html"
51
+ ? "default"
52
+ : (staticXmlSpace(node) ?? (entersForeignContent ? "default" : context.xmlSpace));
53
+ const nextContext = {
54
+ protectedHtmlText: context.protectedHtmlText || protectedTextElements.has(tagName),
55
+ foreignContent,
56
+ xmlSpace,
57
+ };
58
+ return {
59
+ ...node,
60
+ attrs: node.attrs.map((attribute) => ({ ...attribute })),
61
+ children: node.children.map((child) => transformNode(child, nextContext)),
62
+ };
63
+ };
64
+ export const applyTemplateWhitespace = (root, policy) => policy === "condense"
65
+ ? transformNode(root, { protectedHtmlText: false, foreignContent: "html", xmlSpace: "default" })
66
+ : root;
@@ -0,0 +1 @@
1
+ export * from "./compiler/index.js";
@@ -0,0 +1 @@
1
+ export * from "./compiler/index.js";
@@ -0,0 +1 @@
1
+ export declare const timingSafeEqual: (left: unknown, right: string) => Promise<boolean>;
@@ -0,0 +1,26 @@
1
+ const encoder = new TextEncoder();
2
+ const xorEqual = (left, right) => {
3
+ let diff = left.length ^ right.length;
4
+ const length = Math.max(left.length, right.length);
5
+ for (let index = 0; index < length; index++) {
6
+ diff |= (left[index] ?? 0) ^ (right[index] ?? 0);
7
+ }
8
+ return diff === 0;
9
+ };
10
+ const digest = async (value) => {
11
+ if (!globalThis.crypto?.subtle) {
12
+ return undefined;
13
+ }
14
+ return new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", encoder.encode(value)));
15
+ };
16
+ export const timingSafeEqual = async (left, right) => {
17
+ if (typeof left !== "string") {
18
+ return false;
19
+ }
20
+ const leftDigest = await digest(left);
21
+ const rightDigest = await digest(right);
22
+ if (leftDigest && rightDigest) {
23
+ return xorEqual(leftDigest, rightDigest);
24
+ }
25
+ return xorEqual(encoder.encode(left), encoder.encode(right));
26
+ };
@@ -0,0 +1,44 @@
1
+ export type CookieOptions = {
2
+ path?: string;
3
+ domain?: string;
4
+ maxAge?: number;
5
+ expires?: Date;
6
+ httpOnly?: boolean;
7
+ secure?: boolean;
8
+ sameSite?: "Strict" | "Lax" | "None";
9
+ };
10
+ export type Session<Data extends Record<string, unknown> = Record<string, unknown>> = {
11
+ id: string;
12
+ data: Data;
13
+ };
14
+ export type MemorySessionStorageOptions = {
15
+ cookieName?: string;
16
+ cookie?: CookieOptions;
17
+ id?: () => string;
18
+ };
19
+ export type CookieSessionStorageOptions = {
20
+ secret: string;
21
+ verificationSecrets?: readonly string[];
22
+ maxAgeMs?: number;
23
+ now?: () => number;
24
+ cookieName?: string;
25
+ cookie?: CookieOptions;
26
+ id?: () => string;
27
+ };
28
+ export declare const signCookieValue: (value: string, secret: string) => string;
29
+ export declare const verifySignedCookieValue: (signedValue: string | undefined, secret: string) => string | undefined;
30
+ export declare const parseCookies: (header: string | null | undefined) => Record<string, string>;
31
+ export declare const serializeCookie: (name: string, value: string, options?: CookieOptions) => string;
32
+ export declare const createMemorySessionStorage: <Data extends Record<string, unknown> = Record<string, unknown>>(options?: MemorySessionStorageOptions) => {
33
+ createSession: (data: Data) => Promise<Session<Data>>;
34
+ getSession: (cookieHeader: string | null | undefined) => Promise<Session<Data>>;
35
+ commitSession: (session: Session<Data>) => Promise<string>;
36
+ regenerateSession: (session: Session<Data>) => Promise<Session<Data>>;
37
+ destroySession: (session: Session<Data>) => Promise<string>;
38
+ };
39
+ export declare const createCookieSessionStorage: <Data extends Record<string, unknown> = Record<string, unknown>>(options: CookieSessionStorageOptions) => {
40
+ createSession: (data: Data) => Promise<Session<Data>>;
41
+ getSession: (cookieHeader: string | null | undefined) => Promise<Session<Data>>;
42
+ commitSession: (session: Session<Data>) => Promise<string>;
43
+ destroySession: (_session: Session<Data>) => Promise<string>;
44
+ };