Skip to content

Commit

Permalink
test for path resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
sullenor committed Mar 8, 2017
1 parent 54c574a commit 6f6fa14
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 3 deletions.
8 changes: 7 additions & 1 deletion lib/resolveDeps.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const {dirname} = require('path');
const {readFileSync} = require('fs');
const {resolveModule} = require('./resolveModule');
const {resolvePaths} = require('./resolvePaths');

const PERMANENT_MARK = 2;
const TEMPORARY_MARK = 1;
Expand All @@ -24,10 +25,12 @@ function resolveDeps(ast, result) {
from: selfPath,
graph,
resolve,
rootPath,
rootTree,
} = result.opts; // rootPath
} = result.opts;

const cwd = dirname(selfPath);
const rootDir = dirname(rootPath);
const processor = result.processor;
const self = graph[selfPath] = graph[selfPath] || {};

Expand Down Expand Up @@ -84,6 +87,9 @@ function resolveDeps(ast, result) {
self.mark = PERMANENT_MARK;
self.exports = ast.exports = moduleExports;

// resolve paths
if (cwd !== rootDir) resolvePaths(ast, cwd, rootDir);

// append comment
rootTree.append(ast.nodes);
}
Expand Down
56 changes: 56 additions & 0 deletions lib/resolvePaths.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
'use strict';

const {parseValues, stringifyValues} = require('css-selector-tokenizer');
const {relative, resolve, sep} = require('path');

const isRelativeUrl = filepath => /^(?:\.\.?(?:[\\\/]|$))/.test(filepath);

exports.isRelativeUrl = isRelativeUrl;
exports.iterateValues = iterateValues;
exports.resolvePaths = resolvePaths;

function iterateValues(values, iteratee) {
values.nodes.forEach(value =>
value.nodes.forEach(item => iteratee(item)));
}

function resolvePaths(ast, from, to) {
// @import
ast.walkAtRules(atrule => {
if (atrule.name === 'import') {
const values = parseValues(atrule.params);

iterateValues(values, item => {
if (item.type === 'string' && isRelativeUrl(item.value))
item.value = resolveUrl(item.value, from, to);

if (item.type === 'url' && isRelativeUrl(item.url))
item.url = resolveUrl(item.url, from, to);
});

atrule.params = stringifyValues(values);
}
});

// background: url(..)
ast.walkDecls(decl => {
if (/url/.test(decl.value)) {
const values = parseValues(decl.value);

iterateValues(values, item => {
if (item.type === 'url' && isRelativeUrl(item.url))
item.url = resolveUrl(item.url, from, to);
});

decl.value = stringifyValues(values);
}
});
}

function resolveUrl(url, from, to) {
const resolvedUrl = relative(to, resolve(from, url));

return !isRelativeUrl(resolvedUrl)
? '.' + sep + resolvedUrl
: resolvedUrl;
}
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@
"postcss-modules-local-by-default": "^1.1.1",
"postcss-modules-scope": "^1.0.2",
"tape": "^4.6.3"
},
"dependencies": {
"css-selector-tokenizer": "^0.7.0"
}
}
5 changes: 3 additions & 2 deletions sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
* Notes about postcss plugin's api
*
* Containers are iterated with .walk* methods.
* Rules are actually selectors.
* Decls are actually css rules (keys prop, value).
* - Rule is actually a selector.
* - AtRule usually is rule, that starts from '@'.
* - Decl are actually css rules (keys prop, value).
*
* @see http://api.postcss.org/AtRule.html#walkRules
*/
Expand Down
1 change: 1 addition & 0 deletions test/case/resolve-paths/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!node_modules
9 changes: 9 additions & 0 deletions test/case/resolve-paths/expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* should be './lib/reset1.css' */
@import url('./lib/reset1.css');
/* should be './lib/reset2.css' */
@import './lib/reset2.css';
._nested_url-decl {
/* should be ./lib/spin-icon.svg */
background: url(./lib/spin-icon.svg) 0 0 no-repeat
}
._source_relative {}
10 changes: 10 additions & 0 deletions test/case/resolve-paths/lib/nested.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* should be './lib/reset1.css' */
@import url('./reset1.css');
/* should be './lib/reset2.css' */
@import './reset2.css';

.url-decl
{
/* should be ./lib/spin-icon.svg */
background: url(./spin-icon.svg) 0 0 no-repeat;
}
4 changes: 4 additions & 0 deletions test/case/resolve-paths/source.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.relative
{
composes: url-decl from './lib/nested.css';
}
16 changes: 16 additions & 0 deletions test/case/resolve-paths/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use strict';

const setup = require('../../setup');
const test = require('tape');

test('resolve-paths', t => {
const {expected, resulting} = setup(
'local-by-default',
'extract-imports',
'scope',
'self'
)(__dirname);

t.equal(resulting.trim(), expected.trim());
t.end();
});

0 comments on commit 6f6fa14

Please sign in to comment.