@bleedingdev/modern-js-app-tools 3.2.0-ultramodern.65 → 3.2.0-ultramodern.66

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.
@@ -121,6 +121,45 @@ function createRequestHandlerOptions({ route, htmlTemplate, routeManifest, loada
121
121
  }
122
122
  };
123
123
  }
124
+ function collectRouteCssAssets(route, routeManifest) {
125
+ const routeAssets = routeManifest?.routeAssets || {};
126
+ const candidateKeys = [
127
+ route.entryName,
128
+ `async-${route.entryName}`
129
+ ].filter(Boolean);
130
+ const assets = new Set();
131
+ for (const key of candidateKeys){
132
+ const routeAsset = routeAssets[key];
133
+ const cssAssets = [
134
+ ...Array.isArray(routeAsset?.referenceCssAssets) ? routeAsset.referenceCssAssets : [],
135
+ ...Array.isArray(routeAsset?.assets) ? routeAsset.assets : []
136
+ ];
137
+ for (const asset of cssAssets)if ('string' == typeof asset && asset.endsWith('.css')) assets.add(asset);
138
+ }
139
+ return [
140
+ ...assets
141
+ ];
142
+ }
143
+ function escapeAttribute(value) {
144
+ return String(value).replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
145
+ }
146
+ async function withRouteCssLinks(response, route, routeManifest, request) {
147
+ const contentType = response.headers.get('content-type') || '';
148
+ if (!contentType.includes('text/html')) return response;
149
+ const cssAssets = collectRouteCssAssets(route, routeManifest);
150
+ if (0 === cssAssets.length) return response;
151
+ const html = await response.text();
152
+ const links = cssAssets.filter((asset)=>!html.includes(asset)).map((asset)=>{
153
+ const href = new URL(asset, request.url).toString();
154
+ return `<link rel="stylesheet" href="${escapeAttribute(href)}">`;
155
+ });
156
+ if (0 === links.length || !html.includes('</head>')) return new Response(html, response);
157
+ return new Response(html.replace('</head>', `${links.join('')}</head>`), {
158
+ headers: response.headers,
159
+ status: response.status,
160
+ statusText: response.statusText
161
+ });
162
+ }
124
163
  async function getRequestHandlerOptions(route, request, env) {
125
164
  const [htmlTemplate, routeManifest, loadableStats] = await Promise.all([
126
165
  readAssetText(route.entryPath, request, env),
@@ -180,7 +219,7 @@ async function dispatchRouteWorker(route, request, env, ctx) {
180
219
  const requestHandler = await getRequestHandler(workerModule);
181
220
  if ('function' == typeof requestHandler) {
182
221
  const requestHandlerOptions = await getRequestHandlerOptions(route, request, env);
183
- return requestHandler(request, requestHandlerOptions);
222
+ return withRouteCssLinks(await requestHandler(request, requestHandlerOptions), route, requestHandlerOptions.resource.routeManifest, request);
184
223
  }
185
224
  return new Response(`Worker bundle has no fetch or requestHandler export: ${workerPath}`, {
186
225
  status: 500,
@@ -121,6 +121,45 @@ function createRequestHandlerOptions({ route, htmlTemplate, routeManifest, loada
121
121
  }
122
122
  };
123
123
  }
124
+ function collectRouteCssAssets(route, routeManifest) {
125
+ const routeAssets = routeManifest?.routeAssets || {};
126
+ const candidateKeys = [
127
+ route.entryName,
128
+ `async-${route.entryName}`
129
+ ].filter(Boolean);
130
+ const assets = new Set();
131
+ for (const key of candidateKeys){
132
+ const routeAsset = routeAssets[key];
133
+ const cssAssets = [
134
+ ...Array.isArray(routeAsset?.referenceCssAssets) ? routeAsset.referenceCssAssets : [],
135
+ ...Array.isArray(routeAsset?.assets) ? routeAsset.assets : []
136
+ ];
137
+ for (const asset of cssAssets)if ('string' == typeof asset && asset.endsWith('.css')) assets.add(asset);
138
+ }
139
+ return [
140
+ ...assets
141
+ ];
142
+ }
143
+ function escapeAttribute(value) {
144
+ return String(value).replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
145
+ }
146
+ async function withRouteCssLinks(response, route, routeManifest, request) {
147
+ const contentType = response.headers.get('content-type') || '';
148
+ if (!contentType.includes('text/html')) return response;
149
+ const cssAssets = collectRouteCssAssets(route, routeManifest);
150
+ if (0 === cssAssets.length) return response;
151
+ const html = await response.text();
152
+ const links = cssAssets.filter((asset)=>!html.includes(asset)).map((asset)=>{
153
+ const href = new URL(asset, request.url).toString();
154
+ return `<link rel="stylesheet" href="${escapeAttribute(href)}">`;
155
+ });
156
+ if (0 === links.length || !html.includes('</head>')) return new Response(html, response);
157
+ return new Response(html.replace('</head>', `${links.join('')}</head>`), {
158
+ headers: response.headers,
159
+ status: response.status,
160
+ statusText: response.statusText
161
+ });
162
+ }
124
163
  async function getRequestHandlerOptions(route, request, env) {
125
164
  const [htmlTemplate, routeManifest, loadableStats] = await Promise.all([
126
165
  readAssetText(route.entryPath, request, env),
@@ -180,7 +219,7 @@ async function dispatchRouteWorker(route, request, env, ctx) {
180
219
  const requestHandler = await getRequestHandler(workerModule);
181
220
  if ('function' == typeof requestHandler) {
182
221
  const requestHandlerOptions = await getRequestHandlerOptions(route, request, env);
183
- return requestHandler(request, requestHandlerOptions);
222
+ return withRouteCssLinks(await requestHandler(request, requestHandlerOptions), route, requestHandlerOptions.resource.routeManifest, request);
184
223
  }
185
224
  return new Response(`Worker bundle has no fetch or requestHandler export: ${workerPath}`, {
186
225
  status: 500,
@@ -121,6 +121,45 @@ function createRequestHandlerOptions({ route, htmlTemplate, routeManifest, loada
121
121
  }
122
122
  };
123
123
  }
124
+ function collectRouteCssAssets(route, routeManifest) {
125
+ const routeAssets = routeManifest?.routeAssets || {};
126
+ const candidateKeys = [
127
+ route.entryName,
128
+ `async-${route.entryName}`
129
+ ].filter(Boolean);
130
+ const assets = new Set();
131
+ for (const key of candidateKeys){
132
+ const routeAsset = routeAssets[key];
133
+ const cssAssets = [
134
+ ...Array.isArray(routeAsset?.referenceCssAssets) ? routeAsset.referenceCssAssets : [],
135
+ ...Array.isArray(routeAsset?.assets) ? routeAsset.assets : []
136
+ ];
137
+ for (const asset of cssAssets)if ('string' == typeof asset && asset.endsWith('.css')) assets.add(asset);
138
+ }
139
+ return [
140
+ ...assets
141
+ ];
142
+ }
143
+ function escapeAttribute(value) {
144
+ return String(value).replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
145
+ }
146
+ async function withRouteCssLinks(response, route, routeManifest, request) {
147
+ const contentType = response.headers.get('content-type') || '';
148
+ if (!contentType.includes('text/html')) return response;
149
+ const cssAssets = collectRouteCssAssets(route, routeManifest);
150
+ if (0 === cssAssets.length) return response;
151
+ const html = await response.text();
152
+ const links = cssAssets.filter((asset)=>!html.includes(asset)).map((asset)=>{
153
+ const href = new URL(asset, request.url).toString();
154
+ return `<link rel="stylesheet" href="${escapeAttribute(href)}">`;
155
+ });
156
+ if (0 === links.length || !html.includes('</head>')) return new Response(html, response);
157
+ return new Response(html.replace('</head>', `${links.join('')}</head>`), {
158
+ headers: response.headers,
159
+ status: response.status,
160
+ statusText: response.statusText
161
+ });
162
+ }
124
163
  async function getRequestHandlerOptions(route, request, env) {
125
164
  const [htmlTemplate, routeManifest, loadableStats] = await Promise.all([
126
165
  readAssetText(route.entryPath, request, env),
@@ -180,7 +219,7 @@ async function dispatchRouteWorker(route, request, env, ctx) {
180
219
  const requestHandler = await getRequestHandler(workerModule);
181
220
  if ('function' == typeof requestHandler) {
182
221
  const requestHandlerOptions = await getRequestHandlerOptions(route, request, env);
183
- return requestHandler(request, requestHandlerOptions);
222
+ return withRouteCssLinks(await requestHandler(request, requestHandlerOptions), route, requestHandlerOptions.resource.routeManifest, request);
184
223
  }
185
224
  return new Response(`Worker bundle has no fetch or requestHandler export: ${workerPath}`, {
186
225
  status: 500,
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "modern",
18
18
  "modern.js"
19
19
  ],
20
- "version": "3.2.0-ultramodern.65",
20
+ "version": "3.2.0-ultramodern.66",
21
21
  "types": "./dist/types/index.d.ts",
22
22
  "main": "./dist/cjs/index.js",
23
23
  "exports": {
@@ -99,16 +99,16 @@
99
99
  "ndepe": "^0.1.13",
100
100
  "pkg-types": "^2.3.1",
101
101
  "std-env": "4.1.0",
102
- "@modern-js/builder": "npm:@bleedingdev/modern-js-builder@3.2.0-ultramodern.65",
103
- "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.2.0-ultramodern.65",
104
- "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.2.0-ultramodern.65",
105
- "@modern-js/server": "npm:@bleedingdev/modern-js-server@3.2.0-ultramodern.65",
106
- "@modern-js/plugin-data-loader": "npm:@bleedingdev/modern-js-plugin-data-loader@3.2.0-ultramodern.65",
107
- "@modern-js/prod-server": "npm:@bleedingdev/modern-js-prod-server@3.2.0-ultramodern.65",
108
- "@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.2.0-ultramodern.65",
109
- "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.2.0-ultramodern.65",
110
- "@modern-js/server-utils": "npm:@bleedingdev/modern-js-server-utils@3.2.0-ultramodern.65",
111
- "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.2.0-ultramodern.65"
102
+ "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.2.0-ultramodern.66",
103
+ "@modern-js/builder": "npm:@bleedingdev/modern-js-builder@3.2.0-ultramodern.66",
104
+ "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.2.0-ultramodern.66",
105
+ "@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.2.0-ultramodern.66",
106
+ "@modern-js/plugin-data-loader": "npm:@bleedingdev/modern-js-plugin-data-loader@3.2.0-ultramodern.66",
107
+ "@modern-js/server": "npm:@bleedingdev/modern-js-server@3.2.0-ultramodern.66",
108
+ "@modern-js/server-utils": "npm:@bleedingdev/modern-js-server-utils@3.2.0-ultramodern.66",
109
+ "@modern-js/prod-server": "npm:@bleedingdev/modern-js-prod-server@3.2.0-ultramodern.66",
110
+ "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.2.0-ultramodern.66",
111
+ "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.2.0-ultramodern.66"
112
112
  },
113
113
  "devDependencies": {
114
114
  "@rslib/core": "0.21.5",