Skip to content

Commit 7cdffdd

Browse files
committed
merged master
2 parents f03ab7e + cc92a12 commit 7cdffdd

File tree

4 files changed

+89
-17
lines changed

4 files changed

+89
-17
lines changed

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ This project adheres to [Semantic Versioning](http://semver.org/).
66
### Changed
77
- Nothing yet.
88

9+
## [0.0.8] - 2015-06-11
10+
### Added
11+
- Pure mode where only local scope is allowed.
12+
13+
### Changed
14+
- Using global selectors outside of a global context now triggers warnings.
15+
916
## [0.0.7] - 2015-05-30
1017
### Changed
1118
- Migrated to `css-selector-tokenizer`.
@@ -38,10 +45,11 @@ This project adheres to [Semantic Versioning](http://semver.org/).
3845
- Automatic local classes
3946
- Explicit global selectors with `:global`
4047

41-
[unreleased]: https://github.com/postcss-modules-local-by-default/compare/v0.0.7...HEAD
48+
[unreleased]: https://github.com/postcss-modules-local-by-default/compare/v0.0.8...HEAD
4249
[0.0.2]: https://github.com/postcss-modules-local-by-default/compare/v0.0.1...v0.0.2
4350
[0.0.3]: https://github.com/postcss-modules-local-by-default/compare/v0.0.2...v0.0.3
4451
[0.0.4]: https://github.com/postcss-modules-local-by-default/compare/v0.0.3...v0.0.4
4552
[0.0.5]: https://github.com/postcss-modules-local-by-default/compare/v0.0.4...v0.0.5
4653
[0.0.6]: https://github.com/postcss-modules-local-by-default/compare/v0.0.5...v0.0.6
4754
[0.0.7]: https://github.com/postcss-modules-local-by-default/compare/v0.0.6...v0.0.7
55+
[0.0.8]: https://github.com/postcss-modules-local-by-default/compare/v0.0.7...v0.0.8

index.js

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,49 @@ function localizeNode(node, context) {
153153
return node;
154154
}
155155

156-
function localizeDecl(decl) {
157-
if(typeof decl.prop === "string" && /animation(-name)?/.test(decl.prop)) {
158-
decl.value = decl.value.replace(/(^|,)(\s*)(\w+)/g, "$1$2:local($3)"); // TODO
156+
function localizeDeclNode(node, context) {
157+
var newNode;
158+
switch(node.type) {
159+
case "item":
160+
if(context.localizeNextItem) {
161+
newNode = Object.create(node);
162+
newNode.name = ":local(" + newNode.name + ")";
163+
context.localizeNextItem = false;
164+
return newNode;
165+
}
166+
break;
167+
case "url":
168+
if(context.options.rewriteUrl) {
169+
newNode = Object.create(node);
170+
newNode.url = context.options.rewriteUrl(context.global, node.url);
171+
return newNode;
172+
}
173+
break;
159174
}
175+
return node;
176+
}
177+
178+
function localizeDeclValue(valueNode, context) {
179+
var newValueNode = Object.create(valueNode);
180+
newValueNode.nodes = valueNode.nodes.map(function(node) {
181+
return localizeDeclNode(node, context);
182+
});
183+
return newValueNode;
184+
}
185+
186+
function localizeDecl(decl, context) {
187+
var valuesNode = Tokenizer.parseValues(decl.value);
188+
var localizeName = /animation(-name)?/.test(decl.prop);
189+
var newValuesNode = Object.create(valuesNode);
190+
newValuesNode.nodes = valuesNode.nodes.map(function(valueNode) {
191+
var subContext = {
192+
options: context.options,
193+
global: context.global,
194+
localizeNextItem: localizeName && !context.global
195+
};
196+
return localizeDeclValue(valueNode, subContext);
197+
});
198+
decl.value = Tokenizer.stringifyValues(newValuesNode);
160199
}
161200

162201
module.exports = postcss.plugin('postcss-modules-local-by-default', function (options) {
@@ -174,7 +213,7 @@ module.exports = postcss.plugin('postcss-modules-local-by-default', function (op
174213
var localMatch = /^\s*:local\s*\((.+)\)\s*$/.exec(atrule.params);
175214
if(globalMatch) {
176215
if(pureMode) {
177-
throw new Error("@keyframes :global(...) is not allowed in pure mode");
216+
throw atrule.error("@keyframes :global(...) is not allowed in pure mode");
178217
}
179218
atrule.params = globalMatch[1];
180219
} else if(localMatch) {
@@ -187,22 +226,28 @@ module.exports = postcss.plugin('postcss-modules-local-by-default', function (op
187226
css.eachRule(function(rule) {
188227
var selector = Tokenizer.parse(rule.selector);
189228
var context = {
229+
options: options,
190230
global: globalMode,
191231
hasPureGlobals: false,
192232
hasPureImplicitGlobals: false
193233
};
194-
var newSelector = localizeNode(selector, context);
234+
var newSelector;
235+
try {
236+
newSelector = localizeNode(selector, context);
237+
} catch(e) {
238+
throw rule.error(e.message);
239+
}
195240
if(pureMode && context.hasPureGlobals) {
196-
throw new Error("Selector '" + Tokenizer.stringify(selector) + "' is not pure " +
241+
throw rule.error("Selector '" + Tokenizer.stringify(selector) + "' is not pure " +
197242
"(pure selectors must contain at least one local class or id)");
198243
}
199244
if(!globalMode && context.hasPureImplicitGlobals) {
200-
throw new Error("Selector '" + Tokenizer.stringify(selector) + "' must be explicit flagged :global " +
245+
throw rule.error("Selector '" + Tokenizer.stringify(selector) + "' must be explicit flagged :global " +
201246
"(elsewise it would leak globally)");
202247
}
203-
if(!context.global) {
204-
rule.nodes.forEach(localizeDecl);
205-
}
248+
rule.nodes.forEach(function(decl) {
249+
localizeDecl(decl, context);
250+
});
206251
rule.selector = Tokenizer.stringify(newSelector);
207252
});
208253
};

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "postcss-modules-local-by-default",
3-
"version": "0.0.7",
3+
"version": "0.0.8",
44
"description": "A CSS Modules transform to make local scope the default",
55
"keywords": [
66
"css-modules",
@@ -15,7 +15,7 @@
1515
"url": "https://github.com/css-modules/postcss-modules-local-by-default.git"
1616
},
1717
"dependencies": {
18-
"css-selector-tokenizer": "^0.3.1",
18+
"css-selector-tokenizer": "^0.4.0",
1919
"postcss": "^4.1.5"
2020
},
2121
"devDependencies": {

test.js

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,11 +345,30 @@ var tests = [
345345
expected: '[type="radio"] {}'
346346
},
347347
{
348-
should: 'localise class and pass through attribute',
349-
input: '.foo :not([type="radio"]) {}',
350-
expected: ':local(.foo) :not([type="radio"]) {}'
348+
should: 'not modify urls without option',
349+
input: '.a { background: url(./image.png); }\n' +
350+
':global .b { background: url(image.png); }\n' +
351+
'.c { background: url("./image.png"); }',
352+
expected: ':local(.a) { background: url(./image.png); }\n' +
353+
'.b { background: url(image.png); }\n' +
354+
':local(.c) { background: url("./image.png"); }'
355+
},
356+
{
357+
should: 'rewrite url in local block',
358+
input: '.a { background: url(./image.png); }\n' +
359+
':global .b { background: url(image.png); }\n' +
360+
'.c { background: url("./image.png"); }',
361+
options: {
362+
rewriteUrl: function(global, url) {
363+
var mode = global ? 'global' : 'local';
364+
return '(' + mode + ')' + url + '"' + mode + '"';
365+
}
366+
},
367+
expected: ':local(.a) { background: url((local\\)./image.png\\\"local\\\"); }\n' +
368+
'.b { background: url((global\\)image.png\\\"global\\\"); }\n' +
369+
':local(.c) { background: url(\"(local)./image.png\\\"local\\\"\"); }'
351370
}
352-
371+
353372
];
354373

355374
function process (css, options) {

0 commit comments

Comments
 (0)