Skip to content
This repository was archived by the owner on Jun 6, 2022. It is now read-only.

Commit 590e414

Browse files
committed
Merge pull request #10 from hgl/recursive
Allow custom media to reference each other
2 parents 2c8f253 + 47c800c commit 590e414

8 files changed

+112
-4
lines changed

index.js

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,33 @@ var postcss = require("postcss")
22

33
var EXTENSION_RE = /\(\s*(--[\w-]+)\s*\)/g
44

5+
/*
6+
* Resolve custom media values.
7+
*/
8+
function resolveValue(value, map, result) {
9+
if (!EXTENSION_RE.test(value)) {
10+
return value
11+
}
12+
return value.replace(EXTENSION_RE, function(orig, name) {
13+
if (!map[name]) {
14+
return orig
15+
}
16+
17+
var mq = map[name]
18+
if (mq.resolved) {
19+
return mq.value
20+
}
21+
22+
if (mq.deps.indexOf(name) !== -1) {
23+
mq.circular = true
24+
return orig
25+
}
26+
mq.deps.push(name)
27+
mq.value = resolveValue(mq.value, map, result)
28+
return mq.value
29+
})
30+
}
31+
532
/*
633
* read & replace custom media queries by standard media queries
734
*/
@@ -32,7 +59,12 @@ function customMedia(options) {
3259
var params = rule.params.split(" ")
3360
// @custom-media <extension-name> <media-query-list>;
3461
// map[<extension-name>] = <media-query-list>
35-
map[params.shift()] = params.join(" ")
62+
map[params.shift()] = {
63+
value: params.join(" "),
64+
deps: [],
65+
circular: false,
66+
resolved: false,
67+
}
3668

3769
if (!preserve) {
3870
toRemove.push(rule)
@@ -41,7 +73,17 @@ function customMedia(options) {
4173

4274
// apply js-defined media queries
4375
Object.keys(extensions).forEach(function(name) {
44-
map[name] = extensions[name]
76+
map[name] = {
77+
value: extensions[name],
78+
deps: [],
79+
circular: false,
80+
resolved: false,
81+
}
82+
})
83+
84+
Object.keys(map).forEach(function(name) {
85+
map[name].value = resolveValue(map[name].value, map, result)
86+
map[name].resolved = true
4587
})
4688

4789
// transform custom media query aliases
@@ -52,7 +94,15 @@ function customMedia(options) {
5294

5395
rule.params = rule.params.replace(EXTENSION_RE, function(_, name) {
5496
if (map[name]) {
55-
return map[name]
97+
if (map[name].circular) {
98+
result.warn(
99+
"Circular @custom-media definition for '" + name +
100+
"'. The entire rule has been removed from the output.",
101+
{node: rule}
102+
)
103+
toRemove.push(rule)
104+
}
105+
return map[name].value
56106
}
57107

58108
result.warn(
@@ -68,10 +118,13 @@ function customMedia(options) {
68118
var names = Object.keys(map)
69119
if (names.length) {
70120
names.forEach(function(name) {
121+
if (map[name].circular) {
122+
return
123+
}
71124
var atRule = postcss.atRule({
72125
name: "custom-media",
73126
afterName: " ",
74-
params: name + " " + map[name],
127+
params: name + " " + map[name].value,
75128
})
76129
styles.append(atRule)
77130
})
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
body { color: #000 }
2+
3+
@custom-media --a (--b);
4+
@custom-media --b (--a);
5+
6+
@media (--b) {
7+
selector {
8+
property: value;
9+
}
10+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
body { color: #000 }
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@custom-media --a (foo: bar);
2+
@custom-media --b (--a);
3+
4+
@media (--b) {
5+
selector {
6+
property: value;
7+
}
8+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
3+
@media (foo: bar) {
4+
selector {
5+
property: value;
6+
}
7+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
body { color: #000 }
2+
3+
@custom-media --a (--a);
4+
5+
@media (--a) {
6+
selector {
7+
property: value;
8+
}
9+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
body { color: #000 }

test/index.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,24 @@ test("@custom-media", function(t) {
4040
"should replaces all extension names"
4141
)
4242

43+
compareFixtures(
44+
t,
45+
"transform-reference",
46+
"should transform custom media referencing another custom media"
47+
)
48+
49+
compareFixtures(
50+
t,
51+
"transform-self-reference",
52+
"should transform custom media with self reference"
53+
)
54+
55+
compareFixtures(
56+
t,
57+
"transform-circular-reference",
58+
"should transform custom media with circular reference"
59+
)
60+
4361
var undefinedRes = compareFixtures(
4462
t,
4563
"undefined",
@@ -89,6 +107,7 @@ test("@custom-media", function(t) {
89107
{
90108
extensions: {
91109
"--viewport-max-s": "(max-width: 30em)",
110+
"--a": "(--a)",
92111
},
93112
appendExtensions: true,
94113
}

0 commit comments

Comments
 (0)