@ecopages/ecopages-jsx 0.2.0-alpha.37 → 0.2.0-alpha.39
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 +18 -4
- package/src/eco-embed.d.ts +11 -0
- package/src/eco-embed.js +11 -0
- package/src/ecopages-jsx-radiant-ssr-policy.d.ts +0 -1
- package/src/ecopages-jsx-radiant-ssr-policy.js +1 -12
- package/src/ecopages-jsx-renderer.d.ts +1 -0
- package/src/ecopages-jsx-renderer.js +94 -92
- package/src/ecopages-jsx.plugin.d.ts +1 -0
- package/src/ecopages-jsx.plugin.js +17 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ecopages/ecopages-jsx",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.39",
|
|
4
4
|
"description": "JSX integration plugin for Ecopages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ecopages",
|
|
@@ -11,6 +11,20 @@
|
|
|
11
11
|
"main": "./src/ecopages-jsx.plugin.js",
|
|
12
12
|
"types": "./src/ecopages-jsx.plugin.d.ts",
|
|
13
13
|
"type": "module",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"default": "./src/ecopages-jsx.plugin.js",
|
|
17
|
+
"types": "./src/ecopages-jsx.plugin.d.ts"
|
|
18
|
+
},
|
|
19
|
+
"./eco-embed": {
|
|
20
|
+
"default": "./src/eco-embed.js",
|
|
21
|
+
"types": "./src/eco-embed.d.ts"
|
|
22
|
+
},
|
|
23
|
+
"./eco-embed.ts": {
|
|
24
|
+
"default": "./src/eco-embed.js",
|
|
25
|
+
"types": "./src/eco-embed.d.ts"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
14
28
|
"repository": {
|
|
15
29
|
"type": "git",
|
|
16
30
|
"url": "https://github.com/ecopages/ecopages.git",
|
|
@@ -21,8 +35,8 @@
|
|
|
21
35
|
"vfile": "^6.0.3"
|
|
22
36
|
},
|
|
23
37
|
"peerDependencies": {
|
|
24
|
-
"@ecopages/core": "0.2.0-alpha.
|
|
25
|
-
"@ecopages/jsx": "0.3.0-alpha.
|
|
26
|
-
"@ecopages/radiant": "0.3.0-alpha.
|
|
38
|
+
"@ecopages/core": "0.2.0-alpha.39",
|
|
39
|
+
"@ecopages/jsx": "0.3.0-alpha.25",
|
|
40
|
+
"@ecopages/radiant": "0.3.0-alpha.25"
|
|
27
41
|
}
|
|
28
42
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { EcoComponent, EcoEmbedProps as CoreEcoEmbedProps } from '@ecopages/core';
|
|
2
|
+
import type { JsxRenderable } from '@ecopages/jsx';
|
|
3
|
+
/**
|
|
4
|
+
* Props for the Ecopages JSX-owned `EcoEmbed` adapter.
|
|
5
|
+
*/
|
|
6
|
+
export type EcoEmbedProps<TComponent extends EcoComponent> = CoreEcoEmbedProps<TComponent>;
|
|
7
|
+
/**
|
|
8
|
+
* Renders a foreign or same-integration eco component from an Ecopages JSX
|
|
9
|
+
* file without forcing inline mixed-JSX authoring.
|
|
10
|
+
*/
|
|
11
|
+
export declare function EcoEmbed<TComponent extends EcoComponent>({ component, props, children, }: EcoEmbedProps<TComponent>): JsxRenderable;
|
package/src/eco-embed.js
ADDED
|
@@ -21,7 +21,6 @@ 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;
|
|
25
24
|
/**
|
|
26
25
|
* Converts one Radiant custom-element instance into trusted SSR markup.
|
|
27
26
|
*
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { createMarkupNodeLike } from "@ecopages/jsx";
|
|
2
2
|
import {
|
|
3
3
|
createServerHydrationBindingState,
|
|
4
|
-
isServerRenderHydrationActive,
|
|
5
4
|
withServerHydrationBindingState
|
|
6
5
|
} from "@ecopages/jsx/server";
|
|
7
6
|
class EcopagesJsxRadiantSsrPolicy {
|
|
@@ -33,16 +32,6 @@ class EcopagesJsxRadiantSsrPolicy {
|
|
|
33
32
|
}
|
|
34
33
|
return runtimeModules.withServerRadiantElementSsrRuntime(render);
|
|
35
34
|
}
|
|
36
|
-
withPreparedRuntime(render) {
|
|
37
|
-
if (!this.enabled) {
|
|
38
|
-
return render();
|
|
39
|
-
}
|
|
40
|
-
const runtimeModules = EcopagesJsxRadiantSsrPolicy.runtimeModules;
|
|
41
|
-
if (!runtimeModules) {
|
|
42
|
-
return render();
|
|
43
|
-
}
|
|
44
|
-
return runtimeModules.withServerRadiantElementSsrRuntime(render);
|
|
45
|
-
}
|
|
46
35
|
/**
|
|
47
36
|
* Converts one Radiant custom-element instance into trusted SSR markup.
|
|
48
37
|
*
|
|
@@ -59,7 +48,7 @@ class EcopagesJsxRadiantSsrPolicy {
|
|
|
59
48
|
withServerHydrationBindingState(
|
|
60
49
|
createServerHydrationBindingState(),
|
|
61
50
|
() => renderBridge.renderHostToString({
|
|
62
|
-
mode:
|
|
51
|
+
mode: "hydrate"
|
|
63
52
|
})
|
|
64
53
|
)
|
|
65
54
|
);
|
|
@@ -42,5 +42,6 @@ export declare class EcopagesJsxRenderer extends IntegrationRenderer<JsxRenderab
|
|
|
42
42
|
renderToResponse<P = any>(view: EcoComponent<P>, props: P, ctx: RenderToResponseContext): Promise<Response>;
|
|
43
43
|
private renderJsx;
|
|
44
44
|
private withCustomElementRenderHook;
|
|
45
|
+
private withPreparedRadiantRuntime;
|
|
45
46
|
private createIntrinsicCustomElementRenderHook;
|
|
46
47
|
}
|
|
@@ -116,118 +116,120 @@ class EcopagesJsxRenderer extends IntegrationRenderer {
|
|
|
116
116
|
return isMdxFile(filePath, this.mdxExtensions);
|
|
117
117
|
}
|
|
118
118
|
async importPageFile(file, options) {
|
|
119
|
-
await this.
|
|
120
|
-
|
|
121
|
-
|
|
119
|
+
return await this.withPreparedRadiantRuntime(async () => {
|
|
120
|
+
const module = await super.importPageFile(file, options);
|
|
121
|
+
return this.isMdxFile(file) ? normalizeMdxPageModule(file, module) : module;
|
|
122
|
+
});
|
|
122
123
|
}
|
|
123
124
|
async render(options) {
|
|
124
|
-
await this.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
125
|
+
return await this.withPreparedRadiantRuntime(
|
|
126
|
+
() => this.renderSession.withActiveScope(async () => {
|
|
127
|
+
try {
|
|
128
|
+
return await this.renderPageWithDocumentShell({
|
|
129
|
+
page: {
|
|
130
|
+
component: options.Page,
|
|
131
|
+
props: {
|
|
132
|
+
...options.pageProps,
|
|
133
|
+
locals: options.pageLocals
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
layout: options.Layout ? {
|
|
137
|
+
component: options.Layout,
|
|
138
|
+
props: {
|
|
139
|
+
...options.pageProps,
|
|
140
|
+
locals: options.locals
|
|
141
|
+
}
|
|
142
|
+
} : void 0,
|
|
143
|
+
htmlTemplate: options.HtmlTemplate,
|
|
144
|
+
metadata: options.metadata,
|
|
145
|
+
pageProps: options.pageProps ?? {}
|
|
146
|
+
});
|
|
147
|
+
} catch (error) {
|
|
148
|
+
throw this.createRenderError("Error rendering page", error);
|
|
149
|
+
}
|
|
150
|
+
})
|
|
151
|
+
);
|
|
150
152
|
}
|
|
151
153
|
async renderComponent(input) {
|
|
152
|
-
await this.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
return await this.withPreparedRadiantRuntime(
|
|
155
|
+
() => this.renderSession.withActiveScope(async () => {
|
|
156
|
+
const assetFrame = this.renderSession.beginCollectedAssetFrame();
|
|
157
|
+
try {
|
|
158
|
+
if (typeof input.component !== "function") {
|
|
159
|
+
throw new TypeError("JSX renderer expected a callable component.");
|
|
160
|
+
}
|
|
161
|
+
const component = input.component;
|
|
162
|
+
const componentProps = input.children === void 0 ? input.props : {
|
|
163
|
+
...input.props,
|
|
164
|
+
children: typeof input.children === "string" ? createMarkupNodeLike(input.children) : input.children
|
|
165
|
+
};
|
|
166
|
+
const content = await this.withCustomElementRenderHook(() => component(componentProps));
|
|
167
|
+
const rendered = await this.renderJsx(content);
|
|
168
|
+
const queuedForeignSubtreeResolution = await this.resolveOwnedForeignSubtreeHtml(
|
|
169
|
+
rendered.html,
|
|
170
|
+
this.getQueuedForeignSubtreeResolutionContext(
|
|
171
|
+
input
|
|
172
|
+
)
|
|
173
|
+
);
|
|
174
|
+
const componentAssets = input.component.config?.dependencies && typeof this.assetProcessingService?.processDependencies === "function" ? await this.processComponentDependencies([input.component]) : [];
|
|
175
|
+
const assets = this.htmlTransformer.dedupeProcessedAssets([
|
|
176
|
+
...this.renderSession.endCollectedAssetFrame(assetFrame),
|
|
177
|
+
...queuedForeignSubtreeResolution.assets,
|
|
178
|
+
...componentAssets
|
|
179
|
+
]);
|
|
180
|
+
return {
|
|
181
|
+
html: queuedForeignSubtreeResolution.html,
|
|
182
|
+
canAttachAttributes: true,
|
|
183
|
+
rootTag: this.getRootTagName(queuedForeignSubtreeResolution.html),
|
|
184
|
+
integrationName: this.name,
|
|
185
|
+
assets
|
|
186
|
+
};
|
|
187
|
+
} catch (error) {
|
|
188
|
+
this.renderSession.endCollectedAssetFrame(assetFrame);
|
|
189
|
+
throw this.createRenderError("Error rendering component", error);
|
|
158
190
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
...input.props,
|
|
162
|
-
children: typeof input.children === "string" ? createMarkupNodeLike(input.children) : input.children
|
|
163
|
-
};
|
|
164
|
-
const componentAssetsFromRender = [];
|
|
165
|
-
const content = await this.withCustomElementRenderHook(
|
|
166
|
-
componentAssetsFromRender,
|
|
167
|
-
() => component(componentProps)
|
|
168
|
-
);
|
|
169
|
-
this.renderSession.recordCollectedAssets(componentAssetsFromRender);
|
|
170
|
-
const rendered = await this.renderJsx(content);
|
|
171
|
-
const queuedForeignSubtreeResolution = await this.resolveOwnedForeignSubtreeHtml(
|
|
172
|
-
rendered.html,
|
|
173
|
-
this.getQueuedForeignSubtreeResolutionContext(input)
|
|
174
|
-
);
|
|
175
|
-
const componentAssets = input.component.config?.dependencies && typeof this.assetProcessingService?.processDependencies === "function" ? await this.processComponentDependencies([input.component]) : [];
|
|
176
|
-
const assets = this.htmlTransformer.dedupeProcessedAssets([
|
|
177
|
-
...this.renderSession.endCollectedAssetFrame(assetFrame),
|
|
178
|
-
...queuedForeignSubtreeResolution.assets,
|
|
179
|
-
...componentAssets
|
|
180
|
-
]);
|
|
181
|
-
return {
|
|
182
|
-
html: queuedForeignSubtreeResolution.html,
|
|
183
|
-
canAttachAttributes: true,
|
|
184
|
-
rootTag: this.getRootTagName(queuedForeignSubtreeResolution.html),
|
|
185
|
-
integrationName: this.name,
|
|
186
|
-
assets
|
|
187
|
-
};
|
|
188
|
-
} catch (error) {
|
|
189
|
-
this.renderSession.endCollectedAssetFrame(assetFrame);
|
|
190
|
-
throw this.createRenderError("Error rendering component", error);
|
|
191
|
-
}
|
|
192
|
-
});
|
|
191
|
+
})
|
|
192
|
+
);
|
|
193
193
|
}
|
|
194
194
|
async renderToResponse(view, props, ctx) {
|
|
195
|
-
await this.
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
195
|
+
return await this.withPreparedRadiantRuntime(
|
|
196
|
+
() => this.renderSession.withActiveScope(async () => {
|
|
197
|
+
try {
|
|
198
|
+
if (typeof view !== "function") {
|
|
199
|
+
throw new TypeError("JSX renderer expected a callable view component.");
|
|
200
|
+
}
|
|
201
|
+
const viewComponent = view;
|
|
202
|
+
return await this.renderViewWithDocumentShell({
|
|
203
|
+
view: viewComponent,
|
|
204
|
+
props,
|
|
205
|
+
ctx,
|
|
206
|
+
layout: viewComponent.config?.layout
|
|
207
|
+
});
|
|
208
|
+
} catch (error) {
|
|
209
|
+
throw this.createRenderError("Error rendering view", error);
|
|
200
210
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
view: viewComponent,
|
|
204
|
-
props,
|
|
205
|
-
ctx,
|
|
206
|
-
layout: viewComponent.config?.layout
|
|
207
|
-
});
|
|
208
|
-
} catch (error) {
|
|
209
|
-
throw this.createRenderError("Error rendering view", error);
|
|
210
|
-
}
|
|
211
|
-
});
|
|
211
|
+
})
|
|
212
|
+
);
|
|
212
213
|
}
|
|
213
214
|
async renderJsx(value) {
|
|
214
215
|
const collectedAssets = [];
|
|
215
|
-
const html = await this.
|
|
216
|
-
() => this.withCustomElementRenderHook(collectedAssets, () => renderToString(value, { mode: "hydrate" }))
|
|
217
|
-
);
|
|
216
|
+
const html = await this.withCustomElementRenderHook(() => renderToString(value));
|
|
218
217
|
const dedupedAssets = this.renderSession.recordCollectedAssets(collectedAssets);
|
|
219
218
|
return {
|
|
220
219
|
assets: dedupedAssets,
|
|
221
220
|
html
|
|
222
221
|
};
|
|
223
222
|
}
|
|
224
|
-
async withCustomElementRenderHook(
|
|
225
|
-
await this.radiantSsrPolicy.prepareRuntime();
|
|
223
|
+
async withCustomElementRenderHook(render) {
|
|
226
224
|
return await this.radiantSsrPolicy.withRuntime(
|
|
227
|
-
() => withServerCustomElementRenderHook(this.createIntrinsicCustomElementRenderHook(
|
|
225
|
+
() => withServerCustomElementRenderHook(this.createIntrinsicCustomElementRenderHook(), render)
|
|
228
226
|
);
|
|
229
227
|
}
|
|
230
|
-
|
|
228
|
+
async withPreparedRadiantRuntime(render) {
|
|
229
|
+
await this.radiantSsrPolicy.prepareRuntime();
|
|
230
|
+
return await render();
|
|
231
|
+
}
|
|
232
|
+
createIntrinsicCustomElementRenderHook() {
|
|
231
233
|
return ({ instance }) => {
|
|
232
234
|
return instance ? this.radiantSsrPolicy.renderIntrinsicElementMarkup(instance) : void 0;
|
|
233
235
|
};
|
|
@@ -18,6 +18,7 @@ export declare class EcopagesJsxPlugin extends IntegrationPlugin<JsxRenderable>
|
|
|
18
18
|
rendererModules?: unknown;
|
|
19
19
|
}): EcopagesJsxRenderer;
|
|
20
20
|
constructor(options?: EcopagesJsxPluginOptions);
|
|
21
|
+
private getDependencies;
|
|
21
22
|
/** Ensures MDX build hooks are ready before Ecopages collects contributions. */
|
|
22
23
|
prepareBuildContributions(): Promise<void>;
|
|
23
24
|
/**
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
IntegrationPlugin
|
|
3
3
|
} from "@ecopages/core/plugins/integration-plugin";
|
|
4
|
+
import { AssetFactory } from "@ecopages/core/services/asset-processing-service";
|
|
4
5
|
import { ECOPAGES_JSX_PLUGIN_NAME } from "./ecopages-jsx.constants.js";
|
|
5
6
|
import {
|
|
6
7
|
appendMdxExtensions,
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
resolveMdxCompilerOptions
|
|
10
11
|
} from "./ecopages-jsx-mdx.js";
|
|
11
12
|
import { EcopagesJsxRenderer } from "./ecopages-jsx-renderer.js";
|
|
13
|
+
const RADIANT_HYDRATOR_SCRIPT_ID = "ecopages-jsx-radiant-hydrator";
|
|
12
14
|
const resolvePluginOptions = (options) => {
|
|
13
15
|
const { extensions: userExtensions, radiant, mdx, ...baseConfig } = options ?? {};
|
|
14
16
|
const extensions = [...userExtensions ?? [".tsx"]];
|
|
@@ -62,6 +64,21 @@ class EcopagesJsxPlugin extends IntegrationPlugin {
|
|
|
62
64
|
this.mdxEnabled = mdxEnabled;
|
|
63
65
|
this.mdxExtensions = mdxExtensions;
|
|
64
66
|
this.mdxCompilerOptions = mdxCompilerOptions;
|
|
67
|
+
if (this.includeRadiant) {
|
|
68
|
+
this.integrationDependencies.unshift(...this.getDependencies());
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
getDependencies() {
|
|
72
|
+
return [
|
|
73
|
+
AssetFactory.createNodeModuleScript({
|
|
74
|
+
position: "head",
|
|
75
|
+
importPath: "@ecopages/radiant/client/install-hydrator",
|
|
76
|
+
bundle: false,
|
|
77
|
+
attributes: {
|
|
78
|
+
"data-eco-script-id": RADIANT_HYDRATOR_SCRIPT_ID
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
];
|
|
65
82
|
}
|
|
66
83
|
/** Ensures MDX build hooks are ready before Ecopages collects contributions. */
|
|
67
84
|
async prepareBuildContributions() {
|