Lightning CSS is over 100x faster than comparable JavaScript-based tools. It can minify over 2.7 million lines of code per second on a single thread.
-
Lightning CSS is written in Rust, a native systems programming language. It was built with performance in mind from the start, designed to make efficient use of memory, and limit AST passes.
+
+ Lightning CSS is over 100x faster than comparable JavaScript-based
+ tools.
+ It can minify over 2.7 million lines of code per second on a single
+ thread.
+
+
+ Lightning CSS is written in Rust, a native systems programming
+ language. It was built with performance in mind from the start,
+ designed to make efficient use of memory, and limit AST passes.
+
- Time to minify Bootstrap 4 (~10,000 lines). See the readme for more benchmarks.
+
+ Time to minify Bootstrap 4 (~10,000 lines). See the
+ readme
+ for more benchmarks.
+
Live in the future
-
Lightning CSS lets you use modern CSS features and future syntax today. Features such as CSS nesting, custom media queries, high gamut color spaces, logical properties, and new selector features are automatically converted to more compatible syntax based on your browser targets.
-
Lightning CSS also automatically adds vendor prefixes for your browser targets, so you can keep your source code clean and repetition free.
+
+ Lightning CSS lets you use modern CSS features and future
+ syntax today.
+ Features such as CSS nesting, custom media queries, high gamut
+ color spaces, logical properties, and new selector features are
+ automatically converted to more compatible syntax based on your
+ browser targets.
+
+
+ Lightning CSS also automatically adds vendor prefixes for your
+ browser targets, so you can keep your source code clean and
+ repetition free.
+
- Output size after minifying Bootstrap 4 (~10,000 lines). See the readme for more benchmarks.
+
+ Output size after minifying Bootstrap 4 (~10,000 lines). See the
+ readme
+ for more benchmarks.
+
CSS modules
-
Lightning CSS supports CSS modules, which locally scope classes, ids, @keyframes, CSS variables, and more. This ensures that there are no unintended name clashes between different CSS files.
-
Lightning CSS generates a mapping of the original names to scoped names, which can be used from your JavaScript. This also enables unused classes and variables to be tree-shaken.
+
+ Lightning CSS supports CSS modules, which locally scope classes,
+ ids, @keyframes, CSS variables, and more.
+ This ensures that there are no unintended name clashes between
+ different CSS files.
+
+
+ Lightning CSS generates a mapping of the original names to scoped
+ names, which can be used from your JavaScript. This also enables
+ unused classes and variables to be tree-shaken.
+
Lightning CSS is written in Rust, using the cssparser and selectors crates created by Mozilla and used by Firefox. These provide a solid CSS-parsing foundation on top of which Lightning CSS implements support for all specific CSS rules and properties.
-
Lightning CSS fully parses every CSS rule, property, and value just as a browser would. This reduces duplicate work for transformers, leading to improved performance and minification.
+
+ Lightning CSS is written in Rust, using the
+ cssparser
+ and
+ selectors
+ crates created by Mozilla and used by Firefox.
+ These provide a solid CSS-parsing foundation on top of which
+ Lightning CSS implements support for all specific CSS rules and
+ properties.
+
+
+ Lightning CSS fully parses every CSS rule, property, and value just
+ as a browser would. This reduces duplicate work for transformers,
+ leading to improved performance and minification.
+
@media (width < 500px) {
.modules {
- grid-template-areas: "main" "input" "output" "json";
+ grid-template-areas: 'main' 'input' 'output' 'json';
}
.modules .compartment {
diff --git a/website/minification.html b/website/minification.html
index c9b51522..538a8f85 100644
--- a/website/minification.html
+++ b/website/minification.html
@@ -1 +1,4 @@
-
+
diff --git a/website/pages/bundling.md b/website/pages/bundling.md
index 07e74e06..368e04c8 100644
--- a/website/pages/bundling.md
+++ b/website/pages/bundling.md
@@ -11,11 +11,11 @@ Lightning CSS supports bundling dependencies referenced by CSS `@import` rules i
This API requires filesystem access, so it does not accept `code` directly via the API. Instead, the `filename` option is used to read the entry file directly.
```js
-import { bundle } from 'lightningcss';
+import {bundle} from 'lightningcss';
-let { code, map } = bundle({
+let {code, map} = bundle({
filename: 'style.css',
- minify: true
+ minify: true,
});
```
@@ -43,34 +43,46 @@ The `@import` rule can be conditional by appending a media query or `supports()`
```css
/* a.css */
-@import "b.css" print;
-@import "c.css" supports(display: grid);
+@import 'b.css' print;
+@import 'c.css' supports(display: grid);
-.a { color: red }
+.a {
+ color: red;
+}
```
```css
/* b.css */
-.b { color: green }
+.b {
+ color: green;
+}
```
```css
/* c.css */
-.c { display: grid }
+.c {
+ display: grid;
+}
```
compiles to:
```css
@media print {
- .b { color: green }
+ .b {
+ color: green;
+ }
}
@supports (display: grid) {
- .c { display: grid }
+ .c {
+ display: grid;
+ }
}
-.a { color: red }
+.a {
+ color: red;
+}
```
@@ -88,33 +100,45 @@ Imported CSS rules can also be placed into a CSS cascade layer, allowing you to
```css
/* a.css */
-@import "b.css" layer(foo);
-.a { color: red }
+@import 'b.css' layer(foo);
+.a {
+ color: red;
+}
```
```css
/* b.css */
-@import "c.css" layer(bar);
-.b { color: green }
+@import 'c.css' layer(bar);
+.b {
+ color: green;
+}
```
```css
/* c.css */
-.c { color: green }
+.c {
+ color: green;
+}
```
compiles to:
```css
@layer foo.bar {
- .c { color: green }
+ .c {
+ color: green;
+ }
}
@layer foo {
- .b { color: green }
+ .b {
+ color: green;
+ }
}
-.a { color: red }
+.a {
+ color: red;
+}
```
@@ -132,25 +156,31 @@ When `@import` rules are processed in browsers, if the same file appears more th
```css
/* index.css */
-@import "a.css";
-@import "b.css";
-@import "a.css";
+@import 'a.css';
+@import 'b.css';
+@import 'a.css';
```
```css
/* a.css */
-body { background: green }
+body {
+ background: green;
+}
```
```css
/* b.css */
-body { background: red }
+body {
+ background: red;
+}
```
compiles to:
```css
-body { background: green }
+body {
+ background: green;
+}
```
## Custom resolvers
@@ -158,9 +188,9 @@ body { background: green }
The `bundleAsync` API is an asynchronous version of `bundle`, which also accepts a custom `resolver` object. This allows you to provide custom JavaScript functions for resolving `@import` specifiers to file paths, and reading files from the file system (or another source). The `read` and `resolve` functions are both optional, and may either return a string synchronously, or a Promise for asynchronous resolution.
```js
-import { bundleAsync } from 'lightningcss';
+import {bundleAsync} from 'lightningcss';
-let { code, map } = await bundleAsync({
+let {code, map} = await bundleAsync({
filename: 'style.css',
minify: true,
resolver: {
@@ -169,8 +199,8 @@ let { code, map } = await bundleAsync({
},
resolve(specifier, from) {
return path.resolve(path.dirname(from), specifier);
- }
- }
+ },
+ },
});
```
diff --git a/website/pages/css-modules.md b/website/pages/css-modules.md
index d66016c3..cb50a349 100644
--- a/website/pages/css-modules.md
+++ b/website/pages/css-modules.md
@@ -13,16 +13,16 @@ CSS modules treat the classes defined in each file as unique. Each class name or
To enable CSS modules, provide the `cssModules` option when calling the Lightning CSS API. When using the CLI, enable the `--css-modules` flag.
```js
-import { transform } from 'lightningcss';
+import {transform} from 'lightningcss';
-let { code, map, exports } = transform({
+let {code, map, exports} = transform({
// ...
cssModules: true,
code: Buffer.from(`
.logo {
background: skyblue;
}
- `)
+ `),
});
```
@@ -89,7 +89,7 @@ You can also reference class names defined in a different CSS file using the `fr
```css
.logo {
- composes: bg-indigo from "./colors.module.css";
+ composes: bg-indigo from './colors.module.css';
}
```
@@ -150,10 +150,10 @@ compiles to:
By default, class names, id selectors, and the names of `@keyframes`, `@counter-style`, and CSS grid lines and areas are scoped to the module they are defined in. Scoping for CSS variables and other [``](https://www.w3.org/TR/css-values-4/#dashed-idents) names can also be enabled using the `dashedIdents` option when calling the Lightning CSS API. When using the CLI, enable the `--css-modules-dashed-idents` flag.
```js
-let { code, map, exports } = transform({
+let {code, map, exports} = transform({
// ...
cssModules: {
- dashedIdents: true
+ dashedIdents: true,
},
});
```
@@ -186,7 +186,7 @@ You can also reference variables defined in other files using the `from` keyword
```css
.button {
- background: var(--accent-color from "./vars.module.css");
+ background: var(--accent-color from './vars.module.css');
}
```
@@ -207,19 +207,19 @@ By default, Lightning CSS prepends the hash of the filename to each class name a
A pattern is a string with placeholders that will be filled in by Lightning CSS. This allows you to add custom prefixes or adjust the naming convention for scoped classes.
```js
-let { code, map, exports } = transform({
+let {code, map, exports} = transform({
// ...
cssModules: {
- pattern: 'my-company-[name]-[hash]-[local]'
- }
+ pattern: 'my-company-[name]-[hash]-[local]',
+ },
});
```
The following placeholders are currently supported:
-* `[name]` - The base name of the file, without the extension.
-* `[hash]` - A hash of the full file path.
-* `[local]` - The original class name or identifier.
+- `[name]` - The base name of the file, without the extension.
+- `[hash]` - A hash of the full file path.
+- `[local]` - The original class name or identifier.
@@ -231,7 +231,7 @@ The following placeholders are currently supported:
let { code, map, exports } = transform({
// ...
cssModules: {
- // ❌ [local] must be at the end so that
+ // ❌ [local] must be at the end so that
// auto-generated grid line names work
pattern: '[local]-[hash]'
// ✅ do this instead
@@ -242,7 +242,7 @@ let { code, map, exports } = transform({
```css
.grid {
- grid-template-areas: "nav main";
+ grid-template-areas: 'nav main';
}
.nav {
@@ -256,6 +256,6 @@ let { code, map, exports } = transform({
Lightning CSS does not currently implement all CSS modules features available in other implementations. Some of these may be added in the future.
-* Non-function syntax for the `:local` and `:global` pseudo classes.
-* The `@value` rule – superseded by standard CSS variables.
-* The `:import` and `:export` ICSS rules.
+- Non-function syntax for the `:local` and `:global` pseudo classes.
+- The `@value` rule – superseded by standard CSS variables.
+- The `:import` and `:export` ICSS rules.
diff --git a/website/pages/docs.md b/website/pages/docs.md
index 64496e6f..cb40efe8 100644
--- a/website/pages/docs.md
+++ b/website/pages/docs.md
@@ -19,13 +19,13 @@ npm install --save-dev lightningcss
Once installed, import the module and call one of the Lightning CSS APIs. The `transform` function compiles a CSS stylesheet from a [Node Buffer](https://nodejs.org/api/buffer.html). This example minifies the input CSS, and outputs the compiled code and a source map.
```js
-import { transform } from 'lightningcss';
+import {transform} from 'lightningcss';
-let { code, map } = transform({
+let {code, map} = transform({
filename: 'style.css',
code: Buffer.from('.foo { color: red }'),
minify: true,
- sourceMap: true
+ sourceMap: true,
});
```
@@ -67,7 +67,7 @@ See the [Parcel docs](https://parceljs.org/languages/css) for more details.
The `lightningcss-wasm` package can be used in Deno or directly in browsers. This uses a WebAssembly build of Lightning CSS. Use `TextEncoder` and `TextDecoder` convert code from a string to a typed array and back.
```js
-import init, { transform } from 'https://esm.run/lightningcss-wasm';
+import init, {transform} from 'https://esm.run/lightningcss-wasm';
await init();
@@ -105,7 +105,7 @@ module.exports = {
new CssMinimizerPlugin({
minify: CssMinimizerPlugin.lightningCssMinify,
minimizerOptions: {
- targets: lightningcss.browserslistToTargets(browserslist('>= 0.25%'))
+ targets: lightningcss.browserslistToTargets(browserslist('>= 0.25%')),
},
}),
],
@@ -131,12 +131,12 @@ export default {
css: {
transformer: 'lightningcss',
lightningcss: {
- targets: browserslistToTargets(browserslist('>= 0.25%'))
- }
+ targets: browserslistToTargets(browserslist('>= 0.25%')),
+ },
},
build: {
- cssMinify: 'lightningcss'
- }
+ cssMinify: 'lightningcss',
+ },
};
```
diff --git a/website/pages/minification.md b/website/pages/minification.md
index ad5b7b21..b7f883e8 100644
--- a/website/pages/minification.md
+++ b/website/pages/minification.md
@@ -9,11 +9,11 @@
Lightning CSS can optimize your CSS to make it smaller, which can help improve the loading performance of your website. When using the Lightning CSS API, enable the `minify` option, or when using the CLI, use the `--minify` flag.
```js
-import { transform } from 'lightningcss';
+import {transform} from 'lightningcss';
-let { code, map } = transform({
+let {code, map} = transform({
// ...
- minify: true
+ minify: true,
});
```
@@ -37,7 +37,9 @@ Lightning CSS will combine longhand properties into shorthands when all of the c
minifies to:
```css
-.foo{padding:1px 4px 3px 2px}
+.foo {
+ padding: 1px 4px 3px 2px;
+}
```
This is supported across most shorthand properties defined in the CSS spec.
@@ -67,7 +69,14 @@ Lightning CSS will merge adjacent style rules with the same selectors or declara
becomes:
```css
-.a,.b{color:red}.c{color:green;padding:10px}
+.a,
+.b {
+ color: red;
+}
+.c {
+ color: green;
+ padding: 10px;
+}
```
In addition to style rules, Lightning CSS will also merge adjacent `@media`, `@supports`, and `@container` rules with identical queries, and adjacent `@layer` rules with the same layer name.
@@ -91,7 +100,9 @@ For example, when compiling for modern browsers, prefixed versions of the `trans
becomes:
```css
-.button{transition:background .2s}
+.button {
+ transition: background 0.2s;
+}
```
See [Transpilation](transpilation.html) for more on how to configure browser targets.
@@ -110,7 +121,10 @@ Lightning CSS will reduce `calc()` and other math expressions to constant values
minifies to:
```css
-.foo{width:200px;height:calc(75.37% - 763.5px)}
+.foo {
+ width: 200px;
+ height: calc(75.37% - 763.5px);
+}
```
Note that `calc()` expressions with variables are currently left unmodified by Lightning CSS.
@@ -121,14 +135,16 @@ Lightning CSS will minify colors to the smallest format possible without changin
```css
.foo {
- color: rgba(255, 255, 0, 0.8)
+ color: rgba(255, 255, 0, 0.8);
}
```
minifies to:
```css
-.foo{color:#ff0c}
+.foo {
+ color: #ff0c;
+}
```
Note that only colors in the RGB gamut (including HSL and HWB) are converted to hex. Colors in other color spaces such as LAB or P3 are preserved.
@@ -145,7 +161,10 @@ In addition to static colors, Lightning CSS also supports many color functions s
minifies to:
```css
-.foo{color:#669;background:#545c3d}
+.foo {
+ color: #669;
+ background: #545c3d;
+}
```
Note that these conversions cannot be performed when any of the components include CSS variables.
@@ -163,7 +182,9 @@ Lightning CSS parses all properties and values according to the CSS specificatio
minifies to:
```css
-.foo{background:red}
+.foo {
+ background: red;
+}
```
In addition to removing defaults, Lightning CSS also omits quotes, whitespace, and optional delimiters where possible. It also converts values to shorter equivalents where possible.
@@ -172,14 +193,18 @@ In addition to removing defaults, Lightning CSS also omits quotes, whitespace, a
.foo {
font-weight: bold;
background-position: center center;
- background-image: url("logo.png");
+ background-image: url('logo.png');
}
```
minifies to:
```css
-.foo{background-image:url(logo.png);background-position:50%;font-weight:700}
+.foo {
+ background-image: url(logo.png);
+ background-position: 50%;
+ font-weight: 700;
+}
```
### CSS grid templates
@@ -188,16 +213,19 @@ Lightning CSS will minify the `grid-template-areas` property to remove unnecessa
```css
.foo {
- grid-template-areas: "head head"
- "nav main"
- "foot ....";
+ grid-template-areas:
+ 'head head'
+ 'nav main'
+ 'foot ....';
}
```
minifies to:
```css
-.foo{grid-template-areas:"head head""nav main""foot."}
+.foo {
+ grid-template-areas: 'head head' 'nav main' 'foot.';
+}
```
### Reduce transforms
@@ -213,21 +241,42 @@ Lightning CSS will reduce CSS transform functions to shorter equivalents where p
minifies to:
```css
-.foo{transform:translateY(50px)}
+.foo {
+ transform: translateY(50px);
+}
```
In addition, the `matrix()` and `matrix3d()` functions are converted to their equivalent transforms when shorter:
```css
.foo {
- transform: matrix3d(1, 0, 0, 0, 0, 0.707106, 0.707106, 0, 0, -0.707106, 0.707106, 0, 100, 100, 10, 1);
+ transform: matrix3d(
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0.707106,
+ 0.707106,
+ 0,
+ 0,
+ -0.707106,
+ 0.707106,
+ 0,
+ 100,
+ 100,
+ 10,
+ 1
+ );
}
```
minifies to:
```css
-.foo{transform:translate3d(100px,100px,10px)rotateX(45deg)}
+.foo {
+ transform: translate3d(100px, 100px, 10px) rotateX(45deg);
+}
```
When a matrix would be shorter, individual transform functions are converted to a single matrix instead:
@@ -241,7 +290,9 @@ When a matrix would be shorter, individual transform functions are converted to
minifies to:
```css
-.foo{transform:matrix(1.41421,1.41421,-1.16485,1.66358,100,200)}
+.foo {
+ transform: matrix(1.41421, 1.41421, -1.16485, 1.66358, 100, 200);
+}
```
## Unused symbols
@@ -249,10 +300,10 @@ minifies to:
If you know that certain class names, ids, `@keyframes` rules, CSS variables, or other CSS identifiers are unused (for example as part of a larger full project analysis), you can use the `unusedSymbols` option to remove them.
```js
-let { code, map } = transform({
+let {code, map} = transform({
// ...
minify: true,
- unusedSymbols: ['foo', 'fade-in', '--color']
+ unusedSymbols: ['foo', 'fade-in', '--color'],
});
```
@@ -268,8 +319,12 @@ With this configuration, the following CSS:
}
@keyframes fade-in {
- from { opacity: 0 }
- to { opacity: 1 }
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
}
.bar {
@@ -280,5 +335,7 @@ With this configuration, the following CSS:
minifies to:
```css
-.bar{color:green}
+.bar {
+ color: green;
+}
```
diff --git a/website/pages/transforms.md b/website/pages/transforms.md
index e64d1d9f..34e341d8 100644
--- a/website/pages/transforms.md
+++ b/website/pages/transforms.md
@@ -17,7 +17,7 @@ Custom transforms are implemented by passing a `visitor` object to the Lightning
Visitors can return a new value to update it. Each visitor accepts a different type of value, and usually expects the same type in return. This example multiplies all lengths by 2:
```js
-import { transform } from 'lightningcss';
+import {transform} from 'lightningcss';
let res = transform({
filename: 'test.css',
@@ -31,10 +31,10 @@ let res = transform({
Length(length) {
return {
unit: length.unit,
- value: length.value * 2
- }
- }
- }
+ value: length.value * 2,
+ };
+ },
+ },
});
assert.equal(res.code.toString(), '.foo{width:24px}');
@@ -56,25 +56,33 @@ let res = transform({
visitor: {
Property: {
overflow(property) {
- return [{
- property: 'custom',
- value: {
- name: '-webkit-overflow-scrolling',
- value: [{
- type: 'token',
- value: {
- type: 'ident',
- value: 'touch'
- }
- }]
- }
- }, property];
+ return [
+ {
+ property: 'custom',
+ value: {
+ name: '-webkit-overflow-scrolling',
+ value: [
+ {
+ type: 'token',
+ value: {
+ type: 'ident',
+ value: 'touch',
+ },
+ },
+ ],
+ },
+ },
+ property,
+ ];
},
- }
- }
+ },
+ },
});
-assert.equal(res.code.toString(), '.foo{-webkit-overflow-scrolling:touch;overflow:auto}');
+assert.equal(
+ res.code.toString(),
+ '.foo{-webkit-overflow-scrolling:touch;overflow:auto}',
+);
```
## Value types
@@ -97,9 +105,9 @@ transform({
} else {
// Handle parsed value, e.g. `12px`
}
- }
- }
- }
+ },
+ },
+ },
});
```
@@ -121,18 +129,18 @@ let res = transform({
if (property.value[0].type === 'length') {
let value = {
type: 'length-percentage',
- value: { type: 'dimension', value: property.value[0].value }
+ value: {type: 'dimension', value: property.value[0].value},
};
return [
- { property: 'width', value },
- { property: 'height', value }
+ {property: 'width', value},
+ {property: 'height', value},
];
}
- }
- }
- }
- }
+ },
+ },
+ },
+ },
});
assert.equal(res.code.toString(), '.foo{width:12px;height:12px}');
@@ -155,10 +163,10 @@ let res = transform({
visitor: {
Function: {
color() {
- return { raw: 'rgb(255, 0, 0)' };
- }
- }
- }
+ return {raw: 'rgb(255, 0, 0)'};
+ },
+ },
+ },
});
assert.equal(res.code.toString(), '.foo{color:red}');
@@ -188,11 +196,11 @@ let res = transform({
type: 'length',
value: {
unit: f.arguments[0].value.unit,
- value: f.arguments[0].value.value * 2
- }
+ value: f.arguments[0].value.value * 2,
+ },
};
}
- }
+ },
},
EnvironmentVariable: {
// This will run before the FunctionExit visitor, above.
@@ -200,11 +208,11 @@ let res = transform({
type: 'length',
value: {
unit: 'px',
- value: 20
- }
- })
- }
- }
+ value: 20,
+ },
+ }),
+ },
+ },
});
assert.equal(res.code.toString(), '.foo{padding:40px}');
@@ -215,7 +223,7 @@ assert.equal(res.code.toString(), '.foo{padding:40px}');
Multiple visitors can be combined into one using the `composeVisitors` function. This lets you reuse visitors between projects by publishing them as plugins. The AST is visited in a single pass, running the functions from each visitor object as if they were written together.
```js
-import { transform, composeVisitors } from 'lightningcss';
+import {transform, composeVisitors} from 'lightningcss';
let environmentVisitor = {
EnvironmentVariable: {
@@ -223,10 +231,10 @@ let environmentVisitor = {
type: 'length',
value: {
unit: 'px',
- value: 20
- }
- })
- }
+ value: 20,
+ },
+ }),
+ },
};
let doubleFunctionVisitor = {
@@ -237,12 +245,12 @@ let doubleFunctionVisitor = {
type: 'length',
value: {
unit: f.arguments[0].value.unit,
- value: f.arguments[0].value.value * 2
- }
+ value: f.arguments[0].value.value * 2,
+ },
};
}
- }
- }
+ },
+ },
};
let res = transform({
@@ -253,7 +261,7 @@ let res = transform({
padding: double(env(--branding-padding));
}
`),
- visitor: composeVisitors([environmentVisitor, doubleFunctionVisitor])
+ visitor: composeVisitors([environmentVisitor, doubleFunctionVisitor]),
});
assert.equal(res.code.toString(), '.foo{padding:40px}');
@@ -282,14 +290,14 @@ let res = transform({
unknown(rule) {
declared.set(rule.name, rule.prelude);
return [];
- }
+ },
},
Token: {
'at-keyword'(token) {
return declared.get(token.value);
- }
- }
- }
+ },
+ },
+ },
});
assert.equal(res.code.toString(), '.menu_link{background:#056ef0}');
@@ -301,9 +309,9 @@ Raw tokens as stored in unknown at-rules are fine for simple cases, but in more
The syntax of the at-rule prelude can be defined with a [CSS syntax string](https://drafts.css-houdini.org/css-properties-values-api/#syntax-strings), which Lightning CSS will interpret and use to validate the input CSS. This uses the same syntax as the [@property](https://developer.mozilla.org/en-US/docs/Web/CSS/@property) rule. The body syntax is defined using one of the following options:
-* `"declaration-list"` – A list of CSS declarations (property value pairs), as in a style rule or other at-rules like `@font-face`.
-* `"rule-list"` – A list of nested CSS rules, including style rules and at rules. Directly nested declarations with CSS nesting are not allowed. This matches how rules like `@keyframes` are parsed.
-* `"style-block"` – A list of CSS declarations and/or nested rules. This matches the behavior of rules like `@media` and `@supports` which support directly nested declarations when inside a style rule. Note that the [nesting](transpilation.html#nesting) and [targets](transpilation.html#browser-targets) options must be defined for nesting to be compiled.
+- `"declaration-list"` – A list of CSS declarations (property value pairs), as in a style rule or other at-rules like `@font-face`.
+- `"rule-list"` – A list of nested CSS rules, including style rules and at rules. Directly nested declarations with CSS nesting are not allowed. This matches how rules like `@keyframes` are parsed.
+- `"style-block"` – A list of CSS declarations and/or nested rules. This matches the behavior of rules like `@media` and `@supports` which support directly nested declarations when inside a style rule. Note that the [nesting](transpilation.html#nesting) and [targets](transpilation.html#browser-targets) options must be defined for nesting to be compiled.
This example defines two custom at-rules. `@mixin` defines a reusable style block, supporting both directly nested declarations and nested rules. A visitor function registers the mixin in a map and removes the custom rule. `@apply` looks up the requested mixin in the map and returns the nested rules, which are inlined into the parent.
@@ -312,7 +320,7 @@ let mixins = new Map();
let res = transform({
filename: 'test.css',
minify: true,
- targets: { chrome: 100 << 16 },
+ targets: {chrome: 100 << 16},
code: Buffer.from(`
@mixin color {
color: red;
@@ -329,11 +337,11 @@ let res = transform({
customAtRules: {
mixin: {
prelude: '',
- body: 'style-block'
+ body: 'style-block',
},
apply: {
- prelude: ''
- }
+ prelude: '',
+ },
},
visitor: {
Rule: {
@@ -344,10 +352,10 @@ let res = transform({
},
apply(rule) {
return mixins.get(rule.prelude.value);
- }
- }
- }
- }
+ },
+ },
+ },
+ },
});
assert.equal(res.code.toString(), '.foo{color:red}.foo.bar{color:#ff0}');
@@ -367,8 +375,8 @@ export default {
FunctionExit: {
double(f) {
// ...
- }
- }
+ },
+ },
};
```
@@ -379,7 +387,7 @@ Plugins can also export a function in order to accept options.
export default (values) => ({
EnvironmentVariable(env) {
return values[env.name];
- }
+ },
});
```
@@ -398,7 +406,7 @@ Plugin package names should start with `lightningcss-plugin-` and be descriptive
To use a published visitor plugin, install the package from npm, import it, and use the `composeVisitors` function as described above.
```js
-import { transform, composeVisitors } from 'lightningcss';
+import {transform, composeVisitors} from 'lightningcss';
import environmentVisitor from 'lightningcss-plugin-environment';
import doubleFunctionVisitor from 'lightningcss-plugin-double-function';
@@ -416,12 +424,12 @@ let res = transform({
type: 'length',
value: {
unit: 'px',
- value: 20
- }
- }
+ value: 20,
+ },
+ },
}),
- doubleFunctionVisitor
- ])
+ doubleFunctionVisitor,
+ ]),
});
assert.equal(res.code.toString(), '.foo{padding:40px}');
diff --git a/website/pages/transpilation.md b/website/pages/transpilation.md
index abf0ef86..64c88906 100644
--- a/website/pages/transpilation.md
+++ b/website/pages/transpilation.md
@@ -16,15 +16,15 @@ Targets are defined using an object that specifies the minimum version of each b
```js
import browserslist from 'browserslist';
-import { transform, browserslistToTargets } from 'lightningcss';
+import {transform, browserslistToTargets} from 'lightningcss';
// Call this once per build.
let targets = browserslistToTargets(browserslist('>= 0.25%'));
// Use `targets` for each file you transform.
-let { code, map } = transform({
+let {code, map} = transform({
// ...
- targets
+ targets,
});
```
@@ -34,7 +34,7 @@ Under the hood, `targets` are represented using an object that maps browser name
```js
let targets = {
- safari: (13 << 16) | (2 << 8)
+ safari: (13 << 16) | (2 << 8),
};
```
@@ -76,15 +76,15 @@ The `include` and `exclude` options allow you to explicitly turn on or off certa
The `include` and `exclude` options are configured using the `Features` enum, which can be imported from `lightningcss`. You can bitwise OR multiple flags together to turn them on or off.
```js
-import { transform, Features } from 'lightningcss';
+import {transform, Features} from 'lightningcss';
-let { code, map } = transform({
+let {code, map} = transform({
// ...
targets,
// Always compile colors and CSS nesting, regardless of browser targets.
include: Features.Colors | Features.Nesting,
// Never add any vendor prefixes, regardless of targets.
- exclude: Features.VendorPrefixes
+ exclude: Features.VendorPrefixes,
});
```
@@ -92,35 +92,35 @@ Here is a full list of available flags, described in the sections below:
## Vendor prefixing
-Based on your configured browser targets, Lightning CSS automatically adds vendor prefixed fallbacks for many CSS features. For example, when using the [`image-set()`](https://developer.mozilla.org/en-US/docs/Web/CSS/image/image-set()) function, Lightning CSS will output a fallback `-webkit-image-set()` value as well, since Chrome does not yet support the unprefixed value.
+Based on your configured browser targets, Lightning CSS automatically adds vendor prefixed fallbacks for many CSS features. For example, when using the [`image-set()`]() function, Lightning CSS will output a fallback `-webkit-image-set()` value as well, since Chrome does not yet support the unprefixed value.
```css
.logo {
@@ -133,7 +133,7 @@ compiles to:
```css
.logo {
background: -webkit-image-set(url(logo.png) 2x, url(logo.png) 1x);
- background: image-set("logo.png" 2x, "logo.png");
+ background: image-set('logo.png' 2x, 'logo.png');
}
```
@@ -151,7 +151,7 @@ becomes:
```css
.button {
- transition: background .2s;
+ transition: background 0.2s;
}
```
@@ -251,7 +251,7 @@ compiles to:
### LAB colors
-Lightning CSS will convert [`lab()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/lab()), [`lch()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/lch()), [`oklab()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklab), and [`oklch()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch) colors to fallback values for unsupported browsers when needed. These functions allow you to define colors in higher gamut color spaces, making it possible to use colors that cannot be represented by RGB.
+Lightning CSS will convert [`lab()`](), [`lch()`](), [`oklab()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklab), and [`oklch()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch) colors to fallback values for unsupported browsers when needed. These functions allow you to define colors in higher gamut color spaces, making it possible to use colors that cannot be represented by RGB.
```css
.foo {
@@ -264,7 +264,7 @@ compiles to:
```css
.foo {
color: #b32323;
- color: color(display-p3 .643308 .192455 .167712);
+ color: color(display-p3 0.643308 0.192455 0.167712);
color: lab(40% 56.6 39);
}
```
@@ -273,7 +273,7 @@ As shown above, a `display-p3` fallback is included in addition to RGB when a ta
### Color function
-Lightning CSS converts the [`color()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color()) function to RGB when needed for compatibility with older browsers. This allows you to use predefined color spaces such as `display-p3`, `xyz`, and `a98-rgb`.
+Lightning CSS converts the [`color()`]() function to RGB when needed for compatibility with older browsers. This allows you to use predefined color spaces such as `display-p3`, `xyz`, and `a98-rgb`.
```css
.foo {
@@ -286,7 +286,7 @@ compiles to:
```css
.foo {
background-color: #6a805d;
- background-color: color(a98-rgb .44091 .49971 .37408);
+ background-color: color(a98-rgb 0.44091 0.49971 0.37408);
}
```
@@ -323,7 +323,7 @@ compiles to:
```css
.foo {
- color: rgba(123, 255, 255, .5);
+ color: rgba(123, 255, 255, 0.5);
background: #7bffff;
}
```
@@ -339,11 +339,11 @@ html {
color-scheme: light dark;
}
-html[data-theme=light] {
+html[data-theme='light'] {
color-scheme: light;
}
-html[data-theme=dark] {
+html[data-theme='dark'] {
color-scheme: dark;
}
@@ -368,13 +368,13 @@ html {
}
}
-html[data-theme="light"] {
+html[data-theme='light'] {
--lightningcss-light: initial;
--lightningcss-dark: ;
color-scheme: light;
}
-html[data-theme="dark"] {
+html[data-theme='dark'] {
--lightningcss-light: ;
--lightningcss-dark: initial;
color-scheme: dark;
@@ -387,11 +387,11 @@ button {
### Logical properties
-CSS [logical properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties) allow you to define values in terms of writing direction, so that UIs mirror in right-to-left languages. Lightning CSS will compile these to use the `:dir()` selector when unsupported. If the `:dir()` selector is unsupported, it is compiled as described [below](#%3Adir()-selector).
+CSS [logical properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties) allow you to define values in terms of writing direction, so that UIs mirror in right-to-left languages. Lightning CSS will compile these to use the `:dir()` selector when unsupported. If the `:dir()` selector is unsupported, it is compiled as described [below](<#%3Adir()-selector>).
```css
.foo {
- border-start-start-radius: 20px
+ border-start-start-radius: 20px;
}
```
@@ -407,26 +407,45 @@ compiles to:
}
```
-
### :dir() selector
The [`:dir()`](https://developer.mozilla.org/en-US/docs/Web/CSS/:dir) selector matches elements based on the writing direction. Lightning CSS compiles this to use the `:lang()` selector when unsupported, which approximates this behavior as closely as possible.
```css
a:dir(rtl) {
- color:red
+ color: red;
}
```
compiles to:
```css
-a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
+a:lang(
+ ae,
+ ar,
+ arc,
+ bcc,
+ bqi,
+ ckb,
+ dv,
+ fa,
+ glk,
+ he,
+ ku,
+ mzn,
+ nqo,
+ pnb,
+ ps,
+ sd,
+ ug,
+ ur,
+ yi
+ ) {
color: red;
}
```
-If multiple arguments to `:lang()` are unsupported, it is compiled as described [below](#%3Alang()-selector).
+If multiple arguments to `:lang()` are unsupported, it is compiled as described [below](<#%3Alang()-selector>).
### :lang() selector
@@ -434,7 +453,7 @@ The [`:lang()`](https://developer.mozilla.org/en-US/docs/Web/CSS/:lang) selector
```css
a:lang(en, fr) {
- color:red
+ color: red;
}
```
@@ -446,7 +465,7 @@ a:is(:lang(en), :lang(fr)) {
}
```
-When the `:is()` selector is unsupported, it is compiled as described [below](#%3Ais()-selector).
+When the `:is()` selector is unsupported, it is compiled as described [below](<#%3Ais()-selector>).
### :is() selector
@@ -522,7 +541,9 @@ compiles to:
```css
@media (480px <= width <= 768px) {
- .foo { color: red }
+ .foo {
+ color: red;
+ }
}
```
@@ -530,7 +551,9 @@ compiles to:
```css
@media (min-width: 480px) and (max-width: 768px) {
- .foo { color: red }
+ .foo {
+ color: red;
+ }
}
```
@@ -538,10 +561,10 @@ compiles to:
Lightning CSS compiles the following shorthands to corresponding longhands when the shorthand is not supported in all target browsers:
-* Alignment shorthands: [place-items](https://developer.mozilla.org/en-US/docs/Web/CSS/place-items), [place-content](https://developer.mozilla.org/en-US/docs/Web/CSS/place-content), [place-self](https://developer.mozilla.org/en-US/docs/Web/CSS/place-self)
-* [Overflow shorthand](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow) with multiple values (e.g. `overflow: hidden auto`)
-* [text-decoration](https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration) with thickness, style, color, etc.
-* Two value [display](https://developer.mozilla.org/en-US/docs/Web/CSS/display) syntax (e.g. `display: inline flex`)
+- Alignment shorthands: [place-items](https://developer.mozilla.org/en-US/docs/Web/CSS/place-items), [place-content](https://developer.mozilla.org/en-US/docs/Web/CSS/place-content), [place-self](https://developer.mozilla.org/en-US/docs/Web/CSS/place-self)
+- [Overflow shorthand](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow) with multiple values (e.g. `overflow: hidden auto`)
+- [text-decoration](https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration) with thickness, style, color, etc.
+- Two value [display](https://developer.mozilla.org/en-US/docs/Web/CSS/display) syntax (e.g. `display: inline flex`)
### Double position gradients
@@ -575,7 +598,8 @@ compiles to:
```css
.foo {
- font-family: system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue;
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
+ Noto Sans, Ubuntu, Cantarell, Helvetica Neue;
}
```
@@ -593,7 +617,9 @@ For example:
@custom-media --modern (color), (hover);
@media (--modern) and (width > 1024px) {
- .a { color: green; }
+ .a {
+ color: green;
+ }
}
```
@@ -601,18 +627,20 @@ is equivalent to:
```css
@media ((color) or (hover)) and (width > 1024px) {
- .a { color: green; }
+ .a {
+ color: green;
+ }
}
```
Because custom media queries are a draft, they are not enabled by default. To use them, enable the `customMedia` option under `drafts` when calling the Lightning CSS API. When using the CLI, enable the `--custom-media` flag.
```js
-let { code, map } = transform({
+let {code, map} = transform({
// ...
drafts: {
- customMedia: true
- }
+ customMedia: true,
+ },
});
```
@@ -621,11 +649,11 @@ let { code, map } = transform({
Lightning CSS supports replacing CSS pseudo classes such as `:focus-visible` with normal CSS classes that can be applied using JavaScript. This makes it possible to polyfill these pseudo classes for older browsers.
```js
-let { code, map } = transform({
+let {code, map} = transform({
// ...
pseudoClasses: {
- focusVisible: 'focus-visible'
- }
+ focusVisible: 'focus-visible',
+ },
});
```
@@ -633,26 +661,25 @@ The above configuration will result in the `:focus-visible` pseudo class in all
The following pseudo classes may be configured as shown above:
-* `hover` – corresponds to the `:hover` pseudo class
-* `active` – corresponds to the `:active` pseudo class
-* `focus` – corresponds to the `:focus` pseudo class
-* `focusVisible` – corresponds to the `:focus-visible` pseudo class
-* `focusWithin` – corresponds to the `:focus-within` pseudo class
+- `hover` – corresponds to the `:hover` pseudo class
+- `active` – corresponds to the `:active` pseudo class
+- `focus` – corresponds to the `:focus` pseudo class
+- `focusVisible` – corresponds to the `:focus-visible` pseudo class
+- `focusWithin` – corresponds to the `:focus-within` pseudo class
## Non-standard syntax
For compatibility with other tools, Lightning CSS supports parsing some non-standard CSS syntax. This must be enabled by turning on a flag under the `nonStandard` option.
```js
-let { code, map } = transform({
+let {code, map} = transform({
// ...
nonStandard: {
- deepSelectorCombinator: true
- }
+ deepSelectorCombinator: true,
+ },
});
-
```
Currently the following features are supported:
-* `deepSelectorCombinator` – enables parsing the Vue/Angular `>>>` and `/deep/` selector combinators.
+- `deepSelectorCombinator` – enables parsing the Vue/Angular `>>>` and `/deep/` selector combinators.
diff --git a/website/playground/index.html b/website/playground/index.html
index a4ade5ed..989f1664 100644
--- a/website/playground/index.html
+++ b/website/playground/index.html
@@ -4,12 +4,21 @@
⚡️ Lightning CSS Playground
@font-face {
- font-family:"urbane-rounded";
- src:url("https://use.typekit.net/af/916187/00000000000000007735bfa0/30/l?primer=81a69539b194230396845be9681d114557adfb35f4cccc679c164afb4aa47365&fvd=n6&v=3") format("woff2"),url("https://use.typekit.net/af/916187/00000000000000007735bfa0/30/d?primer=81a69539b194230396845be9681d114557adfb35f4cccc679c164afb4aa47365&fvd=n6&v=3") format("woff"),url("https://use.typekit.net/af/916187/00000000000000007735bfa0/30/a?primer=81a69539b194230396845be9681d114557adfb35f4cccc679c164afb4aa47365&fvd=n6&v=3") format("opentype");
- font-display:auto;font-style:normal;font-weight:600;font-stretch:normal;
+ font-family: 'urbane-rounded';
+ src: url('https://use.typekit.net/af/916187/00000000000000007735bfa0/30/l?primer=81a69539b194230396845be9681d114557adfb35f4cccc679c164afb4aa47365&fvd=n6&v=3')
+ format('woff2'),
+ url('https://use.typekit.net/af/916187/00000000000000007735bfa0/30/d?primer=81a69539b194230396845be9681d114557adfb35f4cccc679c164afb4aa47365&fvd=n6&v=3')
+ format('woff'),
+ url('https://use.typekit.net/af/916187/00000000000000007735bfa0/30/a?primer=81a69539b194230396845be9681d114557adfb35f4cccc679c164afb4aa47365&fvd=n6&v=3')
+ format('opentype');
+ font-display: auto;
+ font-style: normal;
+ font-weight: 600;
+ font-stretch: normal;
}
- html, body {
+ html,
+ body {
margin: 0;
height: 100%;
box-sizing: border-box;
@@ -77,8 +86,9 @@
main {
display: grid;
- grid-template-areas: "sidebar source compiled compiled"
- "sidebar visitor compiledModules compiledDependencies";
+ grid-template-areas:
+ 'sidebar source compiled compiled'
+ 'sidebar visitor compiledModules compiledDependencies';
grid-template-columns: auto 2fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
flex: 1;
@@ -101,7 +111,7 @@
overflow: hidden;
}
- #source[data-expanded=true] {
+ #source[data-expanded='true'] {
grid-row: source-start / visitor-end;
}
@@ -110,7 +120,7 @@
overflow: hidden;
}
- #compiled[data-expanded=true] {
+ #compiled[data-expanded='true'] {
grid-row: compiled-start / compiledDependencies-end;
grid-column: compiled-start / compiledDependencies-end;
}
@@ -125,8 +135,8 @@
overflow: hidden;
}
- #compiledModules[data-expanded=true],
- #compiledDependencies[data-expanded=true] {
+ #compiledModules[data-expanded='true'],
+ #compiledDependencies[data-expanded='true'] {
grid-row: compiledModules-start;
grid-column: compiledModules-start / compiledDependencies-end;
}
@@ -155,33 +165,67 @@
Lightning CSS Playground
-
-
+
+
diff --git a/website/playground/playground.js b/website/playground/playground.js
index 81ce4bb0..4022e761 100644
--- a/website/playground/playground.js
+++ b/website/playground/playground.js
@@ -1,14 +1,14 @@
import * as localWasm from '../../wasm';
-import { EditorView, basicSetup } from 'codemirror';
-import { javascript } from '@codemirror/lang-javascript';
-import { css } from '@codemirror/lang-css';
-import { oneDark } from '@codemirror/theme-one-dark';
-import { syntaxTree } from '@codemirror/language';
-import { linter, lintGutter } from '@codemirror/lint'
-import { Compartment } from '@codemirror/state'
+import {EditorView, basicSetup} from 'codemirror';
+import {javascript} from '@codemirror/lang-javascript';
+import {css} from '@codemirror/lang-css';
+import {oneDark} from '@codemirror/theme-one-dark';
+import {syntaxTree} from '@codemirror/language';
+import {linter, lintGutter} from '@codemirror/lint';
+import {Compartment} from '@codemirror/state';
-const linterCompartment = new Compartment;
-const visitorLinterCompartment = new Compartment;
+const linterCompartment = new Compartment();
+const visitorLinterCompartment = new Compartment();
let wasm;
let editor, visitorEditor, outputEditor, modulesEditor, depsEditor;
@@ -17,24 +17,29 @@ let dec = new TextDecoder();
let inputs = document.querySelectorAll('input[type=number]');
async function loadVersions() {
- const { versions } = await fetch('https://data.jsdelivr.com/v1/package/npm/lightningcss-wasm').then(r => r.json());
+ const {versions} = await fetch(
+ 'https://data.jsdelivr.com/v1/package/npm/lightningcss-wasm',
+ ).then((r) => r.json());
versions
- .map(v => {
+ .map((v) => {
const option = document.createElement('option');
option.value = v;
option.textContent = v;
return option;
})
- .forEach(o => {
+ .forEach((o) => {
version.appendChild(o);
- })
+ });
}
async function loadWasm() {
if (version.value === 'local') {
wasm = localWasm;
} else {
- wasm = await new Function('version', 'return import(`https://esm.sh/lightningcss-wasm@${version}?bundle`)')(version.value);
+ wasm = await new Function(
+ 'version',
+ 'return import(`https://esm.sh/lightningcss-wasm@${version}?bundle`)',
+ )(version.value);
}
await wasm.default();
}
@@ -81,7 +86,7 @@ function loadPlaygroundState() {
return color;
}
}
-}`
+}`,
};
}
}
@@ -110,7 +115,7 @@ function reflectPlaygroundState(playgroundState) {
}
if (playgroundState.targets) {
- const { targets } = playgroundState;
+ const {targets} = playgroundState;
for (let input of inputs) {
let value = targets[input.id];
input.value = value == null ? '' : value >> 16;
@@ -148,7 +153,10 @@ function savePlaygroundState() {
source: editor.state.doc.toString(),
visitorEnabled: visitorEnabled.checked,
visitor: visitorEditor.state.doc.toString(),
- unusedSymbols: unusedSymbols.value.split('\n').map(v => v.trim()).filter(Boolean),
+ unusedSymbols: unusedSymbols.value
+ .split('\n')
+ .map((v) => v.trim())
+ .filter(Boolean),
version: version.value,
};
@@ -190,12 +198,12 @@ function updateFeatures(elements, include) {
for (let checkbox of elements) {
let feature = wasm.Features[checkbox.value];
checkbox.checked = (include & feature) === feature;
- checkbox.indeterminate = !checkbox.checked && (include & feature);
+ checkbox.indeterminate = !checkbox.checked && include & feature;
}
}
function update() {
- const { transform } = wasm;
+ const {transform} = wasm;
const targets = getTargets();
let data = new FormData(sidebar);
@@ -210,24 +218,49 @@ function update() {
include,
exclude,
drafts: {
- customMedia: customMedia.checked
+ customMedia: customMedia.checked,
},
cssModules: cssModules.checked,
analyzeDependencies: analyzeDependencies.checked,
- unusedSymbols: unusedSymbols.value.split('\n').map(v => v.trim()).filter(Boolean),
- visitor: visitorEnabled.checked ? (0, eval)('(' + visitorEditor.state.doc.toString() + ')') : undefined,
+ unusedSymbols: unusedSymbols.value
+ .split('\n')
+ .map((v) => v.trim())
+ .filter(Boolean),
+ visitor: visitorEnabled.checked
+ ? (0, eval)('(' + visitorEditor.state.doc.toString() + ')')
+ : undefined,
});
- let update = outputEditor.state.update({ changes: { from: 0, to: outputEditor.state.doc.length, insert: dec.decode(res.code) } });
+ let update = outputEditor.state.update({
+ changes: {
+ from: 0,
+ to: outputEditor.state.doc.length,
+ insert: dec.decode(res.code),
+ },
+ });
outputEditor.update([update]);
if (res.exports) {
- let update = modulesEditor.state.update({ changes: { from: 0, to: modulesEditor.state.doc.length, insert: '// CSS module exports\n' + JSON.stringify(res.exports, false, 2) } });
+ let update = modulesEditor.state.update({
+ changes: {
+ from: 0,
+ to: modulesEditor.state.doc.length,
+ insert:
+ '// CSS module exports\n' + JSON.stringify(res.exports, false, 2),
+ },
+ });
modulesEditor.update([update]);
}
if (res.dependencies) {
- let update = depsEditor.state.update({ changes: { from: 0, to: depsEditor.state.doc.length, insert: '// Dependencies\n' + JSON.stringify(res.dependencies, false, 2) } });
+ let update = depsEditor.state.update({
+ changes: {
+ from: 0,
+ to: depsEditor.state.doc.length,
+ insert:
+ '// Dependencies\n' + JSON.stringify(res.dependencies, false, 2),
+ },
+ });
depsEditor.update([update]);
}
@@ -235,27 +268,36 @@ function update() {
compiledDependencies.hidden = !analyzeDependencies.checked;
visitor.hidden = !visitorEnabled.checked;
source.dataset.expanded = visitor.hidden;
- compiled.dataset.expanded = compiledModules.hidden && compiledDependencies.hidden;
+ compiled.dataset.expanded =
+ compiledModules.hidden && compiledDependencies.hidden;
compiledModules.dataset.expanded = compiledDependencies.hidden;
compiledDependencies.dataset.expanded = compiledModules.hidden;
editor.dispatch({
- effects: linterCompartment.reconfigure(createCssLinter(null, res.warnings))
+ effects: linterCompartment.reconfigure(
+ createCssLinter(null, res.warnings),
+ ),
});
visitorEditor.dispatch({
- effects: visitorLinterCompartment.reconfigure(createVisitorLinter(null))
+ effects: visitorLinterCompartment.reconfigure(createVisitorLinter(null)),
});
} catch (e) {
- let update = outputEditor.state.update({ changes: { from: 0, to: outputEditor.state.doc.length, insert: `/* ERROR: ${e.message} */` } });
+ let update = outputEditor.state.update({
+ changes: {
+ from: 0,
+ to: outputEditor.state.doc.length,
+ insert: `/* ERROR: ${e.message} */`,
+ },
+ });
outputEditor.update([update]);
editor.dispatch({
- effects: linterCompartment.reconfigure(createCssLinter(e))
+ effects: linterCompartment.reconfigure(createCssLinter(e)),
});
visitorEditor.dispatch({
- effects: visitorLinterCompartment.reconfigure(createVisitorLinter(e))
+ effects: visitorLinterCompartment.reconfigure(createVisitorLinter(e)),
});
}
@@ -263,80 +305,86 @@ function update() {
}
function createCssLinter(lastError, warnings) {
- return linter(view => {
- let diagnostics = [];
- if (lastError && lastError.loc) {
- let l = view.state.doc.line(lastError.loc.line);
- let loc = l.from + lastError.loc.column - 1;
- let node = syntaxTree(view.state).resolveInner(loc, 1);
- diagnostics.push(
- {
- from: node.from,
- to: node.to,
- message: lastError.message,
- severity: 'error'
- }
- );
- }
- if (warnings) {
- for (let warning of warnings) {
- let l = view.state.doc.line(warning.loc.line);
- let loc = l.from + warning.loc.column - 1;
+ return linter(
+ (view) => {
+ let diagnostics = [];
+ if (lastError && lastError.loc) {
+ let l = view.state.doc.line(lastError.loc.line);
+ let loc = l.from + lastError.loc.column - 1;
let node = syntaxTree(view.state).resolveInner(loc, 1);
diagnostics.push({
from: node.from,
to: node.to,
- message: warning.message,
- severity: 'warning'
+ message: lastError.message,
+ severity: 'error',
});
}
- }
- return diagnostics;
- }, { delay: 0 });
+ if (warnings) {
+ for (let warning of warnings) {
+ let l = view.state.doc.line(warning.loc.line);
+ let loc = l.from + warning.loc.column - 1;
+ let node = syntaxTree(view.state).resolveInner(loc, 1);
+ diagnostics.push({
+ from: node.from,
+ to: node.to,
+ message: warning.message,
+ severity: 'warning',
+ });
+ }
+ }
+ return diagnostics;
+ },
+ {delay: 0},
+ );
}
function createVisitorLinter(lastError) {
- return linter(view => {
- if (lastError && !lastError.loc) {
- // Firefox has lineNumber and columnNumber, Safari has line and column.
- let line = lastError.lineNumber ?? lastError.line;
- let column = lastError.columnNumber ?? lastError.column;
- if (lastError.column != null) {
- column--;
- }
-
- if (line == null) {
- // Chrome.
- let match = lastError.stack.match(/(?:(?:eval.*:)|(?:eval:))(?\d+):(?\d+)/);
- if (match) {
- line = Number(match.groups.line);
- column = Number(match.groups.column);
+ return linter(
+ (view) => {
+ if (lastError && !lastError.loc) {
+ // Firefox has lineNumber and columnNumber, Safari has line and column.
+ let line = lastError.lineNumber ?? lastError.line;
+ let column = lastError.columnNumber ?? lastError.column;
+ if (lastError.column != null) {
+ column--;
+ }
- // Chrome's column numbers are off by the amount of leading whitespace in the line.
- let l = view.state.doc.line(line);
- let m = l.text.match(/^\s*/);
- if (m) {
- column += m[0].length;
+ if (line == null) {
+ // Chrome.
+ let match = lastError.stack.match(
+ /(?:(?:eval.*:)|(?:eval:))(?\d+):(?\d+)/,
+ );
+ if (match) {
+ line = Number(match.groups.line);
+ column = Number(match.groups.column);
+
+ // Chrome's column numbers are off by the amount of leading whitespace in the line.
+ let l = view.state.doc.line(line);
+ let m = l.text.match(/^\s*/);
+ if (m) {
+ column += m[0].length;
+ }
}
}
- }
- if (line != null) {
- let l = view.state.doc.line(line);
- let loc = l.from + column;
- let node = syntaxTree(view.state).resolveInner(loc, -1);
- return [
- {
- from: node.from,
- to: node.to,
- message: lastError.message,
- severity: 'error'
- }
- ];
+ if (line != null) {
+ let l = view.state.doc.line(line);
+ let loc = l.from + column;
+ let node = syntaxTree(view.state).resolveInner(loc, -1);
+ return [
+ {
+ from: node.from,
+ to: node.to,
+ message: lastError.message,
+ severity: 'error',
+ },
+ ];
+ }
}
- }
- return [];
- }, { delay: 0 });
+ return [];
+ },
+ {delay: 0},
+ );
}
function renderFeatures(parent, name) {
@@ -358,7 +406,7 @@ function renderFeatures(parent, name) {
updateFeatures(sidebar.elements[name], flags);
};
label.appendChild(checkbox);
- label.appendChild(document.createTextNode(' ' + feature))
+ label.appendChild(document.createTextNode(' ' + feature));
parent.appendChild(label);
}
}
@@ -372,7 +420,13 @@ async function main() {
reflectPlaygroundState(state);
editor = new EditorView({
- extensions: [lintGutter(), basicSetup, css(), oneDark, linterCompartment.of(createCssLinter())],
+ extensions: [
+ lintGutter(),
+ basicSetup,
+ css(),
+ oneDark,
+ linterCompartment.of(createCssLinter()),
+ ],
parent: source,
doc: state.source,
dispatch(tr) {
@@ -380,11 +434,17 @@ async function main() {
if (tr.docChanged) {
update();
}
- }
+ },
});
visitorEditor = new EditorView({
- extensions: [lintGutter(), basicSetup, javascript(), oneDark, visitorLinterCompartment.of(createVisitorLinter())],
+ extensions: [
+ lintGutter(),
+ basicSetup,
+ javascript(),
+ oneDark,
+ visitorLinterCompartment.of(createVisitorLinter()),
+ ],
parent: visitor,
doc: state.visitor,
dispatch(tr) {
@@ -392,21 +452,39 @@ async function main() {
if (tr.docChanged) {
update();
}
- }
+ },
});
outputEditor = new EditorView({
- extensions: [basicSetup, css(), oneDark, EditorView.editable.of(false), EditorView.lineWrapping],
+ extensions: [
+ basicSetup,
+ css(),
+ oneDark,
+ EditorView.editable.of(false),
+ EditorView.lineWrapping,
+ ],
parent: compiled,
});
modulesEditor = new EditorView({
- extensions: [basicSetup, javascript(), oneDark, EditorView.editable.of(false), EditorView.lineWrapping],
+ extensions: [
+ basicSetup,
+ javascript(),
+ oneDark,
+ EditorView.editable.of(false),
+ EditorView.lineWrapping,
+ ],
parent: compiledModules,
});
depsEditor = new EditorView({
- extensions: [basicSetup, javascript(), oneDark, EditorView.editable.of(false), EditorView.lineWrapping],
+ extensions: [
+ basicSetup,
+ javascript(),
+ oneDark,
+ EditorView.editable.of(false),
+ EditorView.lineWrapping,
+ ],
parent: compiledDependencies,
});
diff --git a/website/synthwave.css b/website/synthwave.css
index 9395b6ac..2366e690 100644
--- a/website/synthwave.css
+++ b/website/synthwave.css
@@ -3,10 +3,10 @@
* Originally ported for PrismJS by Marc Backes [@themarcba]
*/
-pre[class*="language-"] {
+pre[class*='language-'] {
color: lab(64% 103 0);
- text-shadow: 0 0 10px lab(64% 103 0 / .5);
- background: rgb(255 255 255 / .05);
+ text-shadow: 0 0 10px lab(64% 103 0 / 0.5);
+ background: rgb(255 255 255 / 0.05);
display: block;
padding: 20px;
border-radius: 8px;
@@ -30,16 +30,16 @@ pre[class*="language-"] {
}
/* Code blocks */
-pre[class*="language-"] {
+pre[class*='language-'] {
padding: 1em;
- margin: .5em 0;
+ margin: 0.5em 0;
overflow: auto;
}
/* Inline code */
-:not(pre) > code[class*="language-"] {
- padding: .1em;
- border-radius: .3em;
+:not(pre) > code[class*='language-'] {
+ padding: 0.1em;
+ border-radius: 0.3em;
white-space: normal;
}
@@ -65,13 +65,13 @@ pre[class*="language-"] {
.token.deleted,
.token.function {
color: lch(65% 85 35);
- text-shadow: 0 0 10px lch(65% 85 35 / .5);
+ text-shadow: 0 0 10px lch(65% 85 35 / 0.5);
}
.token.property,
.token.selector {
color: lch(85% 58 205);
- text-shadow: 0 0 10px lch(85% 58 205 / .5);
+ text-shadow: 0 0 10px lch(85% 58 205 / 0.5);
}
.token.function-name {
@@ -81,12 +81,14 @@ pre[class*="language-"] {
.token.boolean,
.token.selector .token.id {
color: #fdfdfd;
- text-shadow: 0 0 2px #001716, 0 0 3px #03edf975, 0 0 5px #03edf975, 0 0 8px #03edf975;
+ text-shadow: 0 0 2px #001716, 0 0 3px #03edf975, 0 0 5px #03edf975,
+ 0 0 8px #03edf975;
}
.token.class-name {
color: #fff5f6;
- text-shadow: 0 0 2px #000, 0 0 10px #fc1f2c75, 0 0 5px #fc1f2c75, 0 0 25px #fc1f2c75;
+ text-shadow: 0 0 2px #000, 0 0 10px #fc1f2c75, 0 0 5px #fc1f2c75,
+ 0 0 25px #fc1f2c75;
}
.token.constant,
@@ -112,7 +114,7 @@ pre[class*="language-"] {
.token.variable,
.token.url {
color: lch(85% 82.34 80.104);
- text-shadow: 0 0 10px lch(85% 82.34 80.104 / .5);
+ text-shadow: 0 0 10px lch(85% 82.34 80.104 / 0.5);
}
.token.operator,
diff --git a/website/transforms.html b/website/transforms.html
index 42083909..fa136cfc 100644
--- a/website/transforms.html
+++ b/website/transforms.html
@@ -1 +1,4 @@
-
+
diff --git a/website/transpilation.html b/website/transpilation.html
index 64ec9c63..b3fe2fa4 100644
--- a/website/transpilation.html
+++ b/website/transpilation.html
@@ -1 +1,4 @@
-
+