@ecopages/ecopages-jsx 0.2.0-alpha.34 → 0.2.0-alpha.35

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecopages/ecopages-jsx",
3
- "version": "0.2.0-alpha.34",
3
+ "version": "0.2.0-alpha.35",
4
4
  "description": "JSX integration plugin for Ecopages",
5
5
  "keywords": [
6
6
  "ecopages",
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "peerDependencies": {
24
24
  "@ecopages/core": "0.2.0-alpha.34",
25
- "@ecopages/jsx": "0.3.0-alpha.19",
26
- "@ecopages/radiant": "0.3.0-alpha.19"
25
+ "@ecopages/jsx": "0.3.0-alpha.21",
26
+ "@ecopages/radiant": "0.3.0-alpha.21"
27
27
  }
28
28
  }
@@ -21,6 +21,7 @@ export declare class EcopagesJsxRadiantSsrPolicy {
21
21
  * Runs one render inside Radiant's server runtime when the policy is enabled.
22
22
  */
23
23
  withRuntime<T>(render: () => T): Promise<T>;
24
+ withPreparedRuntime<T>(render: () => T): T;
24
25
  /**
25
26
  * Converts one Radiant custom-element instance into trusted SSR markup.
26
27
  *
@@ -1,5 +1,3 @@
1
- import path from "node:path";
2
- import { fileURLToPath, pathToFileURL } from "node:url";
3
1
  import { createMarkupNodeLike } from "@ecopages/jsx";
4
2
  import { isServerRenderHydrationActive } from "@ecopages/jsx/server";
5
3
  class EcopagesJsxRadiantSsrPolicy {
@@ -31,6 +29,16 @@ class EcopagesJsxRadiantSsrPolicy {
31
29
  }
32
30
  return runtimeModules.withServerRadiantElementSsrRuntime(render);
33
31
  }
32
+ withPreparedRuntime(render) {
33
+ if (!this.enabled) {
34
+ return render();
35
+ }
36
+ const runtimeModules = EcopagesJsxRadiantSsrPolicy.runtimeModules;
37
+ if (!runtimeModules) {
38
+ return render();
39
+ }
40
+ return runtimeModules.withServerRadiantElementSsrRuntime(render);
41
+ }
34
42
  /**
35
43
  * Converts one Radiant custom-element instance into trusted SSR markup.
36
44
  *
@@ -51,16 +59,14 @@ class EcopagesJsxRadiantSsrPolicy {
51
59
  }
52
60
  async ensureRuntimeInstalled() {
53
61
  if (!EcopagesJsxRadiantSsrPolicy.runtimeModulesPromise) {
54
- const radiantLightDomShimEntry = fileURLToPath(
55
- import.meta.resolve("@ecopages/radiant/server/light-dom-shim")
56
- );
57
- const radiantPackageRoot = path.dirname(path.dirname(path.dirname(radiantLightDomShimEntry)));
58
- const radiantElementSsrRuntimeModuleUrl = pathToFileURL(
59
- path.join(radiantPackageRoot, "dist/server/radiant-element-ssr-bridge.js")
62
+ const radiantLightDomShimEntry = import.meta.resolve("@ecopages/radiant/server/light-dom-shim");
63
+ const radiantElementSsrRuntimeModuleUrl = new URL(
64
+ "./radiant-element-ssr-bridge.js",
65
+ radiantLightDomShimEntry
60
66
  ).href;
61
67
  EcopagesJsxRadiantSsrPolicy.runtimeModulesPromise = Promise.all([
62
68
  import(radiantElementSsrRuntimeModuleUrl),
63
- import("@ecopages/radiant/server/light-dom-shim")
69
+ import(radiantLightDomShimEntry)
64
70
  ]).then(([radiantElementSsrRuntimeModule, lightDomShimModule2]) => {
65
71
  const modules = {
66
72
  installLightDomShim: lightDomShimModule2.installLightDomShim,
@@ -1,5 +1,6 @@
1
1
  import type { ComponentRenderInput, ComponentRenderResult, EcoComponent, IntegrationRendererRenderOptions, RouteRendererBody } from '@ecopages/core';
2
2
  import { IntegrationRenderer, type RenderToResponseContext, type RouteModuleLoadOptions } from '@ecopages/core/route-renderer/integration-renderer';
3
+ import type { ForeignChildRuntime } from '@ecopages/core/route-renderer/component-render-context';
3
4
  import { type JsxRenderable } from '@ecopages/jsx';
4
5
  import { type EcopagesJsxMdxPageModule } from './ecopages-jsx-mdx.js';
5
6
  import type { EcopagesJsxRendererOptions } from './ecopages-jsx.types.js';
@@ -15,6 +16,7 @@ export declare class EcopagesJsxRenderer extends IntegrationRenderer<JsxRenderab
15
16
  private readonly mdxExtensions;
16
17
  private readonly renderSession;
17
18
  private readonly radiantSsrPolicy;
19
+ private normalizeForeignChildProps;
18
20
  /**
19
21
  * Re-renders queued JSX children inside the owning renderer so nested custom
20
22
  * elements and queued foreign subtrees contribute assets to the same frame.
@@ -27,6 +29,10 @@ export declare class EcopagesJsxRenderer extends IntegrationRenderer<JsxRenderab
27
29
  * additional browser assets while also replacing placeholder tokens.
28
30
  */
29
31
  private resolveOwnedForeignSubtreeHtml;
32
+ protected createForeignChildRuntime(options: {
33
+ renderInput: ComponentRenderInput;
34
+ rendererCache: Map<string, IntegrationRenderer<any>>;
35
+ }): ForeignChildRuntime;
30
36
  constructor({ appConfig, assetProcessingService, resolvedIntegrationDependencies, jsxConfig, runtimeOrigin, }: EcopagesJsxRendererOptions);
31
37
  /** Returns whether the requested page file should be treated as MDX. */
32
38
  isMdxFile(filePath: string): boolean;
@@ -15,6 +15,25 @@ class EcopagesJsxRenderer extends IntegrationRenderer {
15
15
  mdxExtensions;
16
16
  renderSession;
17
17
  radiantSsrPolicy;
18
+ normalizeForeignChildProps(props) {
19
+ if (!("children" in props)) {
20
+ return props;
21
+ }
22
+ const children = props.children;
23
+ if (children === void 0 || typeof children === "string") {
24
+ return props;
25
+ }
26
+ if (typeof children === "object" && children !== null && "nodeType" in children && typeof children.nodeType === "number" && "outerHTML" in children && typeof children.outerHTML === "string") {
27
+ return {
28
+ ...props,
29
+ children: children.outerHTML
30
+ };
31
+ }
32
+ return {
33
+ ...props,
34
+ children: renderToString(children)
35
+ };
36
+ }
18
37
  /**
19
38
  * Re-renders queued JSX children inside the owning renderer so nested custom
20
39
  * elements and queued foreign subtrees contribute assets to the same frame.
@@ -60,6 +79,19 @@ class EcopagesJsxRenderer extends IntegrationRenderer {
60
79
  renderQueuedChildren: async (children, _runtimeContext, queuedResolutionsByToken, resolveToken) => this.renderQueuedForeignSubtreeChildren(children, queuedResolutionsByToken, resolveToken)
61
80
  });
62
81
  }
82
+ createForeignChildRuntime(options) {
83
+ const runtime = super.createForeignChildRuntime(options);
84
+ const interceptForeignChild = runtime.interceptForeignChild;
85
+ const interceptForeignChildSync = runtime.interceptForeignChildSync;
86
+ const wrapInput = (input) => ({
87
+ ...input,
88
+ props: input.targetIntegration && input.targetIntegration !== this.name ? this.normalizeForeignChildProps(input.props) : input.props
89
+ });
90
+ return {
91
+ interceptForeignChild: interceptForeignChild ? (input) => interceptForeignChild(wrapInput(input)) : void 0,
92
+ interceptForeignChildSync: interceptForeignChildSync ? (input) => interceptForeignChildSync(wrapInput(input)) : void 0
93
+ };
94
+ }
63
95
  constructor({
64
96
  appConfig,
65
97
  assetProcessingService,
@@ -89,6 +121,7 @@ class EcopagesJsxRenderer extends IntegrationRenderer {
89
121
  return this.isMdxFile(file) ? normalizeMdxPageModule(file, module) : module;
90
122
  }
91
123
  async render(options) {
124
+ await this.radiantSsrPolicy.prepareRuntime();
92
125
  return await this.renderSession.withActiveScope(async () => {
93
126
  try {
94
127
  return await this.renderPageWithDocumentShell({
@@ -116,6 +149,7 @@ class EcopagesJsxRenderer extends IntegrationRenderer {
116
149
  });
117
150
  }
118
151
  async renderComponent(input) {
152
+ await this.radiantSsrPolicy.prepareRuntime();
119
153
  return await this.renderSession.withActiveScope(async () => {
120
154
  const assetFrame = this.renderSession.beginCollectedAssetFrame();
121
155
  try {
@@ -158,6 +192,7 @@ class EcopagesJsxRenderer extends IntegrationRenderer {
158
192
  });
159
193
  }
160
194
  async renderToResponse(view, props, ctx) {
195
+ await this.radiantSsrPolicy.prepareRuntime();
161
196
  return await this.renderSession.withActiveScope(async () => {
162
197
  try {
163
198
  if (typeof view !== "function") {
@@ -177,7 +212,10 @@ class EcopagesJsxRenderer extends IntegrationRenderer {
177
212
  }
178
213
  async renderJsx(value) {
179
214
  const collectedAssets = [];
180
- const html = await this.withCustomElementRenderHook(collectedAssets, () => renderToString(value));
215
+ const html = await this.withCustomElementRenderHook(
216
+ collectedAssets,
217
+ () => renderToString(value, { mode: "hydrate" })
218
+ );
181
219
  const dedupedAssets = this.renderSession.recordCollectedAssets(collectedAssets);
182
220
  return {
183
221
  assets: dedupedAssets,
package/CHANGELOG.md DELETED
@@ -1,36 +0,0 @@
1
- # Changelog
2
-
3
- ## [UNRELEASED] -- TBD
4
-
5
- ### Features
6
-
7
- - Added the Ecopages JSX integration with optional Radiant runtime support and optional MDX routes compiled against `@ecopages/jsx`.
8
-
9
- ### Bug Fixes
10
-
11
- - Moved Ecopages JSX intrinsic custom-element asset bookkeeping into the active JSX SSR render scope and reinstalls the Radiant light-DOM shim whenever SSR runtime setup reruns so nested renders stay aligned with the current server render contract.
12
- - Fixed intrinsic custom-element SSR asset hooks to fall back cleanly when they run after the active JSX render frame has already unwound, avoiding spurious server warnings during docs renders.
13
- - Fixed lazy Ecopages JSX custom-element dependencies to stay as standalone assets instead of being folded into page-owned bundles, restoring trigger-driven loading for docs components like `theme-toggle`.
14
- - Fixed Ecopages JSX page-owned browser bundles to inline their JSX and Radiant runtime imports while skipping separate intrinsic custom-element script tags when the current component tree already imports those scripts.
15
- - Fixed intrinsic custom-element script suppression to honor dependency-declared script ownership instead of relying only on source import scanning.
16
- - Fixed Radiant custom-element SSR bridging so `prop:` values like array props render through the server host bridge without requiring wrapper-level attribute serialization fallbacks.
17
- - Aligned the Ecopages JSX browser runtime bundle with the upstream `@ecopages/jsx` runtime shipped by current alpha releases.
18
- - Aligned Ecopages JSX peer dependency ranges with the current `@ecopages/jsx` and `@ecopages/radiant` alpha releases.
19
- - Aligned Radiant SSR and hydration wiring with the public `@ecopages/radiant/server/render-component` and `@ecopages/radiant/client/hydrator` entrypoints so JSX apps install an explicit client hydrator bootstrap instead of relying on implicit side effects.
20
- - Updated the Ecopages JSX Radiant browser runtime for the `RadiantElement` and `RadiantController` API surface and switched the explicit hydrator bootstrap to `@ecopages/radiant/client/install-hydrator`.
21
- - Fixed Radiant SSR page inspection to install the light-DOM shim before JSX page modules are imported outside the normal render pass.
22
- - Restored direct `EcopagesJsxPlugin` construction so the exported class still accepts the public plugin options shape.
23
- - Aligned Ecopages JSX intrinsic custom-element loading with explicit `dependencies.scripts` ownership instead of implicit tag-to-script discovery.
24
- - Removed implicit JSX integration-generated intrinsic custom-element browser entries so client custom-element loading now follows the normal asset pipeline.
25
- - Fixed the Ecopages JSX browser runtime bundle so Radiant custom-element scripts no longer fail on a duplicate `jsxDEV` export cycle.
26
- - Fixed Ecopages JSX foreign-subtree payload compatibility coverage and removed the plugin/renderer integration-name import cycle.
27
-
28
- ### Refactoring
29
-
30
- - Removed the shared JSX runtime bundle service and browser import-map asset in favor of per-script browser entries that prepend `@ecopages/radiant/client/install-hydrator` only when Radiant SSR is enabled.
31
- - Replaced Ecopages JSX renderer static and post-construction configuration with instance-owned renderer wiring and extracted shared plugin and renderer types into a dedicated module.
32
- - Extracted JSX renderer SSR asset-frame scope handling into a dedicated render-session module.
33
-
34
- ### Tests
35
-
36
- - Added renderer-level coverage for the foreign-subtree payload compatibility contract.