Skip to content

Commit aaee8f7

Browse files
committed
camelCase (#90)
additional options for `camelCase`.
1 parent b8df916 commit aaee8f7

12 files changed

+214
-69
lines changed

Diff for: .editorconfig

+9
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,13 @@ charset = utf-8
88
trim_trailing_whitespace = true
99
insert_final_newline = true
1010

11+
[GNUmakefile]
12+
indent_style = tab
13+
14+
[Makefile]
15+
indent_style = tab
16+
17+
[makefile]
18+
indent_style = tab
19+
1120
# cheat sheet: http://EditorConfig.org

Diff for: .gitignore

+5-30
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,5 @@
1-
# Logs
2-
logs
3-
*.log
4-
5-
# Runtime data
6-
pids
7-
*.pid
8-
*.seed
9-
10-
# Directory for instrumented libs generated by jscoverage/JSCover
11-
lib-cov
12-
13-
# Coverage directory used by tools like istanbul
14-
coverage
15-
16-
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17-
.grunt
18-
19-
# node-waf configuration
20-
.lock-wscript
21-
22-
# Compiled binary addons (http://nodejs.org/api/addons.html)
23-
build/Release
24-
25-
# Dependency directory
26-
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
27-
node_modules/*
28-
29-
# added automatically by precommit-hook as defaults
30-
.jshint*
1+
.DS_Store
2+
.npm
3+
node_modules
4+
npm-debug.log*
5+
yarn.lock

Diff for: .travis.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
language: node_js
22
node_js:
3-
- "4.3"
3+
- "4"
4+
- "6"

Diff for: README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,12 @@ hook({
206206
});
207207
```
208208

209-
### `camelCase boolean`
209+
### `camelCase boolean|string`
210210

211211
Camelizes exported class names. Similar to [css-loader?camelCase](https://github.com/webpack/css-loader#camel-case).
212212

213+
Available options: `true`, `dashes`, `only`, `dashesOnly`.
214+
213215
### `append` array
214216

215217
Appends custom plugins to the end of the PostCSS pipeline. Since the `require` function is synchronous, you should provide synchronous plugins only.

Diff for: lib/attachHook.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use strict';
2+
13
/**
24
* @param {function} compile
35
* @param {string} extension

Diff for: lib/index.js

+14-16
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
const assign = require('lodash').assign;
1+
'use strict';
2+
3+
const {assign, identity, negate, camelCase: camelCaseFunc, mapKeys} = require('lodash');
4+
const {dirname, relative, resolve} = require('path');
5+
const {readFileSync} = require('fs');
6+
const {transformTokens} = require('./transformTokens');
7+
28
const attachHook = require('./attachHook');
3-
const dirname = require('path').dirname;
49
const genericNames = require('generic-names');
510
const globToRegex = require('glob-to-regexp');
6-
const identity = require('lodash').identity;
7-
const negate = require('lodash').negate;
8-
const camelCaseFunc = require('lodash').camelCase;
9-
const mapKeys = require('lodash').mapKeys;
10-
const readFileSync = require('fs').readFileSync;
11-
const relative = require('path').relative;
12-
const resolve = require('path').resolve;
1311
const validate = require('./validate');
1412

1513
const postcss = require('postcss');
@@ -23,13 +21,13 @@ const debugFetch = require('debug')('css-modules:fetch');
2321
const debugSetup = require('debug')('css-modules:setup');
2422

2523
module.exports = function setupHook({
24+
camelCase,
2625
devMode,
2726
extensions = '.css',
2827
ignore,
2928
preprocessCss = identity,
3029
processCss,
3130
processorOpts,
32-
camelCase,
3331
append = [],
3432
prepend = [],
3533
createImportedName,
@@ -89,7 +87,6 @@ module.exports = function setupHook({
8987
? require.resolve(_to)
9088
: resolve(dirname(from), _to);
9189

92-
9390
// checking cache
9491
let tokens = tokensByFile[filename];
9592
if (tokens) {
@@ -107,10 +104,6 @@ module.exports = function setupHook({
107104

108105
tokens = lazyResult.root.tokens;
109106

110-
if (camelCase) {
111-
tokens = assign(mapKeys(tokens, (value, key) => camelCaseFunc(key)), tokens);
112-
}
113-
114107
if (!debugMode) {
115108
// updating cache
116109
tokensByFile[filename] = tokens;
@@ -132,8 +125,13 @@ module.exports = function setupHook({
132125
const exts = toArray(extensions);
133126
const isException = buildExceptionChecker(ignore);
134127

128+
const hook = filename => {
129+
const tokens = fetch(filename, filename);
130+
return camelCase ? transformTokens(tokens, camelCase) : tokens;
131+
};
132+
135133
// @todo add possibility to specify particular config for each extension
136-
exts.forEach(extension => attachHook(filename => fetch(filename, filename), extension, isException));
134+
exts.forEach(extension => attachHook(hook, extension, isException));
137135
};
138136

139137
/**

Diff for: lib/transformTokens.js

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
'use strict';
2+
3+
const {assign, camelCase, reduce} = require('lodash');
4+
5+
const camelizeKeys = (acc, value, key) => {
6+
const camelizedKey = camelCase(key);
7+
if (camelizedKey !== key) acc[camelizedKey] = value;
8+
return acc;
9+
};
10+
11+
const camelizeDashedKeys = (acc, value, key) => {
12+
const camelizedKey = camelizeDashes(key);
13+
if (camelizedKey !== key) acc[camelizedKey] = value;
14+
return acc;
15+
};
16+
17+
const camelizeOnlyKeys = (acc, value, key) => {
18+
const camelizedKey = camelCase(key);
19+
if (camelizedKey !== key) acc[camelizedKey] = value
20+
else acc[key] = value;
21+
return acc;
22+
};
23+
24+
const camelizeOnlyDashedKeys = (acc, value, key) => {
25+
const camelizedKey = camelizeDashes(key);
26+
if (camelizedKey !== key) acc[camelizedKey] = value
27+
else acc[key] = value;
28+
return acc;
29+
};
30+
31+
exports.camelizeDashes = camelizeDashes;
32+
exports.transformTokens = transformTokens;
33+
34+
/**
35+
* @param {string} str
36+
* @return {string}
37+
*/
38+
function camelizeDashes(str) {
39+
return str.replace(/-(\w)/g, (m, letter) => letter.toUpperCase());
40+
}
41+
42+
/**
43+
* @param {object} tokens
44+
* @param {boolean|string} camelCase 'dashes|dashesOnly|only'
45+
* @return {object}
46+
*/
47+
function transformTokens(tokens, camelCase) {
48+
switch (camelCase) {
49+
case true:
50+
return reduce(tokens, camelizeKeys, assign({}, tokens));
51+
52+
case 'dashes':
53+
return reduce(tokens, camelizeDashedKeys, assign({}, tokens));
54+
55+
case 'dashesOnly':
56+
return reduce(tokens, camelizeOnlyDashedKeys, {});
57+
58+
case 'only':
59+
return reduce(tokens, camelizeOnlyKeys, {});
60+
}
61+
62+
return tokens;
63+
}

Diff for: lib/validate.js

+20-10
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
1-
const difference = require('lodash').difference;
2-
const forEach = require('lodash').forEach;
3-
const keys = require('lodash').keys;
1+
'use strict';
2+
3+
const {
4+
difference,
5+
forEach,
6+
isArray,
7+
isBoolean,
8+
isFunction,
9+
isPlainObject,
10+
isRegExp,
11+
isString,
12+
keys,
13+
} = require('lodash');
414

515
const rules = {
616
// hook
17+
camelCase: 'boolean|string',
718
devMode: 'boolean',
819
extensions: 'array|string',
920
ignore: 'function|regex|string',
1021
preprocessCss: 'function',
1122
processCss: 'function',
1223
processorOpts: 'object',
13-
camelCase: 'boolean',
1424
// plugins
1525
append: 'array',
1626
prepend: 'array',
@@ -23,12 +33,12 @@ const rules = {
2333
};
2434

2535
const tests = {
26-
array: require('lodash').isArray,
27-
boolean: require('lodash').isBoolean,
28-
function: require('lodash').isFunction,
29-
object: require('lodash').isPlainObject,
30-
regex: require('lodash').isRegExp,
31-
string: require('lodash').isString,
36+
array: isArray,
37+
boolean: isBoolean,
38+
function: isFunction,
39+
object: isPlainObject,
40+
regex: isRegExp,
41+
string: isString,
3242
};
3343

3444
module.exports = function validate(options) {

Diff for: package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
"test": "npm run test:babel",
1515
"test:babel": "NODE_PATH=$(pwd)/test/tokens/node_modules $npm_package_scripts_test_unit --compilers js:babel-register",
1616
"test:coverage": "NODE_PATH=$(pwd)/test/tokens/node_modules babel-node --presets es2015 `npm bin`/isparta cover --report text --report html `npm bin`/_mocha -- --require test/setup.js --ui tdd test/*/*.js",
17-
"test:node": "NODE_PATH=$(pwd)/test/tokens/node_modules $npm_package_scripts_test_unit --use_strict",
18-
"test:watch": "NODE_PATH=$(pwd)/test/tokens/node_modules $npm_package_scripts_test_unit --watch --use_strict",
17+
"test:node": "NODE_PATH=$(pwd)/test/tokens/node_modules $npm_package_scripts_test_unit",
18+
"test:watch": "NODE_PATH=$(pwd)/test/tokens/node_modules $npm_package_scripts_test_unit --watch",
1919
"test:unit": "mocha --require test/setup.js --ui tdd test/*/*.js"
2020
},
2121
"repository": {

Diff for: preset.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use strict';
2+
13
const basename = require('path').basename;
24
const debug = require('debug')('css-modules:preset');
35
const dirname = require('path').dirname;

Diff for: test/api/camelCase.js

+27-9
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,36 @@ const detachHook = require('../sugar').detachHook;
22
const dropCache = require('../sugar').dropCache;
33

44
suite('api/camelCase', () => {
5-
test('should add camel case keys in token', () => {
6-
const tokens = require('./fixture/bem.css');
7-
assert.deepEqual(tokens, {
8-
blockElementModifier: '_test_api_fixture_bem__block__element--modifier',
9-
'block__element--modifier': '_test_api_fixture_bem__block__element--modifier',
5+
suite('-> `true`', () => {
6+
test('should add camel case keys in token', () => {
7+
const tokens = require('./fixture/bem.css');
8+
assert.deepEqual(tokens, {
9+
blockElementModifier: '_test_api_fixture_bem__block__element--modifier',
10+
'block__element--modifier': '_test_api_fixture_bem__block__element--modifier',
11+
});
12+
});
13+
14+
setup(() => hook({ camelCase: true }));
15+
16+
teardown(() => {
17+
detachHook('.css');
18+
dropCache('./api/fixture/bem.css');
1019
});
1120
});
1221

13-
setup(() => hook({ camelCase: true }));
22+
suite('-> `dashesOnly`', () => {
23+
test('should replace keys with dashes by its camel-cased equivalent', () => {
24+
const tokens = require('./fixture/bem.css');
25+
assert.deepEqual(tokens, {
26+
'block__element-Modifier': '_test_api_fixture_bem__block__element--modifier',
27+
});
28+
});
29+
30+
setup(() => hook({camelCase: 'dashesOnly'}));
1431

15-
teardown(() => {
16-
detachHook('.css');
17-
dropCache('./api/fixture/bem.css');
32+
teardown(() => {
33+
detachHook('.css');
34+
dropCache('./api/fixture/bem.css');
35+
});
1836
});
1937
});

Diff for: test/lib/transformTokens.js

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
'use strict';
2+
3+
const {camelizeDashes, transformTokens} = require('../../lib/transformTokens');
4+
5+
suite('lib/transformTokens', () => {
6+
test('camelizeDashes', () => {
7+
assert.equal(camelizeDashes(''), '');
8+
assert.equal(camelizeDashes('a-a'), 'aA');
9+
assert.equal(camelizeDashes('a-a-b'), 'aAB');
10+
assert.equal(camelizeDashes('a-'), 'a-');
11+
});
12+
13+
suite('transformTokens', () => {
14+
test('`true -> should transform all the keys to CC, keeps original keys', () => {
15+
assert.deepEqual(transformTokens({
16+
'k-e-bab': 'kebab case',
17+
's_na_ke': 'snake case',
18+
'simple': 'aaa',
19+
}, true), {
20+
'k-e-bab': 'kebab case',
21+
's_na_ke': 'snake case',
22+
'simple': 'aaa',
23+
'kEBab': 'kebab case',
24+
'sNaKe': 'snake case',
25+
});
26+
});
27+
28+
test('`dashes` -> should transform the keys with dashed, keeps original keys', () => {
29+
assert.deepEqual(transformTokens({
30+
'k-e-bab': 'kebab case',
31+
's_na_ke': 'snake case',
32+
'simple': 'aaa',
33+
}, 'dashes'), {
34+
'k-e-bab': 'kebab case',
35+
's_na_ke': 'snake case',
36+
'simple': 'aaa',
37+
'kEBab': 'kebab case',
38+
});
39+
});
40+
41+
test('`dashesOnly` -> should transform only keys with dashes', () => {
42+
assert.deepEqual(transformTokens({
43+
'k-e-bab': 'kebab case',
44+
's_na_ke': 'snake case',
45+
'simple': 'aaa',
46+
}, 'dashesOnly'), {
47+
's_na_ke': 'snake case',
48+
'simple': 'aaa',
49+
'kEBab': 'kebab case',
50+
});
51+
});
52+
53+
test('`only` -> should camelize keys', () => {
54+
assert.deepEqual(transformTokens({
55+
'k-e-bab': 'kebab case',
56+
's_na_ke': 'snake case',
57+
'simple': 'aaa',
58+
}, 'only'), {
59+
'simple': 'aaa',
60+
'kEBab': 'kebab case',
61+
'sNaKe': 'snake case',
62+
});
63+
});
64+
});
65+
});

0 commit comments

Comments
 (0)