Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5374b10

Browse files
Merge pull request #47 from css-modules/generic-names
Generic names
2 parents 63ce15c + ef58c9c commit 5374b10

File tree

26 files changed

+313
-230
lines changed

26 files changed

+313
-230
lines changed

‎.eslintrc‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"mocha": true
66
},
77
"rules": {
8+
"key-spacing": [2, {"align": "value"}],
89
"no-use-before-define": [2, "nofunc"]
910
}
1011
}

‎generate-tests.js‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ function resolveTo() {
1111
}
1212

1313
let content =
14+
`import { dropCache } from '../utils/sugar';\n`+
1415
`import { equal } from 'assert';\n`+
1516
`import { readFileSync } from 'fs';\n`+
1617
`import { resolve } from 'path';\n`+
@@ -41,12 +42,13 @@ cases.forEach(dirname => {
4142
`\n`+
4243
` describe('${testCase.replace(/-/g, ' ')}', () => {\n`+
4344
` before(() => {\n`+
45+
` dropCache(resolve('test${sep + dirname + sep + testCase + sep}source.css'));\n`+
4446
` expectedCSS = normalize(readFileSync(resolve('test${sep + dirname + sep + testCase + sep}expected.css'), 'utf8'));\n`+
4547
` expectedTokens = JSON.parse(readFileSync(resolve('test${sep + dirname + sep + testCase + sep}expected.json'), 'utf8'));\n`+
4648
` hook({rootDir: resolve('test${sep + dirname}'), use: pipelines['${dirname}']});\n`+
4749
` });\n`+
4850
`\n`+
49-
` it('loader-core', done => {\n`+
51+
` it.skip('loader-core', done => {\n`+
5052
` const loader = new FileSystemLoader(resolve('test${sep + dirname}'), pipelines['${dirname}']);\n`+
5153
`\n`+
5254
` loader.fetch('${testCase + sep}source.css', '/')\n`+
@@ -69,12 +71,14 @@ cases.forEach(dirname => {
6971
`\n`+
7072
` describe('${testCase.replace(/-/g, ' ')}', () => {\n`+
7173
` before(() => {\n`+
74+
` dropCache(resolve('test${sep + dirname + sep + testCase + sep}source1.css'));\n`+
75+
` dropCache(resolve('test${sep + dirname + sep + testCase + sep}source2.css'));\n`+
7276
` expectedCSS = normalize(readFileSync(resolve('test${sep + dirname + sep + testCase + sep}expected.css'), 'utf8'));\n`+
7377
` expectedTokens = JSON.parse(readFileSync(resolve('test${sep + dirname + sep + testCase + sep}expected.json'), 'utf8'));\n`+
7478
` hook({rootDir: resolve('test${sep + dirname}'), use: pipelines['${dirname}']});\n`+
7579
` });\n`+
7680
`\n`+
77-
` it('loader-core', done => {\n`+
81+
` it.skip('loader-core', done => {\n`+
7882
` const loader = new FileSystemLoader(resolve('test${sep + dirname}'), pipelines['${dirname}']);\n`+
7983
`\n`+
8084
` loader.fetch('${testCase + sep}source1.css', '/').then(tokens1 => {\n`+

‎package.json‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
},
99
"dependencies": {
1010
"debug": "^2.2.0",
11+
"generic-names": "^1.0.0-beta",
1112
"icss-replace-symbols": "^1.0.2",
12-
"lodash.assign": "^3.2.0",
13+
"lodash.foreach": "^3.0.3",
1314
"lodash.identity": "^3.0.0",
1415
"lodash.isarray": "^3.0.4",
1516
"lodash.isfunction": "^3.0.6",
16-
"lodash.isstring": "^3.0.1",
17-
"lodash.pick": "^3.1.0"
17+
"lodash.isstring": "^3.0.1"
1818
},
1919
"devDependencies": {
2020
"babel": "^5.8.20",
@@ -28,7 +28,7 @@
2828
"isparta": "^3.0.3",
2929
"lodash": "^3.10.1",
3030
"mocha": "^2.2.5",
31-
"postcss": "^5.x",
31+
"postcss": "^5.0.10",
3232
"postcss-modules-extract-imports": "^1.0.0",
3333
"postcss-modules-local-by-default": "^1.0.0",
3434
"postcss-modules-scope": "^1.0.0",
@@ -45,7 +45,6 @@
4545
"scripts": {
4646
"start": "esw -w .",
4747
"lint": "eslint .",
48-
"pretest": "npm run -s lint",
4948
"test": "mocha --compilers js:babel/register",
5049
"test:cov": "`npm bin`/babel-node `npm bin`/isparta cover --report text --report html `npm bin`/_mocha",
5150
"test:gen": "babel-node generate-tests",
@@ -71,6 +70,7 @@
7170
},
7271
"homepage": "https://github.com/css-modules/css-modules-require-hook",
7372
"pre-commit": [
73+
"lint",
7474
"test"
7575
]
7676
}

‎src/extractor.js‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import postcss from 'postcss';
2+
import genericNames from 'generic-names';
3+
4+
import Values from 'postcss-modules-values';
5+
import LocalByDefault from 'postcss-modules-local-by-default';
6+
import ExtractImports from 'postcss-modules-extract-imports';
7+
import Scope from 'postcss-modules-scope';
8+
import Parser from './parser';
9+
10+
/**
11+
* @param {array} options.append
12+
* @param {array} options.prepend
13+
* @param {array} options.use
14+
* @param {function} options.createImportedName
15+
* @param {function|string} options.generateScopedName
16+
* @param {string} options.mode
17+
* @param {string} options.rootDir
18+
* @param {function} fetch
19+
* @return {object}
20+
*/
21+
export default function extractor({
22+
append = [],
23+
prepend = [],
24+
createImportedName,
25+
generateScopedName,
26+
mode,
27+
use,
28+
rootDir: context = process.cwd(),
29+
} = {}, fetch) {
30+
const scopedName = typeof generateScopedName !== 'function'
31+
? genericNames(generateScopedName || '[name]__[local]___[hash:base64:5]', {context})
32+
: generateScopedName;
33+
34+
const plugins = (use || [
35+
...prepend,
36+
Values,
37+
mode
38+
? new LocalByDefault({mode})
39+
: LocalByDefault,
40+
createImportedName
41+
? new ExtractImports({createImportedName})
42+
: ExtractImports,
43+
new Scope({generateScopedName: scopedName}),
44+
...append,
45+
]).concat(new Parser({fetch})); // no pushing in order to avoid the possible mutations
46+
47+
return postcss(plugins);
48+
}

‎src/guard.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
if (global._cssModulesPolyfill) {
2-
throw new Error('only one instance of css-modules/polyfill is allowed');
2+
throw new Error('only one instance of css-modules-require-hook is allowed');
33
}
44

55
global._cssModulesPolyfill = true;

‎src/index.js‎

Lines changed: 36 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,57 @@
11
import debug from 'debug';
22
import hook from './hook';
3-
import { readFileSync } from 'fs';
4-
import { dirname, sep, relative, resolve } from 'path';
5-
import { get, removeQuotes } from './utility';
6-
import assign from 'lodash.assign';
73
import identity from 'lodash.identity';
8-
import pick from 'lodash.pick';
9-
import postcss from 'postcss';
10-
11-
import Values from 'postcss-modules-values';
12-
import ExtractImports from 'postcss-modules-extract-imports';
13-
import LocalByDefault from 'postcss-modules-local-by-default';
14-
import Scope from 'postcss-modules-scope';
15-
import Parser from './parser';
16-
17-
const debugFetch = debug('css-modules:fetch');
18-
const debugSetup = debug('css-modules:setup');
4+
import extractor from './extractor';
5+
import { readFileSync } from 'fs';
6+
import { dirname, resolve } from 'path';
7+
import { removeQuotes } from './utility';
8+
import validate from './validate';
9+
import './guard';
1910

2011
// cache
21-
let importNr = 0;
2212
let tokensByFile = {};
23-
// processing functions
13+
// global
14+
let instance = extractor({}, fetch);
15+
let processorOptions = {};
2416
let preProcess = identity;
2517
let postProcess;
26-
// defaults
27-
let lazyResultOpts = {};
28-
let plugins = [LocalByDefault, ExtractImports, Scope];
29-
let rootDir = process.cwd();
18+
19+
const debugFetch = debug('css-modules:fetch');
20+
const debugSetup = debug('css-modules:setup');
3021

3122
/**
32-
* @param {object} opts
33-
* @param {function} opts.createImportedName
34-
* @param {function} opts.generateScopedName
35-
* @param {function} opts.preprocessCss
36-
* @param {function} opts.processCss
37-
* @param {string} opts.rootDir
38-
* @param {string} opts.to
39-
* @param {array} opts.use
40-
* @param {array} opts.extensions
23+
* @param {array} options.extensions
24+
* @param {function} options.preprocessCss
25+
* @param {function} options.processCss
26+
* @param {string} options.to
27+
* @param {object} options.rest
4128
*/
42-
export default function setup(opts = {}) {
43-
debugSetup(opts);
29+
export default function setup({ extensions: extraExtensions, preprocessCss, processCss, to, ...rest } = {}) {
30+
debugSetup(arguments[0]);
31+
validate(arguments[0]);
32+
instance = extractor(rest, fetch);
33+
processorOptions = {to};
34+
preProcess = preprocessCss || identity;
35+
postProcess = processCss || null;
4436
// clearing cache
45-
importNr = 0;
4637
tokensByFile = {};
4738

48-
preProcess = get('preprocessCss', null, 'function', opts) || identity;
49-
postProcess = get('processCss', null, 'function', opts) || null;
50-
rootDir = get('rootDir', ['root', 'd'], 'string', opts) || process.cwd();
51-
// https://github.com/postcss/postcss/blob/master/docs/api.md#processorprocesscss-opts
52-
lazyResultOpts = pick(opts, ['to']);
53-
54-
const extraExtensions = get('extensions', null, 'array', opts);
5539
if (extraExtensions) {
56-
extraExtensions.forEach((extension) => {
57-
hook(filename => fetch(filename, filename), extension);
58-
});
59-
}
60-
61-
// Warning. Options, which aren't affected by plugins, should be processed above.
62-
const customPlugins = get('use', ['u'], 'array', opts);
63-
if (customPlugins) {
64-
return void (plugins = customPlugins);
40+
extraExtensions.forEach((extension) => hook(filename => fetch(filename, filename), extension));
6541
}
66-
67-
const prepend = get('prepend', null, 'array', opts) || [];
68-
const append = get('append', null, 'array', opts) || [];
69-
const mode = get('mode', null, 'string', opts);
70-
const createImportedName = get('createImportedName', null, 'function', opts);
71-
const generateScopedName = get('generateScopedName', null, 'function', opts);
72-
73-
plugins = [
74-
...prepend,
75-
Values,
76-
mode
77-
? new LocalByDefault({mode: opts.mode})
78-
: LocalByDefault,
79-
createImportedName
80-
? new ExtractImports({createImportedName: opts.createImportedName})
81-
: ExtractImports,
82-
generateScopedName
83-
? new Scope({generateScopedName: opts.generateScopedName})
84-
: Scope,
85-
...append,
86-
];
8742
}
8843

8944
/**
90-
* @param {string} _to Absolute or relative path. Also can be path to the Node.JS module.
91-
* @param {string} _from Absolute path (relative to root).
92-
* @param {string} _trace
45+
* @param {string} _to Absolute or relative path. Also can be path to the Node.JS module.
46+
* @param {string} from Absolute path.
9347
* @return {object}
9448
*/
95-
function fetch(_to, _from, _trace) {
96-
const trace = _trace || String.fromCharCode(importNr++);
97-
const newPath = removeQuotes(_to);
49+
function fetch(_to, from) {
50+
const to = removeQuotes(_to);
9851
// getting absolute path to the processing file
99-
const filename = /\w/.test(newPath[0])
100-
? require.resolve(newPath)
101-
: resolve(dirname(_from), newPath);
52+
const filename = /\w/i.test(to[0])
53+
? require.resolve(to)
54+
: resolve(dirname(from), to);
10255

10356
// checking cache
10457
let tokens = tokensByFile[filename];
@@ -108,16 +61,15 @@ function fetch(_to, _from, _trace) {
10861
}
10962

11063
debugFetch({cache: false, filename});
111-
const rootRelativePath = sep + relative(rootDir, filename);
11264
const CSSSource = preProcess(readFileSync(filename, 'utf8'), filename);
65+
// https://github.com/postcss/postcss/blob/master/docs/api.md#processorprocesscss-opts
66+
const lazyResult = instance.process(CSSSource, Object.assign(processorOptions, {from: filename}));
11367

114-
const lazyResult = postcss(plugins.concat(new Parser({ fetch, filename, trace })))
115-
.process(CSSSource, assign(lazyResultOpts, {from: rootRelativePath}));
116-
68+
// https://github.com/postcss/postcss/blob/master/docs/api.md#lazywarnings
11769
lazyResult.warnings().forEach(message => console.warn(message.text));
11870

119-
tokens = lazyResult.root.tokens;
12071
// updating cache
72+
tokens = lazyResult.root.tokens;
12173
tokensByFile[filename] = tokens;
12274

12375
if (postProcess) {

‎src/parser.js‎

Lines changed: 23 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,38 @@
11
import { plugin } from 'postcss';
2+
import forEach from 'lodash.foreach';
23
import replaceSymbols from 'icss-replace-symbols';
3-
44
const importRegexp = /^:import\((.+)\)$/;
5+
const exportRegexp = /^:export$/;
56

6-
export default plugin('parser', function parser(opts = {}) {
7-
const exportTokens = {};
8-
const translations = {};
9-
10-
const fetchImport = (importNode, relativeTo, depNr) => {
11-
const file = importNode.selector.match(importRegexp)[1];
12-
const depTrace = opts.trace + String.fromCharCode(depNr);
13-
const exports = opts.fetch(file, opts.filename, depTrace);
14-
15-
importNode.each(decl => {
16-
if (decl.type === 'decl') {
17-
translations[decl.prop] = exports[decl.value];
18-
}
19-
});
20-
21-
importNode.removeSelf();
22-
};
7+
/**
8+
* @param {function} options.fetch
9+
* @return {function}
10+
*/
11+
export default plugin('parser', function parser({ fetch } = {}) {
12+
return css => {
13+
// https://github.com/postcss/postcss/blob/master/docs/api.md#inputfile
14+
const file = css.source.input.file;
15+
const translations = {};
16+
const exportTokens = {};
2317

24-
constfetchAllImports=css => {
25-
letimports=0;
18+
css.walkRules(importRegexp,rule => {
19+
constexports=fetch(RegExp.1ドル,file);
2620

27-
css.each(node => {
28-
if (node.type === 'rule' && node.selector.match(importRegexp)) {
29-
fetchImport(node, css.source.input.from, imports++);
30-
}
21+
rule.walkDecls(decl => translations[decl.prop] = exports[decl.value]);
22+
rule.remove();
3123
});
32-
};
33-
34-
const linkImportedSymbols = css => replaceSymbols(css, translations);
3524

36-
const handleExport = exportNode => {
37-
exportNode.each(decl => {
38-
if (decl.type === 'decl') {
39-
Object.keys(translations).forEach(translation => {
40-
decl.value = decl.value.replace(translation, translations[translation]);
41-
});
25+
replaceSymbols(css, translations);
4226

27+
css.walkRules(exportRegexp, rule => {
28+
rule.walkDecls(decl => {
29+
forEach(translations, (value, key) => decl.value = decl.value.replace(key, value));
4330
exportTokens[decl.prop] = decl.value;
44-
}
45-
});
31+
});
4632

47-
exportNode.removeSelf();
48-
};
49-
50-
const extractExports = css => css.each(node => {
51-
if (node.type === 'rule' && node.selector === ':export') handleExport(node);
52-
});
33+
rule.remove();
34+
});
5335

54-
return css => {
55-
fetchAllImports(css);
56-
linkImportedSymbols(css);
57-
extractExports(css);
5836
css.tokens = exportTokens;
5937
};
6038
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /