@ultimat3/render 22.3.4 → 22.3.5
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 +6 -6
- package/src/module-loader.ts +38 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultimat3/render",
|
|
3
|
-
"version": "22.3.
|
|
3
|
+
"version": "22.3.5",
|
|
4
4
|
"description": "The route primitive and the five render modes: static, isr, ssr, stream, spa.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
"test": "bun test"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@ultimat3/cache": "22.3.
|
|
40
|
-
"@ultimat3/core": "22.3.
|
|
41
|
-
"@ultimat3/http": "22.3.
|
|
42
|
-
"@ultimat3/i18n": "22.3.
|
|
43
|
-
"@ultimat3/seo": "22.3.
|
|
39
|
+
"@ultimat3/cache": "22.3.5",
|
|
40
|
+
"@ultimat3/core": "22.3.5",
|
|
41
|
+
"@ultimat3/http": "22.3.5",
|
|
42
|
+
"@ultimat3/i18n": "22.3.5",
|
|
43
|
+
"@ultimat3/seo": "22.3.5",
|
|
44
44
|
"sass": "1.104.0"
|
|
45
45
|
}
|
|
46
46
|
}
|
package/src/module-loader.ts
CHANGED
|
@@ -79,11 +79,9 @@ export interface Stylesheet {
|
|
|
79
79
|
/** A plain (non-module) stylesheet: the tokens and the reset, which the cascade needs first. */
|
|
80
80
|
readonly global: boolean;
|
|
81
81
|
/**
|
|
82
|
-
* Registered only by an ISLAND build, never by the server's module graph
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* differed between two pods of one image (notificado.co, 22.3.2: one pod's `/styles/<hash>.css`
|
|
86
|
-
* was the other's 404, and each `sw.js` precached a sheet the other did not serve).
|
|
82
|
+
* Registered only by an ISLAND build, never by the server's module graph — what `x build --target
|
|
83
|
+
* docker` records in the island store. Not an ordering key: every sheet is ordered by
|
|
84
|
+
* `stylesheetOrder`, whoever registered it.
|
|
87
85
|
*/
|
|
88
86
|
readonly island: boolean;
|
|
89
87
|
readonly css: string;
|
|
@@ -147,18 +145,25 @@ export function clearStylesheets(): void {
|
|
|
147
145
|
}
|
|
148
146
|
|
|
149
147
|
/**
|
|
150
|
-
* The CSS a document on `surface` must carry
|
|
151
|
-
*
|
|
152
|
-
* browser parses, not just bytes it executes.
|
|
148
|
+
* The CSS a document on `surface` must carry. A `site/` page never receives `app/` CSS — that is
|
|
149
|
+
* axiom 6 applied to bytes the browser parses, not just bytes it executes.
|
|
153
150
|
*
|
|
154
151
|
* `shared/` is carried by both graphs by definition — it is the one directory both surfaces import
|
|
155
152
|
* from, and it is where an app's own global stylesheet lives. Filtering it out (which this did)
|
|
156
153
|
* meant an app could put its tokens in the one place the convention names and have every document
|
|
157
154
|
* silently drop them.
|
|
158
155
|
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
156
|
+
* THE ORDER IS A FUNCTION OF THE SHEETS, NEVER OF THEIR ARRIVAL (22.3.5). A sheet registers in Bun's
|
|
157
|
+
* `onLoad`, which runs as the loader fetches a module's dependencies — in parallel — and an island
|
|
158
|
+
* build's too: the arrival order differed on every boot of one image, and so did the joined bytes
|
|
159
|
+
* and the `/styles/<hash>.css` minted from them (notificado.co, 22.3.2–22.3.4: two pods, two URLs,
|
|
160
|
+
* each the other's 404). `stylesheetOrder` is the whole rule:
|
|
161
|
+
*
|
|
162
|
+
* | key | first | why |
|
|
163
|
+
* |---|---|---|
|
|
164
|
+
* | global | the global layer | the reset styles bare elements at the lowest specificity there is, so a reset after a module rule wins ties it must lose |
|
|
165
|
+
* | owner | a package's sheet, then `shared/`, then the surface's own | library before app: an app's rule wins a tie against the component it restyles |
|
|
166
|
+
* | path | app-root-relative, by code unit | a total order; the same on every machine |
|
|
162
167
|
*/
|
|
163
168
|
export function stylesFor(surface: Surface | null): string {
|
|
164
169
|
const carried = [...stylesheets.values()].filter(
|
|
@@ -166,17 +171,28 @@ export function stylesFor(surface: Surface | null): string {
|
|
|
166
171
|
);
|
|
167
172
|
// `stripCharset` on every sheet, not only the first: a `@charset` or a BOM is legal at byte 0 of
|
|
168
173
|
// a FILE and nowhere else, and this join is what turns seven files into one.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
174
|
+
return carried
|
|
175
|
+
.sort(stylesheetOrder)
|
|
176
|
+
.map((sheet) => stripCharset(sheet.css))
|
|
177
|
+
.join('');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const OWNER_RANK = (sheet: Stylesheet): number =>
|
|
181
|
+
sheet.surface === null ? 0 : sheet.surface === 'shared' ? 1 : 2;
|
|
182
|
+
|
|
183
|
+
/** Relative to the app root, so a container at `/app` and a laptop order one app alike. */
|
|
184
|
+
const orderPath = (sheet: Stylesheet): string => {
|
|
185
|
+
const root = stylesheetRoot ?? process.cwd();
|
|
186
|
+
return sheet.file.startsWith(`${root}/`) ? sheet.file.slice(root.length + 1) : sheet.file;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/** See `stylesFor`: global layer, then owner, then path. Exported for the tests that pin it. */
|
|
190
|
+
export function stylesheetOrder(a: Stylesheet, b: Stylesheet): number {
|
|
191
|
+
if (a.global !== b.global) return a.global ? -1 : 1;
|
|
192
|
+
const owner = OWNER_RANK(a) - OWNER_RANK(b);
|
|
193
|
+
if (owner !== 0) return owner;
|
|
194
|
+
const [x, y] = [orderPath(a), orderPath(b)];
|
|
195
|
+
return x < y ? -1 : x > y ? 1 : 0;
|
|
180
196
|
}
|
|
181
197
|
|
|
182
198
|
/**
|