Skip to content

Commit

Permalink
Merge pull request #3 from tivac/browserify
Browse files Browse the repository at this point in the history
Add simple browserify transform
  • Loading branch information
tivac committed Nov 3, 2015
2 parents 1ade1ba + bc56a46 commit 2cc1e05
Show file tree
Hide file tree
Showing 24 changed files with 302 additions and 135 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ build/Release

# Dependency directory
node_modules
!test/specimens/**/node_modules

# Users Environment Variables
.lock-wscript
Expand Down
1 change: 1 addition & 0 deletions bin/cli.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint no-console:0 */
"use strict";

var fs = require("fs"),
Expand Down
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";

exports.process = require("./imports").process;
exports.processor = require("./src/processor");
exports.browserify = require("./src/browserify");
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
"author": "Pat Cavit <[email protected]>",
"license": "MIT",
"devDependencies": {
"browserify": "^12.0.1",
"eslint": "^1.7.3",
"eslint-config-arenanet": "^1.0.1",
"istanbul": "^0.4.0",
"jscs": "^2.5.0",
"jscs-preset-arenanet": "^1.0.0",
"mocha": "^2.3.3"
"mocha": "^2.3.3",
"mock-fs": "^3.4.0"
},
"dependencies": {
"dependency-graph": "^0.4.1",
Expand All @@ -28,7 +30,8 @@
"lodash.uniq": "^3.2.2",
"postcss": "^5.0.10",
"postcss-selector-parser": "^1.3.0",
"resolve": "^1.1.6"
"resolve": "^1.1.6",
"through2": "^2.0.0"
},
"eslintConfig": {
"extends": "arenanet",
Expand Down
39 changes: 39 additions & 0 deletions src/browserify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"use strict";

var fs = require("fs"),
path = require("path"),

through = require("through2"),
assign = require("lodash.assign"),

processor = require("./processor");

module.exports = function(file, opts) {
var options = assign({}, { extension : ".css" }, opts),
buffer;

if(path.extname(file) !== options.extension) {
return through();
}

buffer = "";

return through(
function(chunk, enc, callback) {
buffer += chunk.toString("utf8");
callback();
},

function(callback) {
var result = processor.string(file, buffer),
dest =
options.dest ||
path.join(path.dirname(file), path.basename(file, options.extension) + "-compiled.css");

fs.writeFileSync(dest, result.css, "utf8");

this.push("module.exports = " + JSON.stringify(result.exports) + ";");
callback();
}
);
};
29 changes: 29 additions & 0 deletions src/imports.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use strict";

var format = /(.+) from ["']([^'"]+?)["']$/i;

exports.format = format;

exports.match = function(text) {
return text.search(format) > -1;
};

exports.parse = function(text) {
var parts = text.match(format),
keys, source;

if(!parts) {
return false;
}

keys = parts[1].split(",");
source = parts[2];

return {
keys : keys.map(function(value) {
return value.trim();
}),

source : source
};
};
2 changes: 1 addition & 1 deletion plugins/composition.js → src/plugins/composition.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ module.exports = postcss.plugin(plugin, function() {

selectors = identifiers(decl.parent.selector);

if(decl.value.search(imports.format) > -1) {
if(imports.match(decl.value)) {
// composes: fooga, wooga from "./some-file.css"
if(!options.files) {
throw decl.error("Invalid @value reference: " + decl.value, { word : decl.value });
Expand Down
File renamed without changes.
6 changes: 3 additions & 3 deletions plugins/values.js → src/plugins/values.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function parseBase(rule) {
return out;
}

function parseImports(options, rule) {
function resolveImports(options, rule) {
var parsed = imports.parse(rule.params),
out = {},
source;
Expand Down Expand Up @@ -60,8 +60,8 @@ module.exports = postcss.plugin(plugin, function() {

if(rule.params.search(format) > -1) {
locals = parseBase(rule);
} else if(rule.params.search(imports.format) > -1) {
locals = parseImports(result.opts, rule);
} else if(imports.match(rule.params)) {
locals = resolveImports(result.opts, rule);
} else {
throw rule.error("Invalid @value declaration", { word : rule.params });
}
Expand Down
42 changes: 12 additions & 30 deletions imports.js → src/processor.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,15 @@ var fs = require("fs"),
require("./plugins/scoping.js"),
require("./plugins/composition.js")
]),
format = /(.+) from ["']([^'"]+?)["']$/i;

function parseImports(text) {
var parts = text.match(format),
keys, source;

if(!parts) {
return false;
}

keys = parts[1].split(",");
source = parts[2];

return {
keys : keys.map(function(value) {
return value.trim();
}),

source : source
};
}
imports = require("./imports");

function parseFile(env, file) {
var contents = fs.readFileSync(file, "utf8"),
basedir = path.dirname(file),
css = postcss.parse(contents, { from : file });
function parseFile(env, file, contents) {
var basedir = path.dirname(file),
css = postcss.parse(contents, { from : file });

function parse(field, rule) {
var parsed = parseImports(rule[field]),
var parsed = imports.parse(rule[field]),
source;

if(!parsed) {
Expand All @@ -61,11 +41,15 @@ function parseFile(env, file) {
css.walkDecls("composes", parse.bind(null, "value"));

env.graph.dependenciesOf(file).forEach(function(dependency) {
parseFile(env, dependency);
parseFile(env, dependency, fs.readFileSync(dependency, "utf8"));
});
}

module.exports.process = function(start) {
exports.file = function(file) {
return exports.string(file, fs.readFileSync(file, "utf8"));
};

exports.string = function(start, contents) {
var files = {},
graph = new Graph(),
source = path.resolve(start),
Expand All @@ -76,7 +60,7 @@ module.exports.process = function(start) {
parseFile({
graph : graph,
files : files
}, source);
}, source, contents);

graph.overallOrder().forEach(function(file) {
var parsed = parser.process(files[file].contents, {
Expand All @@ -102,5 +86,3 @@ module.exports.process = function(start) {
};
};

module.exports.parse = parseImports;
module.exports.format = format;
41 changes: 41 additions & 0 deletions test/_file-system.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"use strict";

module.exports = {
folder : {
"folder.css" :
"@value folder: white;\n" +
".folder { margin: 2px; }\n"
},

invalid : {
"composition.css" : ".wooga { composes: fake from \"../local.css\"; }\n",
"value.css" : "@value not-real from \"../local.css\";\n"
},

node_modules : {
"test-styles" : {
"styles.css" : ".booga { color: white; }\n"
}
},

"client.js" :
"\"use strict\";\n" +
"require(\"./start.css\");\n",

"start.css" :
"@value one, two, folder from \"./local.css\";\n" +
".wooga { composes: booga from \"./local.css\"; }\n" +
".booga { color: one; background: two; }\n" +
".tooga { border: 1px solid folder; }",

"local.css" :
"@value one: red;\n" +
"@value two: blue;\n" +
"@value folder from \"./folder/folder.css\";\n" +
".booga { background: green; }\n" +
".looga { composes: booga; }\n",

"node_modules.css" :
".wooga { composes: booga from \"test-styles/styles.css\"; }\n" +
".booga { color: one; background: two; }\n"
};
43 changes: 43 additions & 0 deletions test/browserify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use strict";

var mock = require("mock-fs"),

fs = require("fs"),
path = require("path"),
assert = require("assert"),

browserify = require("browserify"),

transform = require("../src/browserify"),

cwd = process.cwd();

describe("postcss-css-modules", function() {
describe("browserify", function() {
before(function() {
mock(require("./_file-system"));
});

after(mock.restore);

it("should run browserify", function(done) {
var build = browserify("./client.js");

build.transform(transform);

build.bundle(function(err, out) {
var js = out.toString(),
css = fs.readFileSync("./start-compiled.css", "utf8");

assert(js.indexOf("module.exports = {\"wooga\":[\"f5507abd3eea0987714c5d92c3230347_booga\"],\"booga\":[\"2ba8076ec1145293c7e3600dbc63b306_booga\"],\"tooga\":[\"2ba8076ec1145293c7e3600dbc63b306_tooga\"]};") > -1);

assert(css.indexOf(".dafdfcc7dc876084d352519086f9e6e9_folder { margin: 2px; }") > -1);
assert(css.indexOf(".f5507abd3eea0987714c5d92c3230347_booga { background: green; }") > -1);
assert(css.indexOf(".2ba8076ec1145293c7e3600dbc63b306_booga { color: red; background: blue; }") > -1);
assert(css.indexOf(".2ba8076ec1145293c7e3600dbc63b306_tooga { border: 1px solid white; }") > -1);

done();
});
});
});
});
78 changes: 29 additions & 49 deletions test/imports.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,41 @@
"use strict";

var path = require("path"),
assert = require("assert"),
var assert = require("assert"),

imports = require("../imports");
imports = require("../src/imports");

describe("postcss-css-modules", function() {
describe("imports", function() {
var start = imports.process("./test/specimens/imports/start.css");

it("should walk dependencies", function() {
assert("files" in start);

assert(path.join(__dirname, "./specimens/imports/start.css") in start.files);
assert(path.join(__dirname, "./specimens/imports/local.css") in start.files);
assert(path.join(__dirname, "./specimens/imports/folder/folder.css") in start.files);
it("should check strings for format correctness", function() {
assert(imports.match("fooga from \"/booga.css\""));
assert(imports.match("fooga from '/booga.css'"));
assert(imports.match("fooga, booga from '/booga.css'"));
});

it("should walk dependencies into node_modules", function() {
var result = imports.process("./test/specimens/imports/node_modules.css");
it("should parse strings into their pieces", function() {
assert.deepEqual(
imports.parse("fooga from \"/booga.css\""),
{
keys : [ "fooga" ],
source : "/booga.css"
}
);

assert(path.join(__dirname, "./specimens/imports/node_modules.css") in result.files);
assert(path.join(__dirname, "./specimens/imports/node_modules/test-styles/styles.css") in result.files);
});

it("should export identifiers and their classes", function() {
assert.deepEqual(start.exports, {
wooga : [ "e90a9ca9bb862787d5423d08ffa8a320_booga" ],
booga : [ "624cf273647af7597f5866483cde95d0_booga" ],
tooga : [ "624cf273647af7597f5866483cde95d0_tooga" ]
});
});

it("should generate correct css", function() {
// normalize newlines
var css = start.css.replace(/\r\n/g, "\n");

assert.equal(css.indexOf(".b5600c78a155fc10eeddec15127659a8_folder {\n margin: 2px;\n}"), 0);
assert.equal(css.indexOf(".e90a9ca9bb862787d5423d08ffa8a320_booga {\n background: green;\n}"), 63);
assert.equal(css.indexOf(".624cf273647af7597f5866483cde95d0_booga {\n color: red;\n background: blue;\n}"), 131);
assert.equal(css.indexOf(".624cf273647af7597f5866483cde95d0_tooga {\n border: 1px solid white;\n}"), 218);
});

describe("values", function() {
it("should fail if a non-existant import is referenced", function() {
assert.throws(function() {
imports.process("./test/specimens/imports/invalid-value.css");
});
});
});

describe("composition", function() {
it("should fail if a non-existant import is referenced", function() {
assert.throws(function() {
imports.process("./test/specimens/imports/invalid-composition.css");
});
});
assert.deepEqual(
imports.parse("fooga from '/booga.css'"),
{
keys : [ "fooga" ],
source : "/booga.css"
}
);

assert.deepEqual(
imports.parse("fooga, booga from '/booga.css'"),
{
keys : [ "fooga", "booga" ],
source : "/booga.css"
}
);
});
});
});
Loading

0 comments on commit 2cc1e05

Please sign in to comment.