Skip to content

Commit 67f89ea

Browse files
authored
Implement CSS Nesting (parcel-bundler#16)
1 parent 0287aed commit 67f89ea

File tree

20 files changed

+1460
-155
lines changed

20 files changed

+1460
-155
lines changed

build-prefixes.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ let cssFeatures = [
155155
'css-autofill',
156156
'css-namespaces',
157157
'shadowdomv1',
158-
'css-rrggbbaa'
158+
'css-rrggbbaa',
159+
'css-nesting'
159160
];
160161

161162
let compat = new Map();

node/index.d.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@ export interface TransformOptions {
1010
/** Whether to output a source map. */
1111
source_map?: boolean,
1212
/** The browser targets for the generated code. */
13-
targets?: Targets
13+
targets?: Targets,
14+
/** Whether to enable various draft syntax. */
15+
drafts?: Drafts
16+
}
17+
18+
export interface Drafts {
19+
/** Whether to enable CSS nesting. */
20+
nesting?: boolean
1421
}
1522

1623
export interface TransformResult {

node/src/lib.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc;
44

55
use serde::{Serialize, Deserialize};
6-
use parcel_css::stylesheet::{StyleSheet, StyleAttribute};
6+
use parcel_css::stylesheet::{StyleSheet, StyleAttribute, ParserOptions};
77
use parcel_css::targets::Browsers;
88

99
// ---------------------------------------------
@@ -103,11 +103,23 @@ struct Config {
103103
pub code: Vec<u8>,
104104
pub targets: Option<Browsers>,
105105
pub minify: Option<bool>,
106-
pub source_map: Option<bool>
106+
pub source_map: Option<bool>,
107+
pub drafts: Option<Drafts>
108+
}
109+
110+
#[derive(Serialize, Debug, Deserialize, Default)]
111+
struct Drafts {
112+
nesting: bool
107113
}
108114

109115
fn compile<'i>(code: &'i str, config: &Config) -> Result<TransformResult, CompileError<'i>> {
110-
let mut stylesheet = StyleSheet::parse(config.filename.clone(), &code)?;
116+
let options = config.drafts.as_ref();
117+
let mut stylesheet = StyleSheet::parse(config.filename.clone(), &code, ParserOptions {
118+
nesting: match options {
119+
Some(o) => o.nesting,
120+
None => false
121+
}
122+
})?;
111123
stylesheet.minify(config.targets); // TODO: should this be conditional?
112124
let (res, source_map) = stylesheet.to_css(
113125
config.minify.unwrap_or(false),

playground/index.html

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
html, body {
77
margin: 0;
88
height: 100%;
9-
box-sizing: border-box
9+
box-sizing: border-box;
10+
font-family: -apple-system, system-ui;
11+
color-scheme: dark light;
1012
}
1113

1214
body {
@@ -39,13 +41,25 @@
3941
flex: 1;
4042
font: 14px monospace;
4143
}
44+
45+
h3 {
46+
margin-bottom: 4px;
47+
}
48+
49+
h3:first-child {
50+
margin-top: 0;
51+
}
4252
</style>
4353
</head>
4454
<body>
4555
<h1>Parcel CSS Playground</h1>
4656
<main>
4757
<div>
58+
<h3>Options</h3>
4859
<label><input id="minify" type="checkbox" checked> Minify</label>
60+
<h3>Draft syntax</h3>
61+
<label><input id="nesting" type="checkbox" checked> Nesting</label>
62+
<h3>Targets</h3>
4963
<div class="targets">
5064
<label><span>Chrome: </span><input id="chrome" type="number" value="95"></label>
5165
<label><span>Firefox: </span><input id="firefox" type="number"></label>
@@ -56,7 +70,6 @@ <h1>Parcel CSS Playground</h1>
5670
<label><span>iOS: </span><input id="ios_saf" type="number"></label>
5771
<label><span>Android: </span><input id="android" type="number"></label>
5872
<label><span>Samsung: </span><input id="samsung" type="number"></label>
59-
6073
</div>
6174
</div>
6275
<textarea id="source">
@@ -70,6 +83,10 @@ <h1>Parcel CSS Playground</h1>
7083
-webkit-transition: background 200ms;
7184
-moz-transition: background 200ms;
7285
transition: background 200ms;
86+
87+
&.bar {
88+
color: green;
89+
}
7390
}</textarea>
7491
<textarea id="compiled"></textarea>
7592
</main>

playground/playground.js

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,10 @@ function loadPlaygroundState() {
1111
reflectPlaygroundState(playgroundState);
1212
} catch {
1313
const initialPlaygroundState = {
14-
minify: true,
15-
targets: {
16-
chrome: 95 << 16,
17-
},
18-
source: `.foo {
19-
background: yellow;
20-
21-
-webkit-border-radius: 2px;
22-
-moz-border-radius: 2px;
23-
border-radius: 2px;
24-
25-
-webkit-transition: background 200ms;
26-
-moz-transition: background 200ms;
27-
transition: background 200ms;
28-
}`,
14+
minify: minify.checked,
15+
nesting: nesting.checked,
16+
targets: getTargets(),
17+
source: source.value,
2918
};
3019

3120
reflectPlaygroundState(initialPlaygroundState);
@@ -37,17 +26,15 @@ function reflectPlaygroundState(playgroundState) {
3726
minify.checked = playgroundState.minify;
3827
}
3928

29+
if (typeof playgroundState.nesting !== 'undefined') {
30+
nesting.checked = playgroundState.nesting;
31+
}
32+
4033
if (playgroundState.targets) {
4134
const {targets} = playgroundState;
42-
for (const target in targets) {
43-
const value = targets[target];
44-
if (value) {
45-
for (const input of Array.from(inputs)) {
46-
if (input.id === target) {
47-
input.value = value >> 16;
48-
}
49-
}
50-
}
35+
for (let input of inputs) {
36+
let value = targets[input.id];
37+
input.value = value == null ? '' : value >> 16;
5138
}
5239
}
5340

@@ -59,6 +46,7 @@ function reflectPlaygroundState(playgroundState) {
5946
function savePlaygroundState() {
6047
const playgroundState = {
6148
minify: minify.checked,
49+
nesting: nesting.checked,
6250
targets: getTargets(),
6351
source: source.value,
6452
};
@@ -98,6 +86,9 @@ async function update() {
9886
code: enc.encode(source.value),
9987
minify: minify.checked,
10088
targets: Object.keys(targets).length === 0 ? null : targets,
89+
drafts: {
90+
nesting: nesting.checked
91+
}
10192
});
10293

10394
compiled.value = dec.decode(res.code);

selectors/builder.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,9 @@ where
346346
Component::Namespace(..) => {
347347
// Does not affect specificity
348348
},
349+
Component::Nesting => {
350+
// TODO
351+
}
349352
}
350353
}
351354

selectors/matching.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,7 @@ where
858858
}
859859
true
860860
}),
861+
Component::Nesting => unreachable!()
861862
}
862863
}
863864

0 commit comments

Comments
 (0)