@zenithbuild/runtime 0.7.5 → 0.7.7

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/dist/render.js CHANGED
@@ -12,20 +12,21 @@ export function _applyMarkerValue(nodes, marker, value) {
12
12
  try {
13
13
  const node = nodes[i];
14
14
  if (marker.kind === 'text') {
15
+ const textPath = `${markerPath}.text`;
15
16
  if (node && node.nodeType === 8) {
16
- _applyCommentMarkerValue(node, value, `${markerPath}.text`);
17
+ _applyCommentMarkerValue(node, value, textPath);
17
18
  continue;
18
19
  }
19
20
  if (_isStructuralFragment(value)) {
20
- _mountStructuralFragment(node, value, `${markerPath}.text`);
21
+ _mountStructuralFragment(node, value, textPath);
21
22
  continue;
22
23
  }
23
- const html = _renderFragmentValue(value, `${markerPath}.text`);
24
+ const html = _renderFragmentValue(value, textPath);
24
25
  if (html !== null) {
25
26
  node.innerHTML = html;
26
27
  }
27
28
  else {
28
- node.textContent = _coerceText(value, `${markerPath}.text`);
29
+ node.textContent = _coerceText(value, textPath);
29
30
  }
30
31
  continue;
31
32
  }
@@ -45,7 +46,7 @@ export function _applyMarkerValue(nodes, marker, value) {
45
46
  path: marker.kind === 'attr'
46
47
  ? `${markerPath}.attr.${marker.attr}`
47
48
  : `${markerPath}.${marker.kind}`,
48
- hint: 'Check the binding value type and marker mapping.',
49
+ hint: 'Check binding value and marker mapping.',
49
50
  docsLink: DOCS_LINKS.markerTable,
50
51
  source: marker.source
51
52
  });
@@ -105,16 +106,7 @@ function _ensureCommentPlaceholderEnd(anchor) {
105
106
  return end;
106
107
  }
107
108
  function _clearCommentPlaceholderContent(anchor) {
108
- if (anchor.__z_unmounts) {
109
- for (let i = 0; i < anchor.__z_unmounts.length; i++) {
110
- try {
111
- anchor.__z_unmounts[i]();
112
- }
113
- catch {
114
- }
115
- }
116
- }
117
- anchor.__z_unmounts = [];
109
+ _runUnmounts(anchor);
118
110
  const end = _ensureCommentPlaceholderEnd(anchor);
119
111
  if (!end) {
120
112
  return anchor;
@@ -130,21 +122,7 @@ function _clearCommentPlaceholderContent(anchor) {
130
122
  return end;
131
123
  }
132
124
  function _mountStructuralFragmentIntoCommentRange(anchor, value, rootPath = 'renderable') {
133
- let region = anchor.__z_fragment_region;
134
- if (region && anchor.__z_fragment_region_active) {
135
- try {
136
- region.update(value, { parent: anchor.parentNode, insertBefore: anchor.__z_range_end, rootPath });
137
- }
138
- catch (error) {
139
- rethrowZenithRuntimeError(error, {
140
- phase: 'render',
141
- code: 'FRAGMENT_MOUNT_FAILED',
142
- message: 'Fragment update failed',
143
- path: rootPath,
144
- hint: 'Verify fragment values and nested renderable arrays.',
145
- docsLink: DOCS_LINKS.markerTable
146
- });
147
- }
125
+ if (_tryUpdateFragmentTarget(anchor, value, anchor.parentNode, anchor.__z_range_end, rootPath)) {
148
126
  return;
149
127
  }
150
128
  const end = _clearCommentPlaceholderContent(anchor);
@@ -152,75 +130,15 @@ function _mountStructuralFragmentIntoCommentRange(anchor, value, rootPath = 'ren
152
130
  if (!parent) {
153
131
  return;
154
132
  }
155
- region = createFragmentRegion();
156
- anchor.__z_fragment_region = region;
157
- anchor.__z_fragment_region_active = true;
158
- try {
159
- region.mount(value, { parent, insertBefore: end, rootPath });
160
- }
161
- catch (error) {
162
- rethrowZenithRuntimeError(error, {
163
- phase: 'render',
164
- code: 'FRAGMENT_MOUNT_FAILED',
165
- message: 'Fragment mount failed',
166
- path: rootPath,
167
- hint: 'Verify fragment values and nested renderable arrays.',
168
- docsLink: DOCS_LINKS.markerTable
169
- });
170
- }
171
- anchor.__z_unmounts = [() => {
172
- anchor.__z_fragment_region_active = false;
173
- region.destroy();
174
- }];
133
+ _mountFragmentRegion(anchor, value, parent, end, rootPath);
175
134
  }
176
135
  function _mountStructuralFragment(container, value, rootPath = 'renderable') {
177
- let region = container.__z_fragment_region;
178
- if (region && container.__z_fragment_region_active) {
179
- try {
180
- region.update(value, { parent: container, insertBefore: null, rootPath });
181
- }
182
- catch (error) {
183
- rethrowZenithRuntimeError(error, {
184
- phase: 'render',
185
- code: 'FRAGMENT_MOUNT_FAILED',
186
- message: 'Fragment update failed',
187
- path: rootPath,
188
- hint: 'Verify fragment values and nested renderable arrays.',
189
- docsLink: DOCS_LINKS.markerTable
190
- });
191
- }
136
+ if (_tryUpdateFragmentTarget(container, value, container, null, rootPath)) {
192
137
  return;
193
138
  }
194
- if (container.__z_unmounts) {
195
- for (let i = 0; i < container.__z_unmounts.length; i++) {
196
- try {
197
- container.__z_unmounts[i]();
198
- }
199
- catch {
200
- }
201
- }
202
- }
139
+ _runUnmounts(container);
203
140
  container.innerHTML = '';
204
- region = createFragmentRegion();
205
- container.__z_fragment_region = region;
206
- container.__z_fragment_region_active = true;
207
- try {
208
- region.mount(value, { parent: container, insertBefore: null, rootPath });
209
- }
210
- catch (error) {
211
- rethrowZenithRuntimeError(error, {
212
- phase: 'render',
213
- code: 'FRAGMENT_MOUNT_FAILED',
214
- message: 'Fragment mount failed',
215
- path: rootPath,
216
- hint: 'Verify fragment values and nested renderable arrays.',
217
- docsLink: DOCS_LINKS.markerTable
218
- });
219
- }
220
- container.__z_unmounts = [() => {
221
- container.__z_fragment_region_active = false;
222
- region.destroy();
223
- }];
141
+ _mountFragmentRegion(container, value, container, null, rootPath);
224
142
  }
225
143
  export function _coerceText(value, path = 'renderable') {
226
144
  if (value === null || value === undefined || value === false || value === true) {
@@ -232,7 +150,7 @@ export function _coerceText(value, path = 'renderable') {
232
150
  code: 'NON_RENDERABLE_VALUE',
233
151
  message: `Zenith Render Error: non-renderable function at ${path}. Use map() to render fields.`,
234
152
  path,
235
- hint: 'Convert functions into explicit event handlers or renderable text.',
153
+ hint: 'Convert functions to handlers or text.',
236
154
  docsLink: DOCS_LINKS.expressionScope
237
155
  });
238
156
  }
@@ -242,7 +160,7 @@ export function _coerceText(value, path = 'renderable') {
242
160
  code: 'NON_RENDERABLE_VALUE',
243
161
  message: `Zenith Render Error: non-renderable object at ${path}. Use map() to render fields.`,
244
162
  path,
245
- hint: 'Use map() to render object fields into nodes.',
163
+ hint: 'Use map() to render object fields.',
246
164
  docsLink: DOCS_LINKS.expressionScope
247
165
  });
248
166
  }
@@ -279,21 +197,22 @@ function _escapeHtml(input) {
279
197
  .replace(/'/g, '&#39;');
280
198
  }
281
199
  function _applyAttribute(node, attrName, value) {
282
- if (typeof attrName === 'string' && attrName.toLowerCase() === 'innerhtml') {
200
+ const normalizedAttrName = typeof attrName === 'string' ? attrName.toLowerCase() : '';
201
+ if (normalizedAttrName === 'innerhtml') {
283
202
  throwZenithRuntimeError({
284
203
  phase: 'bind',
285
204
  code: 'UNSAFE_HTML_REQUIRES_EXPLICIT_BOUNDARY',
286
205
  message: 'innerHTML bindings are forbidden in Zenith',
287
206
  path: `attr:${attrName}`,
288
- hint: 'Use unsafeHTML={value} for explicit raw HTML insertion, or embedded markup expressions for compiler-owned fragments.'
207
+ hint: 'Use unsafeHTML={value} or compiler-owned markup fragments.'
289
208
  });
290
209
  }
291
- if (typeof attrName === 'string' && attrName.toLowerCase() === 'unsafehtml') {
210
+ if (normalizedAttrName === 'unsafehtml') {
292
211
  node.innerHTML = value === null || value === undefined || value === false ? '' : String(value);
293
212
  return;
294
213
  }
295
214
  if (attrName === 'class' || attrName === 'className') {
296
- const classValue = value === null || value === undefined || value === false ? '' : String(value);
215
+ const classValue = _isEmptyAttrValue(value) ? '' : String(value);
297
216
  if (node && node.namespaceURI === SVG_NAMESPACE && typeof node.setAttribute === 'function') {
298
217
  node.setAttribute('class', classValue);
299
218
  return;
@@ -302,25 +221,13 @@ function _applyAttribute(node, attrName, value) {
302
221
  return;
303
222
  }
304
223
  if (attrName === 'style') {
305
- if (value === null || value === undefined || value === false) {
224
+ const styleValue = _resolveStyleAttributeValue(value);
225
+ if (styleValue === null) {
306
226
  node.removeAttribute('style');
307
- return;
308
227
  }
309
- if (typeof value === 'string') {
310
- node.setAttribute('style', value);
311
- return;
312
- }
313
- if (typeof value === 'object') {
314
- const entries = Object.entries(value);
315
- let styleText = '';
316
- for (let i = 0; i < entries.length; i++) {
317
- const [key, rawValue] = entries[i];
318
- styleText += `${key}: ${rawValue};`;
319
- }
320
- node.setAttribute('style', styleText);
321
- return;
228
+ else {
229
+ node.setAttribute('style', styleValue);
322
230
  }
323
- node.setAttribute('style', String(value));
324
231
  return;
325
232
  }
326
233
  if (BOOLEAN_ATTRIBUTES.has(attrName)) {
@@ -332,9 +239,84 @@ function _applyAttribute(node, attrName, value) {
332
239
  }
333
240
  return;
334
241
  }
335
- if (value === null || value === undefined || value === false) {
242
+ if (_isEmptyAttrValue(value)) {
336
243
  node.removeAttribute(attrName);
337
244
  return;
338
245
  }
339
246
  node.setAttribute(attrName, String(value));
340
247
  }
248
+ function _runUnmounts(target) {
249
+ if (!target.__z_unmounts) {
250
+ return;
251
+ }
252
+ for (let i = 0; i < target.__z_unmounts.length; i++) {
253
+ try {
254
+ target.__z_unmounts[i]();
255
+ }
256
+ catch {
257
+ }
258
+ }
259
+ target.__z_unmounts = [];
260
+ }
261
+ function _updateFragmentRegion(region, value, parent, insertBefore, rootPath) {
262
+ try {
263
+ region.update(value, { parent, insertBefore, rootPath });
264
+ }
265
+ catch (error) {
266
+ _throwFragmentMountFailure(error, rootPath, 'Fragment update failed');
267
+ }
268
+ }
269
+ function _mountFragmentRegion(target, value, parent, insertBefore, rootPath) {
270
+ const region = createFragmentRegion();
271
+ target.__z_fragment_region = region;
272
+ target.__z_fragment_region_active = true;
273
+ try {
274
+ region.mount(value, { parent, insertBefore, rootPath });
275
+ }
276
+ catch (error) {
277
+ _throwFragmentMountFailure(error, rootPath, 'Fragment mount failed');
278
+ }
279
+ target.__z_unmounts = [() => {
280
+ target.__z_fragment_region_active = false;
281
+ region.destroy();
282
+ }];
283
+ }
284
+ function _tryUpdateFragmentTarget(target, value, parent, insertBefore, rootPath) {
285
+ const region = target.__z_fragment_region;
286
+ if (!region || !target.__z_fragment_region_active) {
287
+ return false;
288
+ }
289
+ _updateFragmentRegion(region, value, parent, insertBefore, rootPath);
290
+ return true;
291
+ }
292
+ function _throwFragmentMountFailure(error, path, message) {
293
+ rethrowZenithRuntimeError(error, {
294
+ phase: 'render',
295
+ code: 'FRAGMENT_MOUNT_FAILED',
296
+ message,
297
+ path,
298
+ hint: 'Verify fragment values and nested arrays.',
299
+ docsLink: DOCS_LINKS.markerTable
300
+ });
301
+ }
302
+ function _resolveStyleAttributeValue(value) {
303
+ if (_isEmptyAttrValue(value)) {
304
+ return null;
305
+ }
306
+ if (typeof value === 'string') {
307
+ return value;
308
+ }
309
+ if (value && typeof value === 'object') {
310
+ const entries = Object.entries(value);
311
+ let styleText = '';
312
+ for (let i = 0; i < entries.length; i++) {
313
+ const [key, rawValue] = entries[i];
314
+ styleText += `${key}: ${rawValue};`;
315
+ }
316
+ return styleText;
317
+ }
318
+ return String(value);
319
+ }
320
+ function _isEmptyAttrValue(value) {
321
+ return value === null || value === undefined || value === false;
322
+ }
@@ -0,0 +1,20 @@
1
+ export function normalizeRuntimeTemplateProfile(profile: any): "default" | "production-emitted" | "production-emitted-with-presence";
2
+ export function buildRuntimeTemplateProfile({ profile, normalizeNewlines, readRuntimeSourceFile }: {
3
+ profile: any;
4
+ normalizeNewlines: any;
5
+ readRuntimeSourceFile: any;
6
+ }): {
7
+ profile: "default" | "production-emitted" | "production-emitted-with-presence";
8
+ source: any;
9
+ contributors: {
10
+ id: string;
11
+ sourceFile: string;
12
+ bytes: number;
13
+ }[];
14
+ coverageBytes: number;
15
+ };
16
+ export const RUNTIME_TEMPLATE_PROFILES: Readonly<{
17
+ DEFAULT: "default";
18
+ PRODUCTION_EMITTED: "production-emitted";
19
+ PRODUCTION_EMITTED_WITH_PRESENCE: "production-emitted-with-presence";
20
+ }>;
@@ -0,0 +1,141 @@
1
+ const DEFAULT_RUNTIME_MODULES = Object.freeze([
2
+ { sourceFile: 'reactivity-core.js', contributorId: 'reactivity-core.js' },
3
+ { sourceFile: 'side-effect-scope.js', contributorId: 'side-effect-scope.js' },
4
+ { sourceFile: 'effect-utils.js', contributorId: 'effect-utils.js' },
5
+ { sourceFile: 'effect-scheduler.js', contributorId: 'effect-scheduler.js' },
6
+ { sourceFile: 'effect-runtime.js', contributorId: 'effect-runtime.js' },
7
+ { sourceFile: 'mount-runtime.js', contributorId: 'mount-runtime.js' },
8
+ { sourceFile: 'zeneffect.js', contributorId: 'zeneffect.js' },
9
+ { sourceFile: 'ref.js', contributorId: 'ref.js' },
10
+ { sourceFile: 'env.js', contributorId: 'env.js' },
11
+ { sourceFile: 'platform.js', contributorId: 'platform.js' },
12
+ { sourceFile: 'presence.js', contributorId: 'presence.js' },
13
+ { sourceFile: 'signal.js', contributorId: 'signal.js' },
14
+ { sourceFile: 'state.js', contributorId: 'state.js' },
15
+ { sourceFile: 'diagnostics.js', contributorId: 'diagnostics.js' },
16
+ { sourceFile: 'cleanup.js', contributorId: 'cleanup.js' },
17
+ { sourceFile: 'template-parser.js', contributorId: 'template-parser.js' },
18
+ { sourceFile: 'markup.js', contributorId: 'markup.js' },
19
+ { sourceFile: 'payload.js', contributorId: 'payload.js' },
20
+ { sourceFile: 'expressions.js', contributorId: 'expressions.js' },
21
+ { sourceFile: 'render.js', contributorId: 'render.js' },
22
+ { sourceFile: 'fragment-patch.js', contributorId: 'fragment-patch.js' },
23
+ { sourceFile: 'scanner.js', contributorId: 'scanner.js' },
24
+ { sourceFile: 'events.js', contributorId: 'events.js' },
25
+ { sourceFile: 'hydrate.js', contributorId: 'hydrate.js' }
26
+ ]);
27
+ const PRODUCTION_EMITTED_RUNTIME_MODULES = Object.freeze([
28
+ { sourceFile: 'reactivity-core.js', contributorId: 'reactivity-core.js' },
29
+ { sourceFile: 'side-effect-scope.js', contributorId: 'side-effect-scope.js' },
30
+ { sourceFile: 'effect-utils.js', contributorId: 'effect-utils.js' },
31
+ { sourceFile: 'effect-scheduler.js', contributorId: 'effect-scheduler.js' },
32
+ { sourceFile: 'effect-runtime.js', contributorId: 'effect-runtime.js' },
33
+ { sourceFile: 'mount-runtime.js', contributorId: 'mount-runtime.js' },
34
+ { sourceFile: 'zeneffect.js', contributorId: 'zeneffect.js' },
35
+ { sourceFile: 'ref.js', contributorId: 'ref.js' },
36
+ { sourceFile: 'env.js', contributorId: 'env.js' },
37
+ { sourceFile: 'platform.js', contributorId: 'platform.js' },
38
+ { sourceFile: 'signal.js', contributorId: 'signal.js' },
39
+ { sourceFile: 'state.js', contributorId: 'state.js' },
40
+ { sourceFile: 'diagnostics-production.js', contributorId: 'diagnostics.js' },
41
+ { sourceFile: 'cleanup.js', contributorId: 'cleanup.js' },
42
+ { sourceFile: 'template-parser.js', contributorId: 'template-parser.js' },
43
+ { sourceFile: 'markup.js', contributorId: 'markup.js' },
44
+ { sourceFile: 'payload.js', contributorId: 'payload.js' },
45
+ { sourceFile: 'expressions.js', contributorId: 'expressions.js' },
46
+ { sourceFile: 'render.js', contributorId: 'render.js' },
47
+ { sourceFile: 'fragment-patch.js', contributorId: 'fragment-patch.js' },
48
+ { sourceFile: 'scanner.js', contributorId: 'scanner.js' },
49
+ { sourceFile: 'events.js', contributorId: 'events.js' },
50
+ { sourceFile: 'hydrate.js', contributorId: 'hydrate.js' }
51
+ ]);
52
+ const PRODUCTION_EMITTED_WITH_PRESENCE_RUNTIME_MODULES = Object.freeze([
53
+ { sourceFile: 'reactivity-core.js', contributorId: 'reactivity-core.js' },
54
+ { sourceFile: 'side-effect-scope.js', contributorId: 'side-effect-scope.js' },
55
+ { sourceFile: 'effect-utils.js', contributorId: 'effect-utils.js' },
56
+ { sourceFile: 'effect-scheduler.js', contributorId: 'effect-scheduler.js' },
57
+ { sourceFile: 'effect-runtime.js', contributorId: 'effect-runtime.js' },
58
+ { sourceFile: 'mount-runtime.js', contributorId: 'mount-runtime.js' },
59
+ { sourceFile: 'zeneffect.js', contributorId: 'zeneffect.js' },
60
+ { sourceFile: 'ref.js', contributorId: 'ref.js' },
61
+ { sourceFile: 'env.js', contributorId: 'env.js' },
62
+ { sourceFile: 'platform.js', contributorId: 'platform.js' },
63
+ { sourceFile: 'presence.js', contributorId: 'presence.js' },
64
+ { sourceFile: 'signal.js', contributorId: 'signal.js' },
65
+ { sourceFile: 'state.js', contributorId: 'state.js' },
66
+ { sourceFile: 'diagnostics-production.js', contributorId: 'diagnostics.js' },
67
+ { sourceFile: 'cleanup.js', contributorId: 'cleanup.js' },
68
+ { sourceFile: 'template-parser.js', contributorId: 'template-parser.js' },
69
+ { sourceFile: 'markup.js', contributorId: 'markup.js' },
70
+ { sourceFile: 'payload.js', contributorId: 'payload.js' },
71
+ { sourceFile: 'expressions.js', contributorId: 'expressions.js' },
72
+ { sourceFile: 'render.js', contributorId: 'render.js' },
73
+ { sourceFile: 'fragment-patch.js', contributorId: 'fragment-patch.js' },
74
+ { sourceFile: 'scanner.js', contributorId: 'scanner.js' },
75
+ { sourceFile: 'events.js', contributorId: 'events.js' },
76
+ { sourceFile: 'hydrate.js', contributorId: 'hydrate.js' }
77
+ ]);
78
+ export const RUNTIME_TEMPLATE_PROFILES = Object.freeze({
79
+ DEFAULT: 'default',
80
+ PRODUCTION_EMITTED: 'production-emitted',
81
+ PRODUCTION_EMITTED_WITH_PRESENCE: 'production-emitted-with-presence'
82
+ });
83
+ function stripImports(source) {
84
+ return source
85
+ .replace(/^\s*import\s+[^;]+;\s*$/gm, '')
86
+ .replace(/^\s*export\s+\{[^}]+\}\s+from\s+['"]\.[^'"]+['"];\s*$/gm, '')
87
+ .trim();
88
+ }
89
+ export function normalizeRuntimeTemplateProfile(profile) {
90
+ if (profile === RUNTIME_TEMPLATE_PROFILES.PRODUCTION_EMITTED) {
91
+ return RUNTIME_TEMPLATE_PROFILES.PRODUCTION_EMITTED;
92
+ }
93
+ if (profile === RUNTIME_TEMPLATE_PROFILES.PRODUCTION_EMITTED_WITH_PRESENCE) {
94
+ return RUNTIME_TEMPLATE_PROFILES.PRODUCTION_EMITTED_WITH_PRESENCE;
95
+ }
96
+ return RUNTIME_TEMPLATE_PROFILES.DEFAULT;
97
+ }
98
+ function runtimeModulesForProfile(profile) {
99
+ switch (normalizeRuntimeTemplateProfile(profile)) {
100
+ case RUNTIME_TEMPLATE_PROFILES.PRODUCTION_EMITTED:
101
+ return PRODUCTION_EMITTED_RUNTIME_MODULES;
102
+ case RUNTIME_TEMPLATE_PROFILES.PRODUCTION_EMITTED_WITH_PRESENCE:
103
+ return PRODUCTION_EMITTED_WITH_PRESENCE_RUNTIME_MODULES;
104
+ default:
105
+ return DEFAULT_RUNTIME_MODULES;
106
+ }
107
+ }
108
+ export function buildRuntimeTemplateProfile({ profile, normalizeNewlines, readRuntimeSourceFile }) {
109
+ const resolvedProfile = normalizeRuntimeTemplateProfile(profile);
110
+ const modules = runtimeModulesForProfile(resolvedProfile);
111
+ const segments = [];
112
+ const contributors = [];
113
+ let coverageBytes = 0;
114
+ for (let i = 0; i < modules.length; i += 1) {
115
+ const entry = modules[i];
116
+ const source = stripImports(readRuntimeSourceFile(entry.sourceFile));
117
+ if (!source)
118
+ continue;
119
+ segments.push(source);
120
+ const bytes = Buffer.byteLength(source, 'utf8');
121
+ coverageBytes += bytes;
122
+ contributors.push({
123
+ id: entry.contributorId,
124
+ sourceFile: entry.sourceFile,
125
+ bytes
126
+ });
127
+ }
128
+ contributors.sort((left, right) => {
129
+ if (right.bytes !== left.bytes)
130
+ return right.bytes - left.bytes;
131
+ if (left.id !== right.id)
132
+ return left.id.localeCompare(right.id);
133
+ return left.sourceFile.localeCompare(right.sourceFile);
134
+ });
135
+ return {
136
+ profile: resolvedProfile,
137
+ source: normalizeNewlines(segments.join('\n\n')),
138
+ contributors,
139
+ coverageBytes
140
+ };
141
+ }
package/dist/scanner.js CHANGED
@@ -15,8 +15,8 @@ export function createNodeResolver(root) {
15
15
  marker: { type: kind, id: index },
16
16
  path: `selector:${selector}`,
17
17
  hint: isRef
18
- ? 'Use ref + zenMount and ensure the ref is bound in markup before mount.'
19
- : 'Confirm SSR marker attributes and runtime selector tables match.',
18
+ ? 'Use ref + zenMount and bind the ref in markup before mount.'
19
+ : 'Confirm SSR marker attributes and selector tables match.',
20
20
  docsLink: isRef ? DOCS_LINKS.refs : DOCS_LINKS.markerTable,
21
21
  source
22
22
  });
@@ -1,2 +1,8 @@
1
- export function runtimeModuleSource(): string;
1
+ export function runtimeModuleSource(): any;
2
+ export function runtimeModuleProfileSnapshot(profile?: "default"): {
3
+ profile: any;
4
+ source: any;
5
+ contributors: any;
6
+ coverageBytes: any;
7
+ };
2
8
  export function runtimeDevClientSource(): string;
package/dist/template.js CHANGED
@@ -1,35 +1,37 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { dirname, join } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
+ import { buildRuntimeTemplateProfile, RUNTIME_TEMPLATE_PROFILES, normalizeRuntimeTemplateProfile } from './runtime-template-profile.js';
4
5
  const __filename = fileURLToPath(import.meta.url);
5
6
  const __dirname = dirname(__filename);
6
- function normalizeNewlines(value) {
7
- return String(value).replace(/\r\n/g, '\n').replace(/\r/g, '\n');
8
- }
9
- function readRuntimeSourceFile(fileName) {
10
- const fullPath = join(__dirname, fileName);
11
- return normalizeNewlines(readFileSync(fullPath, 'utf8'));
12
- }
13
- function stripImports(source) {
14
- return source
15
- .replace(/^\s*import\s+[^;]+;\s*$/gm, '')
16
- .replace(/^\s*export\s+\{[^}]+\}\s+from\s+['"]\.[^'"]+['"];\s*$/gm, '')
17
- .trim();
18
- }
19
- function buildRuntimeModuleSource() {
20
- const segments = [
21
- 'reactivity-core.js', 'side-effect-scope.js', 'effect-utils.js', 'effect-scheduler.js',
22
- 'effect-runtime.js', 'mount-runtime.js', 'zeneffect.js', 'ref.js', 'env.js',
23
- 'platform.js', 'presence.js', 'signal.js', 'state.js',
24
- 'diagnostics.js', 'cleanup.js', 'template-parser.js', 'markup.js', 'payload.js',
25
- 'expressions.js', 'render.js', 'fragment-patch.js', 'scanner.js', 'events.js', 'hydrate.js'
26
- ].map((fileName) => stripImports(readRuntimeSourceFile(fileName))).filter(Boolean);
27
- return normalizeNewlines(segments.join('\n\n'));
7
+ function normalizeNewlines(value) { return String(value).replace(/\r\n/g, '\n').replace(/\r/g, '\n'); }
8
+ function readRuntimeSourceFile(fileName) { return normalizeNewlines(readFileSync(join(__dirname, fileName), 'utf8')); }
9
+ const runtimeTemplateProfileCache = new Map();
10
+ function resolveRuntimeTemplateProfile(profile) {
11
+ const resolvedProfile = normalizeRuntimeTemplateProfile(profile);
12
+ if (runtimeTemplateProfileCache.has(resolvedProfile))
13
+ return runtimeTemplateProfileCache.get(resolvedProfile);
14
+ const built = buildRuntimeTemplateProfile({
15
+ profile: resolvedProfile,
16
+ normalizeNewlines,
17
+ readRuntimeSourceFile
18
+ });
19
+ runtimeTemplateProfileCache.set(resolvedProfile, built);
20
+ return built;
28
21
  }
29
- const RUNTIME_MODULE_SOURCE = buildRuntimeModuleSource();
22
+ const RUNTIME_MODULE_SOURCE = resolveRuntimeTemplateProfile(RUNTIME_TEMPLATE_PROFILES.DEFAULT).source;
30
23
  export function runtimeModuleSource() {
31
24
  return RUNTIME_MODULE_SOURCE;
32
25
  }
26
+ export function runtimeModuleProfileSnapshot(profile = RUNTIME_TEMPLATE_PROFILES.DEFAULT) {
27
+ const resolved = resolveRuntimeTemplateProfile(profile);
28
+ return {
29
+ profile: resolved.profile,
30
+ source: resolved.source,
31
+ contributors: resolved.contributors.map((entry) => ({ ...entry })),
32
+ coverageBytes: resolved.coverageBytes
33
+ };
34
+ }
33
35
  const RUNTIME_DEV_CLIENT_SOURCE = `(() => {
34
36
  if (typeof window === 'undefined' || typeof document === 'undefined') return;
35
37
  if (window.__zenithDevClientActive === true) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenithbuild/runtime",
3
- "version": "0.7.5",
3
+ "version": "0.7.7",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "exports": {