Skip to content

Commit

Permalink
Add ability to consume local modules
Browse files Browse the repository at this point in the history
Close #12
  • Loading branch information
MoOx committed Nov 25, 2014
1 parent 331a3b2 commit 6fd726a
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 52 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# 3.1.0 - 2014-11-24

- Add ability to consume local modules (fix [#12](https://github.com/postcss/postcss-import/issues/12))

# 3.0.0 - 2014-11-21

- Add ability to consume npm packages ([ref](https://github.com/postcss/postcss-import/issues/7)).
- Add ability to consume node modules ([ref](https://github.com/postcss/postcss-import/issues/7)).
This means you don't have to add `node_modules` in the path anymore (or using `@import "../node_modules/..."`).
Also, `index.css` can be ommited.

Expand Down
61 changes: 21 additions & 40 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ var fs = require("fs")
var path = require("path")

var clone = require("clone")
var findFile = require("find-file")
var resolve = require("resolve")
var postcss = require("postcss")
var helpers = require("postcss-message-helpers")

/**
* Expose the plugin.
Expand Down Expand Up @@ -44,7 +44,7 @@ function AtImport(options) {
options.path.push(process.cwd())
}

parseStyles(styles, options)
parseStyles(styles, options, insertRules)
}
}

Expand All @@ -54,7 +54,7 @@ function AtImport(options) {
* @param {Object} styles
* @param {Object} options
*/
function parseStyles(styles, options, importedFiles, ignoredAtRules, media) {
function parseStyles(styles, options, cb, importedFiles, ignoredAtRules, media) {
var isRoot = ignoredAtRules === undefined
importedFiles = importedFiles || {}
ignoredAtRules = ignoredAtRules || []
Expand All @@ -63,7 +63,9 @@ function parseStyles(styles, options, importedFiles, ignoredAtRules, media) {
return
}

readAtImport(atRule, options, importedFiles, ignoredAtRules, media)
helpers.try(function transformAtImport() {
readAtImport(atRule, options, cb, importedFiles, ignoredAtRules, media)
}, atRule.source)
})

if (isRoot) {
Expand Down Expand Up @@ -102,7 +104,7 @@ function addIgnoredAtRulesOnTop(styles, ignoredAtRules) {
* @param {Object} atRule postcss atRule
* @param {Object} options
*/
function readAtImport(atRule, options, importedFiles, ignoredAtRules, media) {
function readAtImport(atRule, options, cb, importedFiles, ignoredAtRules, media) {
// parse-import module parse entire line
// @todo extract what can be interesting from this one
var parsedAtImport = parseImport(atRule.params, atRule.source)
Expand Down Expand Up @@ -130,7 +132,7 @@ function readAtImport(atRule, options, importedFiles, ignoredAtRules, media) {
}
importedFiles[resolvedFilename][media] = true

insertAtImportContent(atRule, parsedAtImport, clone(options), resolvedFilename, importedFiles, ignoredAtRules)
readImportedContent(atRule, parsedAtImport, clone(options), resolvedFilename, cb, importedFiles, ignoredAtRules)
}

/**
Expand All @@ -140,10 +142,9 @@ function readAtImport(atRule, options, importedFiles, ignoredAtRules, media) {
* @param {Object} parsedAtImport
* @param {Object} options
* @param {String} resolvedFilename
* @param {Array} importedFiles
* @param {Array} ignoredAtRules
* @param {Function} cb
*/
function insertAtImportContent(atRule, parsedAtImport, options, resolvedFilename, importedFiles, ignoredAtRules) {
function readImportedContent(atRule, parsedAtImport, options, resolvedFilename, cb, importedFiles, ignoredAtRules) {
// add directory containing the @imported file in the paths
// to allow local import from this file
var dirname = path.dirname(resolvedFilename)
Expand All @@ -156,17 +157,17 @@ function insertAtImportContent(atRule, parsedAtImport, options, resolvedFilename
var fileContent = readFile(resolvedFilename, options.encoding, options.transform || function(value) { return value })

if (fileContent.trim() === "") {
console.warn(gnuMessage(resolvedFilename + " is empty", atRule.source))
console.warn(helpers.message(resolvedFilename + " is empty", atRule.source))
atRule.removeSelf()
return
}

var newStyles = postcss.parse(fileContent, options)

// recursion: import @import from imported file
parseStyles(newStyles, options, importedFiles, ignoredAtRules, parsedAtImport.media)
parseStyles(newStyles, options, cb, importedFiles, ignoredAtRules, parsedAtImport.media)

insertRules(atRule, parsedAtImport, newStyles)
cb(atRule, parsedAtImport, newStyles, resolvedFilename)
}

/**
Expand Down Expand Up @@ -209,7 +210,7 @@ function parseImport(str, source) {
var regex = /((?:url\s?\()?(?:'|")?([^)'"]+)(?:'|")?\)?)(?:(?:\s)(.*))?/gi
var matches = regex.exec(str)
if (matches === null) {
throw new Error(gnuMessage("Unable to find uri in '" + str + "'", source))
throw new Error("Unable to find uri in '" + str + "'", source)
}

return {
Expand All @@ -225,20 +226,13 @@ function parseImport(str, source) {
* @param {String} name
*/
function resolveFilename(name, paths, source) {
var file = findFile(name, {path: paths, global: false})
if (file) {
// if (file.length > 1) {
// console.warn(gnuMessage("Warning: multiples files found for `" + name + "`: " + file, source))
// }
return file[0]
}

var root = paths[paths.length - 1]
var dir = source && source.file ? path.dirname(path.resolve(root, source.file)) : root

try {
file = resolve.sync(name, {
var file = resolve.sync(name, {
basedir: dir,
moduleDirectory: ["node_modules"].concat(paths),
extensions: [".css"],
packageFilter: function processPackage(pkg) {
pkg.main = pkg.style || "index.css"
Expand All @@ -250,14 +244,11 @@ function resolveFilename(name, paths, source) {
}
catch (e) {
throw new Error(
// GNU style message
gnuMessage(
"Failed to find '" + name + "'" +
"\n in [ " +
"\n " + paths.join(",\n ") +
"\n ]",
source
)
"Failed to find '" + name + "'" +
"\n in [ " +
"\n " + paths.join(",\n ") +
"\n ]",
source
)
}
}
Expand All @@ -284,13 +275,3 @@ function addInputToPath(options) {
}
}
}

/**
* return GNU style message
*
* @param {String} message
* @param {Object} source
*/
function gnuMessage(message, source) {
return (source ? (source.file ? source.file : "<css input>") + ":" + source.start.line + ":" + source.start.column + " " : "") + message
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
],
"dependencies": {
"clone": "^0.1.17",
"find-file": "^0.1.4",
"postcss": "^3.0.0",
"postcss-message-helpers": "^1.1.0",
"resolve": "^1.0.0"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/imports/local-module/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.local-module{}
1 change: 1 addition & 0 deletions test/fixtures/imports/local-module/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"style": "main.css"}
1 change: 1 addition & 0 deletions test/fixtures/npm.css → test/fixtures/modules.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
@import "use-dep";
@import "use-dep-too";
@import "use-dep" screen;
@import "local-module";
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
@media screen{
.dep{}
}
.local-module{}
18 changes: 8 additions & 10 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use strict";

var test = require("tape")
var assert = require("assert")

var path = require("path")
var fs = require("fs")
Expand All @@ -18,7 +17,10 @@ function read(name) {

function compareFixtures(t, name, msg, opts, postcssOpts) {
opts = opts || {path: importsDir}
var actual = postcss().use(atImport(opts)).process(read("fixtures/" + name), postcssOpts).css.trim()
var actual = postcss()
.use(atImport(opts))
.process(read("fixtures/" + name), postcssOpts)
.css.trim()
var expected = read("fixtures/" + name + ".expected")

// handy thing: checkout actual in the *.actual.css file
Expand Down Expand Up @@ -49,20 +51,16 @@ test("@import", function(t) {

compareFixtures(t, "relative-to-source", "should not need `path` option if `source` option has been passed to postcss", null, {from: "test/fixtures/relative-to-source.css"})

compareFixtures(t, "npm", "should be able to consume npm package")
compareFixtures(t, "modules", "should be able to consume npm package or local modules")

t.end()
})

test("@import error output", function(t) {
var file = importsDir + "/import-missing.css"
t.doesNotThrow(
function() {
assert.throws(
function() {postcss().use(atImport()).process(fs.readFileSync(file), {from: file})},
/import-missing.css:2:5 Failed to find 'missing-file.css'\n\s+in \[/gm
)
},
t.throws(
function() {postcss().use(atImport()).process(fs.readFileSync(file), {from: file})},
/import-missing.css:2:5: Failed to find 'missing-file.css'\n\s+in \[/gm,
"should output readable trace"
)

Expand Down

0 comments on commit 6fd726a

Please sign in to comment.