Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add glob option (Boolean, with default false). Closes gh-8 #34

Merged
merged 1 commit into from
Apr 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ Default: `null`

Function called after the import process. Take one argument (array of imported files).

#### `glob`

Type: `Boolean`
Default: `false`

Set to `true` if you want @import rules to parse glob patterns.

#### Example with some options

```js
Expand Down
46 changes: 45 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ var resolve = require("resolve")
var postcss = require("postcss")
var helpers = require("postcss-message-helpers")
var hash = require("string-hash")
var glob = require("glob")

/**
* Constants
Expand Down Expand Up @@ -81,14 +82,57 @@ function AtImport(options) {
*/
function parseStyles(styles, options, cb, importedFiles, ignoredAtRules, media, hashFiles) {
var imports = []
styles.eachAtRule("import", function checkAtRule(atRule) {imports.push(atRule)})
styles.eachAtRule("import", function checkAtRule(atRule) {
if (options.glob && glob.hasMagic(atRule.params)) {
imports = parseGlob(atRule, options, imports)
}
else {
imports.push(atRule)
}
})
imports.forEach(function(atRule) {
helpers.try(function transformAtImport() {
readAtImport(atRule, options, cb, importedFiles, ignoredAtRules, media, hashFiles)
}, atRule.source)
})
}

/**
* parse glob patterns (for relative paths only)
*
* @param {Object} atRule
* @param {Object} options
* @param {Array} imports
*/
function parseGlob(atRule, options, imports) {
var globPattern = atRule.params.replace(/"/g, "")
var files = []
var dir = options.source && options.source.input && options.source.input.file ?
path.dirname(path.resolve(options.root, options.source.input.file)) :
options.root
options.path.forEach(function(p) {
p = path.resolve(dir, p)
var globbed = glob.sync(path.join(p, globPattern))
globbed.forEach(function(file) {
file = path.relative(p, file)
files.push(file)
});
});

files.forEach(function(file) {
var deglobbedAtRule = atRule.clone({
params: "\"" + file + "\""
})
if (deglobbedAtRule.source && deglobbedAtRule.source.input && deglobbedAtRule.source.input.css) {
deglobbedAtRule.source.input.css = atRule.source.input.css.replace(globPattern, file)
}
atRule.parent.insertBefore(atRule, deglobbedAtRule)
imports.push(deglobbedAtRule)
});
atRule.removeSelf()
return imports;
}

/**
* put back at the top ignored url (absolute url)
*
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
],
"dependencies": {
"clone": "^0.1.17",
"glob": "^5.0.1",
"postcss": "^4.0.2",
"postcss-message-helpers": "^2.0.0",
"resolve": "^1.0.0",
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/glob.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import "./foobar*.css";
2 changes: 2 additions & 0 deletions test/fixtures/glob.expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
foobar{}
foobarbaz{}
2 changes: 2 additions & 0 deletions test/fixtures/imports/glob-missing.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@import "./missing*.css";
@import "foobar.css";
20 changes: 19 additions & 1 deletion test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ test("@import", function(t) {

compareFixtures(t, "ignore", "should ignore & adjust external import")

compareFixtures(t, "glob", "should handle a glob pattern", {
path: importsDir,
glob: true
})

compareFixtures(t, "recursive", "should import stylsheets recursively")

compareFixtures(t, "relative", "should import stylsheets relatively")
Expand Down Expand Up @@ -75,7 +80,6 @@ test("@import", function(t) {
t.end()
})


test("@import error output", function(t) {
var file = importsDir + "/import-missing.css"
t.throws(
Expand All @@ -92,6 +96,20 @@ test("@import error output", function(t) {
t.end()
})

test("@import glob pattern matches no files", function(t) {
var file = importsDir + "/glob-missing.css"
t.equal(
postcss()
.use(atImport({glob: true}))
.process(fs.readFileSync(file), {from: file})
.css.trim(),
"foobar{}",
"should fail silently, skipping the globbed import, if no files found"
)

t.end()
})

test("@import sourcemap", function(t) {
t.equal(
postcss()
Expand Down