Skip to content

Commit ee32ac5

Browse files
committed
Throw error when non-local isn't marked as :global
1 parent fdfae1a commit ee32ac5

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

index.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,25 @@ var postcss = require('postcss');
33
var ESCAPED_DOT = ' ___LOCAL_SCOPE__ESCAPED_DOT___ ';
44

55
module.exports = postcss.plugin('postcss-local-scope', function () {
6-
return function(css) {
6+
return function(css, result) {
77
css.eachRule(function(rule) {
88
rule.selector = rule.selector
99
.split(',')
10-
.map(transformSelector)
10+
.map(transformSelector.bind(null, rule))
1111
.join(',');
1212
});
1313
};
1414
});
1515

16-
function transformSelector(selector) {
16+
function transformSelector(rule, selector) {
17+
// Syntax warnings
18+
var trimmedSelector = selector.trim();
19+
if (!/^\./.test(trimmedSelector)) {
20+
if (!/^\:global/.test(trimmedSelector)) {
21+
throw rule.error('Global selector detected in local context. Does this selector really need to be global? If so, you need to explicitly export it into the global scope with ":global", e.g. ":global '+trimmedSelector+'"', { plugin: 'postcss-local-scope' });
22+
}
23+
}
24+
1725
return selector
1826
.replace(/\:global\((.*?)\)/g, escapeDots)
1927
.replace(/\:global (.*)/g, escapeDots)

test.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,59 @@ test(name, function (t) {
104104
});
105105
});
106106

107+
108+
var errorTests = [
109+
{
110+
should: 'reject naked element selectors',
111+
input: 'input {}',
112+
reason: 'Global selector detected in local context. Does this selector really need to be global? If so, you need to explicitly export it into the global scope with ":global", e.g. ":global input"'
113+
},
114+
{
115+
should: 'reject naked element selectors in a collection',
116+
input: '.foo, input {}',
117+
reason: 'Global selector detected in local context. Does this selector really need to be global? If so, you need to explicitly export it into the global scope with ":global", e.g. ":global input"'
118+
},
119+
{
120+
should: 'reject naked psuedo classes',
121+
input: ':focus {}',
122+
reason: 'Global selector detected in local context. Does this selector really need to be global? If so, you need to explicitly export it into the global scope with ":global", e.g. ":global :focus"'
123+
},
124+
{
125+
should: 'reject naked psuedo classes in a collection',
126+
input: '.foo, :focus {}',
127+
reason: 'Global selector detected in local context. Does this selector really need to be global? If so, you need to explicitly export it into the global scope with ":global", e.g. ":global :focus"'
128+
},
129+
{
130+
should: 'reject naked attribute selectors',
131+
input: '[data-foobar] {}',
132+
reason: 'Global selector detected in local context. Does this selector really need to be global? If so, you need to explicitly export it into the global scope with ":global", e.g. ":global [data-foobar]"'
133+
},
134+
{
135+
should: 'reject naked attribute selectors in a collection',
136+
input: '.foo, [data-foobar] {}',
137+
reason: 'Global selector detected in local context. Does this selector really need to be global? If so, you need to explicitly export it into the global scope with ":global", e.g. ":global [data-foobar]"'
138+
}
139+
];
140+
141+
function processError (css, options) {
142+
try {
143+
postcss(plugin(options)).process(css).css;
144+
} catch (error) {
145+
return error;
146+
}
147+
}
148+
149+
test(name, function (t) {
150+
t.plan(errorTests.length);
151+
152+
errorTests.forEach(function (test) {
153+
var options = test.options || {};
154+
var error = processError(test.input, options);
155+
t.equal(error.reason, test.reason, 'should ' + test.should);
156+
});
157+
});
158+
159+
107160
test('should use the postcss plugin api', function (t) {
108161
t.plan(2);
109162
t.ok(plugin().postcssVersion, 'should be able to access version');

0 commit comments

Comments
 (0)