Skip to content

Commit ba3dcf2

Browse files
committed
Prepare async path resolving
1 parent fd2b1dd commit ba3dcf2

File tree

4 files changed

+110
-106
lines changed

4 files changed

+110
-106
lines changed

index.js

+37-89
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,19 @@ var fs = require("fs")
55
var path = require("path")
66

77
var assign = require("object-assign")
8-
var resolve = require("resolve")
98
var postcss = require("postcss")
109
var helpers = require("postcss-message-helpers")
1110
var glob = require("glob")
1211
var parseImports = require("./lib/parse-imports")
1312
var resolveMedia = require("./lib/resolve-media")
13+
var resolveId = require("./lib/resolve-id")
1414

1515
/**
1616
* Constants
1717
*/
1818
var moduleDirectories = [
1919
"web_modules",
2020
"node_modules",
21-
"bower_components",
2221
]
2322

2423
/**
@@ -256,42 +255,48 @@ function readAtImport(
256255
return Promise.resolve()
257256
}
258257

258+
var dir = atRule.source && atRule.source.input && atRule.source.input.file
259+
? path.dirname(path.resolve(options.root, atRule.source.input.file))
260+
: options.root
261+
259262
addInputToPath(options)
260-
var resolvedFilename = resolveFilename(
261-
parsedAtImport.uri,
262-
options.root,
263-
options.path,
264-
atRule.source,
265-
options.resolve
266-
)
267263

268-
if (options.skipDuplicates) {
269-
// skip files already imported at the same scope
270-
if (
271-
state.importedFiles[resolvedFilename] &&
272-
state.importedFiles[resolvedFilename][media]
273-
) {
274-
atRule.remove()
275-
return Promise.resolve()
264+
return Promise.resolve().then(function() {
265+
if (options.resolve) {
266+
return options.resolve(parsedAtImport.uri, dir, options)
276267
}
268+
return resolveId(parsedAtImport.uri, dir, options.path)
269+
}).then(function(resolvedFilename) {
270+
if (options.skipDuplicates) {
271+
// skip files already imported at the same scope
272+
if (
273+
state.importedFiles[resolvedFilename] &&
274+
state.importedFiles[resolvedFilename][media]
275+
) {
276+
atRule.remove()
277+
return Promise.resolve()
278+
}
277279

278-
// save imported files to skip them next time
279-
if (!state.importedFiles[resolvedFilename]) {
280-
state.importedFiles[resolvedFilename] = {}
280+
// save imported files to skip them next time
281+
if (!state.importedFiles[resolvedFilename]) {
282+
state.importedFiles[resolvedFilename] = {}
283+
}
284+
state.importedFiles[resolvedFilename][media] = true
281285
}
282-
state.importedFiles[resolvedFilename][media] = true
283-
}
284286

285-
return readImportedContent(
286-
result,
287-
atRule,
288-
parsedAtImport,
289-
assign({}, options),
290-
resolvedFilename,
291-
state,
292-
media,
293-
processor
294-
)
287+
return readImportedContent(
288+
result,
289+
atRule,
290+
parsedAtImport,
291+
assign({}, options),
292+
resolvedFilename,
293+
state,
294+
media,
295+
processor
296+
)
297+
}).catch(function(err) {
298+
result.warn(err.message, { node: atRule })
299+
})
295300
}
296301

297302
/**
@@ -414,63 +419,6 @@ function insertRules(atRule, parsedAtImport, newStyles) {
414419
atRule.replaceWith(newNodes)
415420
}
416421

417-
/**
418-
* Check if a file exists
419-
*
420-
* @param {String} name
421-
*/
422-
function resolveFilename(name, root, paths, source, resolver) {
423-
var dir = source && source.input && source.input.file
424-
? path.dirname(path.resolve(root, source.input.file))
425-
: root
426-
427-
try {
428-
var resolveOpts = {
429-
basedir: dir,
430-
moduleDirectory: moduleDirectories.concat(paths),
431-
paths: paths,
432-
extensions: [ ".css" ],
433-
packageFilter: function processPackage(pkg) {
434-
pkg.main = pkg.style || "index.css"
435-
return pkg
436-
},
437-
}
438-
var file
439-
resolver = resolver || resolve.sync
440-
try {
441-
file = resolver(name, resolveOpts)
442-
}
443-
catch (e) {
444-
// fix to try relative files on windows with "./"
445-
// if it's look like it doesn't start with a relative path already
446-
// if (name.match(/^\.\.?/)) {throw e}
447-
try {
448-
file = resolver("./" + name, resolveOpts)
449-
}
450-
catch (err) {
451-
// LAST HOPE
452-
if (!paths.some(function(dir2) {
453-
file = path.join(dir2, name)
454-
return fs.existsSync(file)
455-
})) {
456-
throw err
457-
}
458-
}
459-
}
460-
461-
return path.normalize(file)
462-
}
463-
catch (e) {
464-
throw new Error(
465-
"Failed to find '" + name + "' from " + root +
466-
"\n in [ " +
467-
"\n " + paths.join(",\n ") +
468-
"\n ]",
469-
source
470-
)
471-
}
472-
}
473-
474422
/**
475423
* Read the contents of a file
476424
*

lib/resolve-id.js

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
var fs = require("fs")
2+
var path = require("path")
3+
var resolve = require("resolve")
4+
5+
var moduleDirectories = [
6+
"web_modules",
7+
"node_modules",
8+
]
9+
10+
module.exports = function(id, base, paths) {
11+
try {
12+
var resolveOpts = {
13+
basedir: base,
14+
moduleDirectory: moduleDirectories,
15+
paths: paths,
16+
extensions: [ ".css" ],
17+
packageFilter: function processPackage(pkg) {
18+
pkg.main = pkg.style || "index.css"
19+
return pkg
20+
},
21+
}
22+
var file
23+
try {
24+
file = resolve.sync(id, resolveOpts)
25+
}
26+
catch (e) {
27+
// fix to try relative files on windows with "./"
28+
// if it's look like it doesn't start with a relative path already
29+
// if (id.match(/^\.\.?/)) {throw e}
30+
try {
31+
file = resolve.sync("./" + id, resolveOpts)
32+
}
33+
catch (err) {
34+
// LAST HOPE
35+
if (!paths.some(function(dir) {
36+
file = path.join(dir, id)
37+
return fs.existsSync(file)
38+
})) {
39+
throw err
40+
}
41+
}
42+
}
43+
44+
return path.normalize(file)
45+
}
46+
catch (e) {
47+
throw new Error([
48+
"Failed to find '" + id + "'",
49+
"in [ ",
50+
" " + paths.join(",\n "),
51+
"]",
52+
].join("\n "))
53+
}
54+
}

test/fixtures/ignore.expected.css

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
@import "http://css" (min-width: 25em);
2-
3-
@import "http://css-screen" (min-width: 25em) and screen;
41

52
@import "http://css";
63

@@ -28,6 +25,10 @@
2825

2926
@import url(//css);
3027

28+
@import "http://css" (min-width: 25em);
29+
30+
@import "http://css-screen" (min-width: 25em) and screen;
31+
3132
@media (min-width: 25em){
3233
ignore{}
3334
}

test/import.js

+15-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import test from "ava"
2+
import path from "path"
23
import { readFileSync } from "fs"
34
import postcss from "postcss"
45
import atImport from ".."
@@ -85,13 +86,11 @@ test("should output readable trace", t => {
8586
return postcss()
8687
.use(atImport())
8788
.process(readFileSync(file), { from: file })
88-
.catch(error => {
89-
t.throws(
90-
() => {
91-
throw error
92-
},
89+
.then(result => {
90+
t.is(
91+
result.warnings()[0].text,
9392
/* eslint-disable max-len */
94-
/import-missing.css:2:5: Failed to find 'missing-file.css' from .*\n\s+in \[/gm
93+
"Failed to find 'missing-file.css'\n in [ \n " + path.resolve("fixtures/imports") + "\n ]"
9594
/* eslint-enabme max-len */
9695
)
9796
})
@@ -155,14 +154,16 @@ test("should work with no styles without throwing an error", t => {
155154

156155
test("should be able to consume modules in the custom-resolve way", t => {
157156
const resolve = require("resolve")
158-
const sassResolve = (file, opts) => {
159-
opts = opts || {}
160-
opts.extensions = [ ".scss", ".css" ]
161-
opts.packageFilter = pkg => {
162-
pkg.main = pkg.sass || pkg.style || "index"
163-
return pkg
164-
}
165-
return resolve.sync(file, opts)
157+
const sassResolve = (id, base, opts) => {
158+
return resolve.sync(id, {
159+
basedir: base,
160+
extensions: [ ".scss", ".css" ],
161+
paths: opts.path,
162+
packageFilter: pkg => {
163+
pkg.main = pkg.sass || pkg.style || "index"
164+
return pkg
165+
},
166+
})
166167
}
167168
return compareFixtures(t, "custom-resolve-modules", {
168169
root: ".",

0 commit comments

Comments
 (0)