@ecopages/ecopages-jsx 0.2.0-rc.10 → 0.2.0-rc.11
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 +3 -3
- package/src/ecopages-jsx-mdx.d.ts +0 -1
- package/src/ecopages-jsx-mdx.js +0 -12
- package/src/ecopages-jsx-render-session.d.ts +2 -8
- package/src/ecopages-jsx-render-session.js +2 -29
- package/src/ecopages-jsx-renderer.d.ts +1 -1
- package/src/ecopages-jsx-renderer.js +7 -19
- package/src/ecopages-jsx.plugin.d.ts +5 -8
- package/src/ecopages-jsx.plugin.js +6 -24
- package/src/page-owned-content-script-grouping.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ecopages/ecopages-jsx",
|
|
3
|
-
"version": "0.2.0-rc.
|
|
3
|
+
"version": "0.2.0-rc.11",
|
|
4
4
|
"description": "JSX integration plugin for Ecopages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ecopages",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"directory": "packages/integrations/ecopages-jsx"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@ecopages/mdx": "0.2.0-rc.
|
|
37
|
+
"@ecopages/mdx": "0.2.0-rc.11",
|
|
38
38
|
"@mdx-js/mdx": "^3.1.1",
|
|
39
39
|
"vfile": "^6.0.3"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@ecopages/core": "0.2.0-rc.
|
|
42
|
+
"@ecopages/core": "0.2.0-rc.11",
|
|
43
43
|
"@ecopages/jsx": "^0.3.0-rc.9",
|
|
44
44
|
"@ecopages/radiant": "^0.3.0-rc.9"
|
|
45
45
|
}
|
|
@@ -19,6 +19,5 @@ export interface CreateEcopagesJsxMdxLoaderPluginOptions {
|
|
|
19
19
|
projectRoot: string;
|
|
20
20
|
}
|
|
21
21
|
export declare const createMdxLoaderPlugin: (options: CreateEcopagesJsxMdxLoaderPluginOptions) => EcoBuildPlugin;
|
|
22
|
-
export declare const registerBunMdxPlugin: (options: CreateEcopagesJsxMdxLoaderPluginOptions) => Promise<void>;
|
|
23
22
|
export declare const isMdxFile: (filePath: string, extensions: string[]) => boolean;
|
|
24
23
|
export declare const normalizeMdxPageModule: (file: string, module: EcopagesJsxMdxPageModule) => EcopagesJsxMdxPageModule;
|
package/src/ecopages-jsx-mdx.js
CHANGED
|
@@ -18,18 +18,6 @@ export const createMdxLoaderPlugin = (options) => createMdxLoaderPluginCore({
|
|
|
18
18
|
loader: 'js',
|
|
19
19
|
projectRoot: options.projectRoot,
|
|
20
20
|
});
|
|
21
|
-
export const registerBunMdxPlugin = async (options) => {
|
|
22
|
-
if (typeof Bun === 'undefined') {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
const plugin = createMdxLoaderPlugin(options);
|
|
26
|
-
Bun.plugin({
|
|
27
|
-
name: plugin.name,
|
|
28
|
-
setup(build) {
|
|
29
|
-
return plugin.setup(build);
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
};
|
|
33
21
|
export const isMdxFile = (filePath, extensions) => {
|
|
34
22
|
return extensions.some((ext) => filePath.endsWith(ext));
|
|
35
23
|
};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { EcoComponent } from '@ecopages/core';
|
|
2
|
-
import type { ProcessedAsset } from '@ecopages/core/services/asset-processing-service';
|
|
3
2
|
export declare const ECOPAGES_JSX_SSR_RENDER_STATE_KEY: unique symbol;
|
|
4
3
|
/**
|
|
5
|
-
* Tracks JSX SSR
|
|
4
|
+
* Tracks JSX SSR HMR-ownership state for one active render flow.
|
|
6
5
|
*
|
|
7
6
|
* @remarks
|
|
8
7
|
* The renderer still mirrors this state into `@ecopages/jsx/server` so nested
|
|
@@ -12,24 +11,19 @@ export declare const ECOPAGES_JSX_SSR_RENDER_STATE_KEY: unique symbol;
|
|
|
12
11
|
* JSX server helpers.
|
|
13
12
|
*/
|
|
14
13
|
export declare class EcopagesJsxRenderSession {
|
|
15
|
-
private readonly dedupeProcessedAssets;
|
|
16
|
-
constructor(dedupeProcessedAssets: (assets: ProcessedAsset[]) => ProcessedAsset[]);
|
|
17
14
|
/**
|
|
18
15
|
* Runs one render inside the active session scope.
|
|
19
16
|
*
|
|
20
17
|
* @remarks
|
|
21
18
|
* When a render is already active, the current session state is reused and
|
|
22
19
|
* mirrored back into the JSX SSR scope so nested `renderToString()` calls see
|
|
23
|
-
* the same
|
|
20
|
+
* the same HMR-ownership set. When no session exists yet, a new state is
|
|
24
21
|
* created and published through both the internal async-local store and the
|
|
25
22
|
* JSX SSR scope bridge. HMR ownership accumulated during the outer scope is
|
|
26
23
|
* published once when that scope completes.
|
|
27
24
|
*/
|
|
28
25
|
withActiveScope<T>(render: () => T | Promise<T>): Promise<T>;
|
|
29
|
-
beginCollectedAssetFrame(): ProcessedAsset[];
|
|
30
|
-
endCollectedAssetFrame(frame: ProcessedAsset[]): ProcessedAsset[];
|
|
31
26
|
mergeHmrOwnership(components: ReadonlyArray<EcoComponent | undefined>): void;
|
|
32
|
-
recordCollectedAssets(collectedAssets: ProcessedAsset[]): ProcessedAsset[];
|
|
33
27
|
/**
|
|
34
28
|
* Resolves the current render-session state from the local async scope first.
|
|
35
29
|
*
|
|
@@ -26,7 +26,7 @@ async function runWithCommittedHmrOwnership(state, render) {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
-
* Tracks JSX SSR
|
|
29
|
+
* Tracks JSX SSR HMR-ownership state for one active render flow.
|
|
30
30
|
*
|
|
31
31
|
* @remarks
|
|
32
32
|
* The renderer still mirrors this state into `@ecopages/jsx/server` so nested
|
|
@@ -36,17 +36,13 @@ async function runWithCommittedHmrOwnership(state, render) {
|
|
|
36
36
|
* JSX server helpers.
|
|
37
37
|
*/
|
|
38
38
|
export class EcopagesJsxRenderSession {
|
|
39
|
-
dedupeProcessedAssets;
|
|
40
|
-
constructor(dedupeProcessedAssets) {
|
|
41
|
-
this.dedupeProcessedAssets = dedupeProcessedAssets;
|
|
42
|
-
}
|
|
43
39
|
/**
|
|
44
40
|
* Runs one render inside the active session scope.
|
|
45
41
|
*
|
|
46
42
|
* @remarks
|
|
47
43
|
* When a render is already active, the current session state is reused and
|
|
48
44
|
* mirrored back into the JSX SSR scope so nested `renderToString()` calls see
|
|
49
|
-
* the same
|
|
45
|
+
* the same HMR-ownership set. When no session exists yet, a new state is
|
|
50
46
|
* created and published through both the internal async-local store and the
|
|
51
47
|
* JSX SSR scope bridge. HMR ownership accumulated during the outer scope is
|
|
52
48
|
* published once when that scope completes.
|
|
@@ -62,36 +58,13 @@ export class EcopagesJsxRenderSession {
|
|
|
62
58
|
return await runWithCommittedHmrOwnership(jsxScopeState, () => renderStateStorage.run(jsxScopeState, () => render()));
|
|
63
59
|
}
|
|
64
60
|
const state = {
|
|
65
|
-
collectedAssetFrames: [],
|
|
66
61
|
pendingHmrFileOwners: new Set(),
|
|
67
62
|
};
|
|
68
63
|
return await runWithCommittedHmrOwnership(state, () => renderStateStorage.run(state, () => withActiveSsrScopeValue(ECOPAGES_JSX_SSR_RENDER_STATE_KEY, state, render)));
|
|
69
64
|
}
|
|
70
|
-
beginCollectedAssetFrame() {
|
|
71
|
-
const state = this.getState();
|
|
72
|
-
const frame = [];
|
|
73
|
-
state.collectedAssetFrames.push(frame);
|
|
74
|
-
return frame;
|
|
75
|
-
}
|
|
76
|
-
endCollectedAssetFrame(frame) {
|
|
77
|
-
const activeFrame = this.getState().collectedAssetFrames.pop();
|
|
78
|
-
if (!activeFrame || activeFrame !== frame) {
|
|
79
|
-
return this.dedupeProcessedAssets(frame);
|
|
80
|
-
}
|
|
81
|
-
return this.dedupeProcessedAssets(activeFrame);
|
|
82
|
-
}
|
|
83
65
|
mergeHmrOwnership(components) {
|
|
84
66
|
mergeEjsxHmrOwnership(ensurePendingHmrFileOwners(this.getState()), components);
|
|
85
67
|
}
|
|
86
|
-
recordCollectedAssets(collectedAssets) {
|
|
87
|
-
const dedupedAssets = this.dedupeProcessedAssets(collectedAssets);
|
|
88
|
-
const state = this.getState();
|
|
89
|
-
const activeFrame = state.collectedAssetFrames[state.collectedAssetFrames.length - 1];
|
|
90
|
-
if (activeFrame) {
|
|
91
|
-
activeFrame.push(...dedupedAssets);
|
|
92
|
-
}
|
|
93
|
-
return dedupedAssets;
|
|
94
|
-
}
|
|
95
68
|
/**
|
|
96
69
|
* Resolves the current render-session state from the local async scope first.
|
|
97
70
|
*
|
|
@@ -34,7 +34,7 @@ export declare class EcopagesJsxRenderer extends IntegrationRenderer<JsxRenderab
|
|
|
34
34
|
private isJsxSerializableForeignChild;
|
|
35
35
|
/**
|
|
36
36
|
* Re-renders queued JSX children inside the owning renderer so nested custom
|
|
37
|
-
* elements and queued foreign subtrees
|
|
37
|
+
* elements and queued foreign subtrees resolve here rather than as opaque markup.
|
|
38
38
|
*/
|
|
39
39
|
private renderQueuedForeignSubtreeChildren;
|
|
40
40
|
protected createForeignChildRuntime(options: {
|
|
@@ -75,25 +75,22 @@ export class EcopagesJsxRenderer extends IntegrationRenderer {
|
|
|
75
75
|
}
|
|
76
76
|
/**
|
|
77
77
|
* Re-renders queued JSX children inside the owning renderer so nested custom
|
|
78
|
-
* elements and queued foreign subtrees
|
|
78
|
+
* elements and queued foreign subtrees resolve here rather than as opaque markup.
|
|
79
79
|
*/
|
|
80
80
|
async renderQueuedForeignSubtreeChildren(children, queuedResolutionsByToken, resolveToken) {
|
|
81
81
|
if (children === undefined) {
|
|
82
82
|
return { assets: [] };
|
|
83
83
|
}
|
|
84
|
-
let assets = [];
|
|
85
84
|
let html;
|
|
86
85
|
if (typeof children === 'string') {
|
|
87
86
|
html = children;
|
|
88
87
|
}
|
|
89
88
|
else {
|
|
90
|
-
|
|
91
|
-
html = renderedChildren.html;
|
|
92
|
-
assets = renderedChildren.assets;
|
|
89
|
+
html = await this.renderJsx(children);
|
|
93
90
|
}
|
|
94
91
|
html = await this.foreignSubtreeExecutionService.resolveQueuedTokens(html, queuedResolutionsByToken, resolveToken);
|
|
95
92
|
return {
|
|
96
|
-
assets,
|
|
93
|
+
assets: [],
|
|
97
94
|
html,
|
|
98
95
|
};
|
|
99
96
|
}
|
|
@@ -124,7 +121,7 @@ export class EcopagesJsxRenderer extends IntegrationRenderer {
|
|
|
124
121
|
runtimeOrigin,
|
|
125
122
|
});
|
|
126
123
|
this.mdxExtensions = jsxConfig?.mdxExtensions ?? ['.mdx'];
|
|
127
|
-
this.renderSession = new EcopagesJsxRenderSession(
|
|
124
|
+
this.renderSession = new EcopagesJsxRenderSession();
|
|
128
125
|
const radiantSsrEnabled = jsxConfig?.radiantSsrEnabled ?? false;
|
|
129
126
|
this.radiantSsrPolicy = jsxConfig?.radiantSsrPolicy ?? new EcopagesJsxRadiantSsrPolicy(radiantSsrEnabled);
|
|
130
127
|
const preferSourceImports = typeof Bun !== 'undefined';
|
|
@@ -209,7 +206,6 @@ export class EcopagesJsxRenderer extends IntegrationRenderer {
|
|
|
209
206
|
return await this.withPreparedRadiantRuntime(async () => {
|
|
210
207
|
await this.ssrScriptPreloader.preloadSsrScripts([input.component]);
|
|
211
208
|
return await this.renderSession.withActiveScope(async () => {
|
|
212
|
-
const assetFrame = this.renderSession.beginCollectedAssetFrame();
|
|
213
209
|
try {
|
|
214
210
|
if (typeof input.component !== 'function') {
|
|
215
211
|
throw new TypeError('JSX renderer expected a callable component.');
|
|
@@ -224,10 +220,10 @@ export class EcopagesJsxRenderer extends IntegrationRenderer {
|
|
|
224
220
|
: input.children,
|
|
225
221
|
};
|
|
226
222
|
const content = await this.withCustomElementRenderHook(() => component(componentProps));
|
|
227
|
-
const
|
|
223
|
+
const html = await this.renderJsx(content);
|
|
228
224
|
const queuedForeignSubtreeResolution = await this.foreignSubtreeExecutionService.resolveQueuedHtml({
|
|
229
225
|
currentIntegrationName: this.name,
|
|
230
|
-
html
|
|
226
|
+
html,
|
|
231
227
|
runtimeContext: this.foreignSubtreeExecutionService.getQueuedRuntimeContext(input, getForeignSubtreeResolutionContextKey(this.name)),
|
|
232
228
|
queueLabel: 'Ecopages JSX',
|
|
233
229
|
getOwningRenderer: (integrationName, rendererCache) => resolveOwningIntegrationRenderer({
|
|
@@ -247,7 +243,6 @@ export class EcopagesJsxRenderer extends IntegrationRenderer {
|
|
|
247
243
|
? await this.processComponentDependencies([input.component])
|
|
248
244
|
: [];
|
|
249
245
|
const assets = this.htmlTransformer.dedupeProcessedAssets([
|
|
250
|
-
...this.renderSession.endCollectedAssetFrame(assetFrame),
|
|
251
246
|
...queuedForeignSubtreeResolution.assets,
|
|
252
247
|
...componentAssets,
|
|
253
248
|
]);
|
|
@@ -261,7 +256,6 @@ export class EcopagesJsxRenderer extends IntegrationRenderer {
|
|
|
261
256
|
});
|
|
262
257
|
}
|
|
263
258
|
catch (error) {
|
|
264
|
-
this.renderSession.endCollectedAssetFrame(assetFrame);
|
|
265
259
|
throw this.createRenderError('Error rendering component', error);
|
|
266
260
|
}
|
|
267
261
|
});
|
|
@@ -293,13 +287,7 @@ export class EcopagesJsxRenderer extends IntegrationRenderer {
|
|
|
293
287
|
});
|
|
294
288
|
}
|
|
295
289
|
async renderJsx(value) {
|
|
296
|
-
|
|
297
|
-
const html = await this.withCustomElementRenderHook(() => renderToString(value));
|
|
298
|
-
const dedupedAssets = this.renderSession.recordCollectedAssets(collectedAssets);
|
|
299
|
-
return {
|
|
300
|
-
assets: dedupedAssets,
|
|
301
|
-
html,
|
|
302
|
-
};
|
|
290
|
+
return await this.withCustomElementRenderHook(() => renderToString(value));
|
|
303
291
|
}
|
|
304
292
|
async withCustomElementRenderHook(render) {
|
|
305
293
|
return await this.radiantSsrPolicy.withRuntime(() => withServerCustomElementRenderHook(this.createIntrinsicCustomElementRenderHook(), render));
|
|
@@ -39,17 +39,14 @@ export declare class EcopagesJsxPlugin extends IntegrationPlugin<JsxRenderable>
|
|
|
39
39
|
*/
|
|
40
40
|
getHmrStrategy(): HmrStrategy | undefined;
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
42
|
+
* Ensures the MDX loader exists, then completes the base integration setup.
|
|
43
|
+
*
|
|
44
|
+
* @remarks
|
|
45
|
+
* Bun registers `integration.plugins` after `setup()` returns. Calling
|
|
46
|
+
* `Bun.plugin` here would install the same MDX loader twice.
|
|
43
47
|
*/
|
|
44
48
|
setup(): Promise<void>;
|
|
45
49
|
private ensureMdxLoaderPlugin;
|
|
46
|
-
/**
|
|
47
|
-
* Registers Bun's MDX loader at runtime setup time.
|
|
48
|
-
*
|
|
49
|
-
* Build-time contribution collection may run where Bun is absent, so
|
|
50
|
-
* this hook stays isolated from manifest preparation.
|
|
51
|
-
*/
|
|
52
|
-
private registerMdxBunPlugin;
|
|
53
50
|
}
|
|
54
51
|
/**
|
|
55
52
|
* Creates the JSX integration plugin with resolved defaults.
|
|
@@ -2,7 +2,7 @@ import { IntegrationPlugin, } from '@ecopages/core/plugins/integration-plugin';
|
|
|
2
2
|
import { AssetFactory } from '@ecopages/core/services/asset-processing-service';
|
|
3
3
|
import { ECOPAGES_JSX_PLUGIN_NAME } from './ecopages-jsx.constants.js';
|
|
4
4
|
import { RADIANT_INSTALL_HYDRATOR_FILEPATH } from './resolve-radiant-install-hydrator.js';
|
|
5
|
-
import { appendMdxExtensions, createMdxLoaderPlugin,
|
|
5
|
+
import { appendMdxExtensions, createMdxLoaderPlugin, resolveMdxCompilerOptions, } from './ecopages-jsx-mdx.js';
|
|
6
6
|
import { EcopagesJsxRenderer } from './ecopages-jsx-renderer.js';
|
|
7
7
|
import { EcopagesJsxHmrStrategy } from './ecopages-jsx-hmr-strategy.js';
|
|
8
8
|
import { EcopagesJsxDevTransformContributor } from './dev-transform/ecopages-jsx-dev-transform-contributor.js';
|
|
@@ -137,13 +137,14 @@ export class EcopagesJsxPlugin extends IntegrationPlugin {
|
|
|
137
137
|
});
|
|
138
138
|
}
|
|
139
139
|
/**
|
|
140
|
-
*
|
|
140
|
+
* Ensures the MDX loader exists, then completes the base integration setup.
|
|
141
|
+
*
|
|
142
|
+
* @remarks
|
|
143
|
+
* Bun registers `integration.plugins` after `setup()` returns. Calling
|
|
144
|
+
* `Bun.plugin` here would install the same MDX loader twice.
|
|
141
145
|
*/
|
|
142
146
|
async setup() {
|
|
143
147
|
this.ensureMdxLoaderPlugin();
|
|
144
|
-
if (typeof Bun !== 'undefined' && this.mdxEnabled && this.mdxCompilerOptions) {
|
|
145
|
-
await this.registerMdxBunPlugin();
|
|
146
|
-
}
|
|
147
148
|
await super.setup();
|
|
148
149
|
}
|
|
149
150
|
ensureMdxLoaderPlugin() {
|
|
@@ -159,25 +160,6 @@ export class EcopagesJsxPlugin extends IntegrationPlugin {
|
|
|
159
160
|
projectRoot: this.appConfig.rootDir,
|
|
160
161
|
});
|
|
161
162
|
}
|
|
162
|
-
/**
|
|
163
|
-
* Registers Bun's MDX loader at runtime setup time.
|
|
164
|
-
*
|
|
165
|
-
* Build-time contribution collection may run where Bun is absent, so
|
|
166
|
-
* this hook stays isolated from manifest preparation.
|
|
167
|
-
*/
|
|
168
|
-
async registerMdxBunPlugin() {
|
|
169
|
-
if (typeof Bun === 'undefined' || !this.mdxCompilerOptions) {
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
if (!this.appConfig) {
|
|
173
|
-
throw new Error('[EcopagesJsxPlugin] Cannot register Bun MDX plugin: appConfig is not set');
|
|
174
|
-
}
|
|
175
|
-
await registerBunMdxPlugin({
|
|
176
|
-
compilerOptions: this.mdxCompilerOptions,
|
|
177
|
-
extensions: this.mdxExtensions,
|
|
178
|
-
projectRoot: this.appConfig.rootDir,
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
163
|
}
|
|
182
164
|
/**
|
|
183
165
|
* Creates the JSX integration plugin with resolved defaults.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { rapidhash } from '@ecopages/core/
|
|
1
|
+
import { rapidhash } from '@ecopages/core/hash';
|
|
2
2
|
import { ECOPAGES_JSX_PLUGIN_NAME } from './ecopages-jsx.constants.js';
|
|
3
3
|
/** Shared grouped-build id prefix for page-owned content scripts. */
|
|
4
4
|
const PAGE_OWNED_CONTENT_SCRIPT_BUNDLE_PREFIX = 'ecopages';
|