@ecopages/ecopages-jsx 0.2.0-alpha.33 → 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.33",
3
+ "version": "0.2.0-alpha.35",
4
4
  "description": "JSX integration plugin for Ecopages",
5
5
  "keywords": [
6
6
  "ecopages",
@@ -21,8 +21,8 @@
21
21
  "vfile": "^6.0.3"
22
22
  },
23
23
  "peerDependencies": {
24
- "@ecopages/core": "0.2.0-alpha.33",
25
- "@ecopages/jsx": "0.3.0-alpha.18",
26
- "@ecopages/radiant": "0.3.0-alpha.18"
24
+ "@ecopages/core": "0.2.0-alpha.34",
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,