Use accumulated sort order when order production CSS (#5549)
* Use accumulated sort order when order production CSS * Adding a changeset * Fix lockfile issue
This commit is contained in:
parent
1cfbd5923f
commit
795f00f73c
15 changed files with 180 additions and 2 deletions
5
.changeset/good-terms-walk.md
Normal file
5
.changeset/good-terms-walk.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Use accumulated sort order when order production CSS
|
|
@ -7,13 +7,16 @@ export function* walkParentInfos(
|
||||||
id: string,
|
id: string,
|
||||||
ctx: { getModuleInfo: GetModuleInfo },
|
ctx: { getModuleInfo: GetModuleInfo },
|
||||||
depth = 0,
|
depth = 0,
|
||||||
|
order = 0,
|
||||||
seen = new Set<string>(),
|
seen = new Set<string>(),
|
||||||
childId = ''
|
childId = ''
|
||||||
): Generator<[ModuleInfo, number, number], void, unknown> {
|
): Generator<[ModuleInfo, number, number], void, unknown> {
|
||||||
seen.add(id);
|
seen.add(id);
|
||||||
const info = ctx.getModuleInfo(id);
|
const info = ctx.getModuleInfo(id);
|
||||||
if (info) {
|
if (info) {
|
||||||
let order = childId ? info.importedIds.indexOf(childId) : 0;
|
if(childId) {
|
||||||
|
order += info.importedIds.indexOf(childId)
|
||||||
|
}
|
||||||
yield [info, depth, order];
|
yield [info, depth, order];
|
||||||
}
|
}
|
||||||
const importers = (info?.importers || []).concat(info?.dynamicImporters || []);
|
const importers = (info?.importers || []).concat(info?.dynamicImporters || []);
|
||||||
|
@ -21,7 +24,7 @@ export function* walkParentInfos(
|
||||||
if (seen.has(imp)) {
|
if (seen.has(imp)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
yield* walkParentInfos(imp, ctx, ++depth, seen, id);
|
yield* walkParentInfos(imp, ctx, ++depth, order, seen, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
63
packages/astro/test/css-order-layout.test.js
Normal file
63
packages/astro/test/css-order-layout.test.js
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
import { expect } from 'chai';
|
||||||
|
import * as cheerio from 'cheerio';
|
||||||
|
import { loadFixture } from './test-utils.js';
|
||||||
|
|
||||||
|
describe('CSS ordering - import order with layouts', () => {
|
||||||
|
/** @type {import('./test-utils').Fixture} */
|
||||||
|
let fixture;
|
||||||
|
before(async () => {
|
||||||
|
fixture = await loadFixture({
|
||||||
|
root: './fixtures/css-order-layout/',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} html
|
||||||
|
* @returns {string[]}
|
||||||
|
*/
|
||||||
|
function getLinks(html) {
|
||||||
|
let $ = cheerio.load(html);
|
||||||
|
let out = [];
|
||||||
|
$('link[rel=stylesheet]').each((i, el) => {
|
||||||
|
out.push($(el).attr('href'));
|
||||||
|
});
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} href
|
||||||
|
* @returns {Promise<{ href: string; css: string; }>}
|
||||||
|
*/
|
||||||
|
async function getLinkContent(href) {
|
||||||
|
const css = await fixture.readFile(href);
|
||||||
|
return { href, css };
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Production', () => {
|
||||||
|
before(async () => {
|
||||||
|
await fixture.build();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Page level CSS is defined lower in the page', async () => {
|
||||||
|
let html = await fixture.readFile('/index.html');
|
||||||
|
|
||||||
|
|
||||||
|
const content = await Promise.all(getLinks(html).map((href) => getLinkContent(href)));
|
||||||
|
|
||||||
|
let specialButtonCSS = -1;
|
||||||
|
let globalCSS = -1;
|
||||||
|
for(let i = 0; i < content.length; i++) {
|
||||||
|
if(content[i].css.indexOf('.SpecialButton') !== -1) {
|
||||||
|
specialButtonCSS = i;
|
||||||
|
} else if(content[i].css.indexOf('green') !== -1) {
|
||||||
|
globalCSS = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(globalCSS).to.equal(0, 'global css sorted on top')
|
||||||
|
expect(specialButtonCSS).to.equal(1, 'component level css sorted last');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
3
packages/astro/test/fixtures/css-order-layout/astro.config.mjs
vendored
Normal file
3
packages/astro/test/fixtures/css-order-layout/astro.config.mjs
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import { defineConfig } from "astro/config";
|
||||||
|
|
||||||
|
export default defineConfig({});
|
6
packages/astro/test/fixtures/css-order-layout/package.json
vendored
Normal file
6
packages/astro/test/fixtures/css-order-layout/package.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "@test/css-order-layout",
|
||||||
|
"dependencies": {
|
||||||
|
"astro": "workspace:*"
|
||||||
|
}
|
||||||
|
}
|
17
packages/astro/test/fixtures/css-order-layout/src/components/BlueButton.astro
vendored
Normal file
17
packages/astro/test/fixtures/css-order-layout/src/components/BlueButton.astro
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
import Button from "./Button.astro";
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
- Improve keyboard navigation / focus handling ref: https://w3c.github.io/aria-practices/examples/disclosure/disclosure-navigation.html
|
||||||
|
*/
|
||||||
|
---
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.SpecialButton {
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div>This button should be blue</div>
|
||||||
|
<Button class="SpecialButton" />
|
8
packages/astro/test/fixtures/css-order-layout/src/components/Button.astro
vendored
Normal file
8
packages/astro/test/fixtures/css-order-layout/src/components/Button.astro
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
type Props = {
|
||||||
|
class?: string;
|
||||||
|
};
|
||||||
|
const { class: className } = Astro.props as Props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<button class:list={["btn", className]} type="button"> button</button>
|
5
packages/astro/test/fixtures/css-order-layout/src/components/MainHead.astro
vendored
Normal file
5
packages/astro/test/fixtures/css-order-layout/src/components/MainHead.astro
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
import "../styles/global.css";
|
||||||
|
---
|
||||||
|
|
||||||
|
<meta charset="UTF-8" />
|
14
packages/astro/test/fixtures/css-order-layout/src/layouts/Main.astro
vendored
Normal file
14
packages/astro/test/fixtures/css-order-layout/src/layouts/Main.astro
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
import MainHead from "../components/MainHead.astro";
|
||||||
|
import BlueButton from "../components/BlueButton.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<MainHead />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<BlueButton />
|
||||||
|
<slot />
|
||||||
|
</body>
|
||||||
|
</html>
|
14
packages/astro/test/fixtures/css-order-layout/src/layouts/Second.astro
vendored
Normal file
14
packages/astro/test/fixtures/css-order-layout/src/layouts/Second.astro
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
import MainHead from "../components/MainHead.astro";
|
||||||
|
import BlueButton from "../components/BlueButton.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<MainHead />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<BlueButton />
|
||||||
|
<slot />
|
||||||
|
</body>
|
||||||
|
</html>
|
9
packages/astro/test/fixtures/css-order-layout/src/pages/admin.astro
vendored
Normal file
9
packages/astro/test/fixtures/css-order-layout/src/pages/admin.astro
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
import MainHead from "../components/MainHead.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<MainHead />
|
||||||
|
</head>
|
||||||
|
</html>
|
11
packages/astro/test/fixtures/css-order-layout/src/pages/beta.astro
vendored
Normal file
11
packages/astro/test/fixtures/css-order-layout/src/pages/beta.astro
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
import SecondLayout from "../layouts/Second.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<SecondLayout>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Subpage (<a href='/'>Home</a>)
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</SecondLayout>
|
11
packages/astro/test/fixtures/css-order-layout/src/pages/index.astro
vendored
Normal file
11
packages/astro/test/fixtures/css-order-layout/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
import MainLayout from "../layouts/Main.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<MainLayout>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Home (<a href='/beta'>Subpage</a>)
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</MainLayout>
|
3
packages/astro/test/fixtures/css-order-layout/src/styles/global.css
vendored
Normal file
3
packages/astro/test/fixtures/css-order-layout/src/styles/global.css
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.btn {
|
||||||
|
color: green;
|
||||||
|
}
|
|
@ -1670,6 +1670,12 @@ importers:
|
||||||
dependencies:
|
dependencies:
|
||||||
astro: link:../../..
|
astro: link:../../..
|
||||||
|
|
||||||
|
packages/astro/test/fixtures/css-order-layout:
|
||||||
|
specifiers:
|
||||||
|
astro: workspace:*
|
||||||
|
dependencies:
|
||||||
|
astro: link:../../..
|
||||||
|
|
||||||
packages/astro/test/fixtures/custom-404:
|
packages/astro/test/fixtures/custom-404:
|
||||||
specifiers:
|
specifiers:
|
||||||
astro: workspace:*
|
astro: workspace:*
|
||||||
|
|
Loading…
Reference in a new issue