Skip to content

Commit 0af9d4a

Browse files
committed
Merge pull request #15 from css-modules/non-relative-imports
Non relative imports
2 parents 4f84739 + 7418dec commit 0af9d4a

File tree

7 files changed

+64
-21
lines changed

7 files changed

+64
-21
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ build/Release
2424

2525
# Dependency directory
2626
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
27-
node_modules
27+
node_modules/*
2828

2929
# added automatically by precommit-hook as defaults
3030
.jshint*
3131

3232
dist/
33+
!node_modules/awesome-theme

node_modules/awesome-theme/oceanic.css

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
"version": "1.0.2",
44
"description": "A require hook to compile CSS Modules on the fly",
55
"main": "index.js",
6+
"engines": {
7+
"node": ">0.12"
8+
},
69
"devDependencies": {
710
"babel": "^5.8.20",
811
"babel-eslint": "^4.0.5",

src/index.js

+39-20
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
11
import './guard';
22
import hook from './hook';
33
import postcss from 'postcss';
4-
import { dirname, join, relative, resolve } from 'path';
4+
import { dirname, join, parse, relative, resolve, sep } from 'path';
55
import { readFileSync } from 'fs';
66

77
import ExtractImports from 'postcss-modules-extract-imports';
88
import LocalByDefault from 'postcss-modules-local-by-default';
99
import Scope from 'postcss-modules-scope';
1010
import Parser from './parser';
1111

12+
const escapedSeparator = sep.replace(/(.)/g, '\\$1');
13+
const relativePathPattern = new RegExp(`^.{1,2}$|^.{1,2}${escapedSeparator}`);
14+
1215
const defaultRoot = process.cwd();
1316
const tokensByFile = {};
1417
let plugins = [LocalByDefault, ExtractImports, Scope];
1518
let root = defaultRoot;
19+
let importNr = 0;
20+
21+
/**
22+
* @param {string} pathname
23+
* @return {boolean}
24+
*/
25+
function isModule(pathname) {
26+
const parsed = parse(pathname);
27+
return !parsed.root && !relativePathPattern.test(parsed.dir);
28+
}
1629

1730
/**
1831
* @param {string} sourceString The file content
@@ -29,32 +42,38 @@ function load(sourceString, sourcePath, trace, pathFetcher) {
2942
return result.tokens;
3043
}
3144

32-
hook(filename => {
33-
let importNr = 0;
45+
/**
46+
* @param {string} _newPath
47+
* @param {string} _relativeTo
48+
* @param {string} _trace
49+
* @return {object}
50+
*/
51+
function fetch(_newPath, _relativeTo, _trace) {
52+
const newPath = _newPath.replace(/^["']|["']$/g, '');
53+
const trace = _trace || String.fromCharCode(importNr++);
3454

35-
const fetch = (_newPath, _relativeTo, _trace) => {
36-
const newPath = _newPath.replace(/^["']|["']$/g, '');
37-
const trace = _trace || String.fromCharCode(importNr++);
55+
const relativeDir = dirname(_relativeTo);
56+
const rootRelativePath = resolve(relativeDir, newPath);
57+
let fileRelativePath = resolve(join(root, relativeDir), newPath);
3858

39-
const relativeDir = dirname(_relativeTo);
40-
const rootRelativePath = resolve(relativeDir, newPath);
41-
const fileRelativePath = resolve(join(root, relativeDir), newPath);
59+
if (isModule(newPath)) {
60+
fileRelativePath = require.resolve(newPath);
61+
}
4262

43-
const tokens = tokensByFile[fileRelativePath];
44-
if (tokens) {
45-
return tokens;
46-
}
63+
const tokens = tokensByFile[fileRelativePath];
64+
if (tokens) {
65+
return tokens;
66+
}
4767

48-
const source = readFileSync(fileRelativePath, 'utf-8');
49-
const exportTokens = load(source, rootRelativePath, trace, fetch);
68+
const source = readFileSync(fileRelativePath, 'utf-8');
69+
const exportTokens = load(source, rootRelativePath, trace, fetch);
5070

51-
tokensByFile[fileRelativePath] = exportTokens;
71+
tokensByFile[fileRelativePath] = exportTokens;
5272

53-
return exportTokens;
54-
};
73+
return exportTokens;
74+
}
5575

56-
return fetch(relative(root, filename), '/');
57-
});
76+
hook(filename => fetch(`.${sep}${relative(root, filename)}`, '/'));
5877

5978
/**
6079
* @param {object} opts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"localName": "_test_cases_non_relative_imports_source__localName _test_cases_non_relative_imports_awesome_theme_oceanic__color"
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.localName
2+
{
3+
composes: color from 'awesome-theme/oceanic.css';
4+
}

test/index.js

+9
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,13 @@ describe('css-modules-require-hook', () => {
1414
equal(JSON.stringify(expectedTokens), JSON.stringify(tokens));
1515
});
1616
});
17+
18+
describe('non-relative imports', () => {
19+
it('should resolve to node_modules', () => {
20+
const expectedTokens = JSON.parse(readFileSync(join(__dirname, './cases/non-relative-imports/expected.json'), 'utf8'));
21+
const tokens = require('./cases/non-relative-imports/source.css');
22+
23+
equal(JSON.stringify(expectedTokens), JSON.stringify(tokens));
24+
});
25+
});
1726
});

0 commit comments

Comments
 (0)