Skip to content

Latest commit

 

History

138 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CSS Import tests

@import in used as a signal by build tools to bundle CSS.
It is however important in my opinion that this is done in ways that match native browser behavior.

Without this parallel users of such tools become dependent on the tool itself, and the tool becomes a barrier to entry for new users.

When implementations differ between browsers and tools there is an increased chance that implementations will differ between multiple tools as well. This also blurs the line between feature and bug.

These tests are intended to surface such differences.

Currently this checks :

  • chrome
  • firefox
  • esbuild
  • lightningcss (abbr. ⚡️)
  • @csstools/postcss-bundler (abbr. p-bundler)
  • postcss-import (abbr. p-import)

bun was previously tracked here but was removed after it was rewritten in rust with an LLM

Configs

esbuild

No config needed to make it compliant.

const esBundle = await esbuild.build({
	entryPoints: ['style.css'],
	bundle: true,
	logLevel: 'silent',
	write: false,
	external: ['*.png'] /* for sub-resource tests */,
})

lightningcss

Some config is needed to make it run without fatal errors and make it more compliant.

let { code } = lightningcss({
	filename: 'style.css',
	errorRecovery: true, /* The CSS language is intended to be forgiving */
	resolver: { /* Adding this significantly slows down lightningcss */
		read(filePath) {
			return fsSync.readFileSync(filePath, 'utf8');
		},
		resolve(specifier, from) {
			if (/^https?:/.test(specifier)) {
				return { external: specifier }; /* imports with a full url must not be dropped from bundles */
			}
			return path.resolve(path.dirname(from), specifier);
		}
	}
});

@csstools/postcss-bundler

No config needed to make it compliant.

postcssBundler()

postcss-import

Some config is needed to make it more compliant.

postcssImport({
	skipDuplicates: false /* skipping duplicates is not how CSS works */,
})

How to run

Full test suite

  • npm ci
  • npm run install:with-firefox
  • npm run test

Individual test

  • npm ci
  • npm run serve <name of a test>

Sub string matches are fine,
npm run serve at-layer will serve the first test that contains at-layer.

Current state

Test chrome firefox webkit esbuild ⚡️ p-bundler p-import
001-core-features/001/absolute-url
001-core-features/001/default
001-core-features/001/foldername-that-is-a-domain
001-core-features/001/relative-url
001-core-features/at-charset/001
001-core-features/at-charset/002
001-core-features/at-keyframes/001
001-core-features/before-other-styles/001
001-core-features/before-other-styles/002
001-core-features/byte-order-mark/001
001-core-features/byte-order-mark/002
001-core-features/byte-order-mark/003
001-core-features/case-sensitivity/001
001-core-features/case-sensitivity/002
001-core-features/case-sensitivity/003
001-core-features/cycles/001
001-core-features/cycles/002
001-core-features/cycles/003
001-core-features/cycles/004
001-core-features/cycles/005
001-core-features/cycles/006
001-core-features/duplicates/001
001-core-features/duplicates/002
001-core-features/empty/001
001-core-features/escape-sequences/001
001-core-features/escape-sequences/002
001-core-features/escape-sequences/003
001-core-features/escape-sequences/004
001-core-features/escape-sequences/005
001-core-features/forwards-compat/001
001-core-features/forwards-compat/002
001-core-features/forwards-compat/003
001-core-features/forwards-compat/004
001-core-features/forwards-compat/005
001-core-features/forwards-compat/006
001-core-features/forwards-compat/007
001-core-features/forwards-compat/008
001-core-features/input-preprocessing/001
001-core-features/input-preprocessing/002
001-core-features/mixed-importables/001
001-core-features/namespace/001
001-core-features/namespace/002
001-core-features/relative-paths/001
001-core-features/relative-paths/002
001-core-features/subresource/001
001-core-features/subresource/002
001-core-features/subresource/003
001-core-features/subresource/004
001-core-features/subresource/005
001-core-features/subresource/006
001-core-features/subresource/007
001-core-features/subresource/008
001-core-features/subresource/009
001-core-features/subresource/010
001-core-features/subresource/011
001-core-features/url-format/001/absolute-url
001-core-features/url-format/001/default
001-core-features/url-format/001/relative-url
001-core-features/url-format/002/absolute-url
001-core-features/url-format/002/default
001-core-features/url-format/002/relative-url
001-core-features/url-fragments/001
001-core-features/url-fragments/002
001-core-features/url-fragments/003
001-core-features/url-fragments/004
001-core-features/url-fragments/005
001-core-features/url-fragments/006
002-sub-features/001-data-urls/001
002-sub-features/001-data-urls/002
002-sub-features/001-data-urls/003
002-sub-features/001-data-urls/004
002-sub-features/001-data-urls/005
002-sub-features/001-data-urls/006
002-sub-features/002-at-media/001/absolute-url
002-sub-features/002-at-media/001/default
002-sub-features/002-at-media/002
002-sub-features/002-at-media/003
002-sub-features/002-at-media/004
002-sub-features/002-at-media/005
002-sub-features/002-at-media/006
002-sub-features/002-at-media/007
002-sub-features/002-at-media/008
002-sub-features/002-at-media/009
002-sub-features/002-at-media/010
002-sub-features/002-at-media/011
002-sub-features/002-at-media/012
002-sub-features/002-at-media/013
002-sub-features/002-at-media/014
002-sub-features/002-at-media/015
002-sub-features/002-at-media/016
002-sub-features/002-at-media/017
002-sub-features/002-at-media/018
002-sub-features/002-at-media/at-keyframes/001
002-sub-features/002-at-media/cycles/001
002-sub-features/003-at-layer/001
002-sub-features/003-at-layer/002
002-sub-features/003-at-layer/003
002-sub-features/003-at-layer/004
002-sub-features/003-at-layer/005
002-sub-features/003-at-layer/006
002-sub-features/003-at-layer/007
002-sub-features/003-at-layer/008
002-sub-features/003-at-layer/009
002-sub-features/003-at-layer/010
002-sub-features/003-at-layer/011
002-sub-features/003-at-layer/012
002-sub-features/003-at-layer/013
002-sub-features/003-at-layer/014
002-sub-features/003-at-layer/015
002-sub-features/003-at-layer/016
002-sub-features/003-at-layer/017
002-sub-features/003-at-layer/018
002-sub-features/003-at-layer/019
002-sub-features/003-at-layer/020
002-sub-features/003-at-layer/at-keyframes/001
002-sub-features/003-at-layer/at-keyframes/002
002-sub-features/003-at-layer/case-sensitivity/001
002-sub-features/003-at-layer/case-sensitivity/002
002-sub-features/003-at-layer/case-sensitivity/003
002-sub-features/003-at-layer/cycles/001
002-sub-features/003-at-layer/mixed-importables/001
002-sub-features/003-at-layer/url-fragments/001
002-sub-features/004-at-supports/001
002-sub-features/004-at-supports/002
002-sub-features/004-at-supports/003
002-sub-features/004-at-supports/004
002-sub-features/004-at-supports/005
002-sub-features/004-at-supports/006
002-sub-features/004-at-supports/007
002-sub-features/004-at-supports/008
002-sub-features/004-at-supports/009
002-sub-features/004-at-supports/010
002-sub-features/004-at-supports/011
002-sub-features/004-at-supports/012
002-sub-features/004-at-supports/case-sensitivity/001
002-sub-features/005-at-scope/001
002-sub-features/005-at-scope/002
002-sub-features/005-at-scope/003
002-sub-features/005-at-scope/004
002-sub-features/005-at-scope/005
002-sub-features/005-at-scope/006
002-sub-features/005-at-scope/007
002-sub-features/005-at-scope/008
002-sub-features/005-at-scope/009
002-sub-features/005-at-scope/010
002-sub-features/005-at-scope/011
002-sub-features/005-at-scope/012
002-sub-features/005-at-scope/case-sensitivity/001
002-sub-features/005-at-scope/scoping/001
002-sub-features/005-at-scope/scoping/002
002-sub-features/005-at-scope/scoping/003
003-should-fail/001-core-features/before-other-styles/001
003-should-fail/001-core-features/before-other-styles/002
003-should-fail/001-core-features/case-sensitivity/001
004-unimplementable/001-namespace/001
004-unimplementable/002-url-queries/001
004-unimplementable/004-subresource/001
004-unimplementable/004-subresource/002
005-implementation-specific/leading-slash-is-import-root/001
005-implementation-specific/leading-slash-is-import-root/002
999-irrelevant/url-format/001/absolute-url
999-irrelevant/url-format/001/default
999-irrelevant/url-format/001/relative-url
999-irrelevant/url-fragments/001
Total 134 / 151 130 / 151 135 / 151 118 / 151 94 / 151 150 / 151 112 / 151

Contributing

Any test contributions are welcome!

You can open an issue and describe the case you want to test, or you can open a PR with a new test.

I don't care about technical purity, formatting, duplicates, ...
Anything that increases test coverage is very much appreciated.

About

Tests for at-import in CSS

Resources

Stars

19 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages