From b77d22ec714dfd229a7156801d107e5be27282aa Mon Sep 17 00:00:00 2001 From: Damian Krzeminski Date: Thu, 27 Dec 2018 08:41:29 -0700 Subject: [PATCH 01/11] work with postcss ~5, ~6, and ~7 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c662c2b..d8e516a 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "license": "MIT", "dependencies": { "neo-async": "~2", - "postcss": "^5.0.0", + "postcss": "~5 || ~6 || ~7", "yargs": "^3.8.0" }, "devDependencies": { @@ -31,4 +31,4 @@ "bin", "lib" ] -} \ No newline at end of file +} From 6552cf44b48fdd9bee0134056062b403ed72672e Mon Sep 17 00:00:00 2001 From: Damian Krzeminski Date: Thu, 27 Dec 2018 08:46:36 -0700 Subject: [PATCH 02/11] fix Makefile dependencies --- Makefile | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 758183f..b9a6612 100644 --- a/Makefile +++ b/Makefile @@ -5,59 +5,59 @@ lint: TESTS = opts source-maps source-maps-file config config-all js-config js-config-all invalid warning - DIFF = diff -q -test: test/build \ - test-help \ +test: test-help \ test-version \ $(patsubst %,test/build/%.css,$(TESTS)) -test-help: +test-help: | test/build ./bin/postcss --help -test-version: +test-version: | test/build ./bin/postcss --version -test/build/opts.css: test/in.css +test/build/opts.css: test/in.css | test/build ./bin/postcss -u postcss-url --postcss-url.url=rebase -o $@ $< @$(DIFF) $@ $(subst build,ref,$@) -test/build/source-maps.css: test/in.css +test/build/source-maps.css: test/in.css | test/build ./bin/postcss -u postcss-url --postcss-url.url=rebase --map -o $@ $< @$(DIFF) $@ $(subst build,ref,$@) -test/build/source-maps-file.css: test/in.css +test/build/source-maps-file.css: test/in.css | test/build ./bin/postcss -u postcss-url --postcss-url.url=rebase --map file -o $@ $< @$(DIFF) $@ $(subst build,ref,$@) @$(DIFF) ${@}.map $(subst build,ref,${@}.map) -test/build/invalid.css: test/in-force-error.css +test/build/invalid.css: test/in-force-error.css | test/build ./bin/postcss --use ./test/dummy-plugin --dummy-plugin.fail=true -o $@ $< || echo Error is OK here.... -test/build/warning.css: test/in-warning.css +test/build/warning.css: test/in-warning.css | test/build ./bin/postcss --use ./test/dummy-plugin -o $@ $< && echo Warning is OK here.... -test/build/config.css: test/in.css +test/build/config.css: test/in.css | test/build ./bin/postcss -u postcss-url -c test/config.json -o $@ $< @$(DIFF) $@ $(subst build,ref,$@) -test/build/config-all.css: test/in.css +test/build/config-all.css: test/in.css | test/build ./bin/postcss -c test/config-all.json test/in.css @$(DIFF) $@ $(subst build,ref,$@) -test/build/js-config.css: test/in.css +test/build/js-config.css: test/in.css | test/build ./bin/postcss -u postcss-url -c test/config.js -o $@ $< @$(DIFF) $@ $(subst build,ref,$@) -test/build/js-config-all.css: test/in.css +test/build/js-config-all.css: test/in.css | test/build ./bin/postcss -c test/config-all.js test/in.css @$(DIFF) $@ $(subst build,ref,$@) test/build: mkdir -p $@ +.NOTPARALLEL: test/build + clean: rm -rf test/build -.PHONY: all lint clean test test-help test-version test-multi test-watch +.PHONY: all lint clean test test-help test-version From 5ef919c14742946aef34f5192ca3fd7dc8cfdfcd Mon Sep 17 00:00:00 2001 From: Damian Krzeminski Date: Thu, 27 Dec 2018 08:59:12 -0700 Subject: [PATCH 03/11] upgrade plugin used for tests --- package.json | 2 +- test/config-all.js | 2 +- test/config.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index d8e516a..fec741b 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "devDependencies": { "jshint": "^2.6.3", - "postcss-url": "^5.0.0" + "postcss-url": "^8.0.0" }, "files": [ "index.js", diff --git a/test/config-all.js b/test/config-all.js index 4f698c4..ee6ad3a 100644 --- a/test/config-all.js +++ b/test/config-all.js @@ -2,6 +2,6 @@ module.exports = { use: "postcss-url", output: "test/build/js-config-all.css", "postcss-url": { - url: function(url) { return "http://example.com/" + url; } + url: function(opts) { return "http://example.com/" + opts.url; } } }; diff --git a/test/config.js b/test/config.js index 55d72b2..38c4e77 100644 --- a/test/config.js +++ b/test/config.js @@ -1,5 +1,5 @@ module.exports = { "postcss-url": { - url: function(url) { return "http://example.com/" + url; } + url: ({ url }) => `http://example.com/${url}` } }; From 347728d747ba4b8a44c92d7c9e961c451997b845 Mon Sep 17 00:00:00 2001 From: Damian Krzeminski Date: Thu, 27 Dec 2018 09:28:17 -0700 Subject: [PATCH 04/11] replace neo-async with async use more popular library to reduce dependencies --- index.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index ec3ca6b..efc5717 100644 --- a/index.js +++ b/index.js @@ -73,7 +73,7 @@ if ('map' in argv) { commonOptions.map = argv.map; } -var async = require('neo-async'); +var async = require('async'); var fs = require('fs'); var postcss = require('postcss'); var processor = postcss(plugins); diff --git a/package.json b/package.json index fec741b..d615361 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "author": "Damian Krzeminski ", "license": "MIT", "dependencies": { - "neo-async": "~2", + "async": "~2", "postcss": "~5 || ~6 || ~7", "yargs": "^3.8.0" }, From e79a95f05ced13a6673f8f533f06cd7b031d2cc1 Mon Sep 17 00:00:00 2001 From: Damian Krzeminski Date: Thu, 27 Dec 2018 09:40:41 -0700 Subject: [PATCH 05/11] move test data to 'text/fixtures' directory --- Makefile | 30 +++++++++++++------------- test/{ => fixtures}/config-all.js | 0 test/{ => fixtures}/config-all.json | 0 test/{ => fixtures}/config.js | 0 test/{ => fixtures}/config.json | 0 test/{ => fixtures}/dummy-plugin.js | 0 test/{ => fixtures}/image.png | 0 test/{ => fixtures}/in-force-error.css | 0 test/{ => fixtures}/in-warning.css | 0 test/{ => fixtures}/in.css | 0 test/{ => fixtures}/invalid.css | 0 test/ref/opts.css | 2 +- test/ref/source-maps-file.css | 2 +- test/ref/source-maps-file.css.map | 2 +- test/ref/source-maps.css | 4 ++-- 15 files changed, 20 insertions(+), 20 deletions(-) rename test/{ => fixtures}/config-all.js (100%) rename test/{ => fixtures}/config-all.json (100%) rename test/{ => fixtures}/config.js (100%) rename test/{ => fixtures}/config.json (100%) rename test/{ => fixtures}/dummy-plugin.js (100%) rename test/{ => fixtures}/image.png (100%) rename test/{ => fixtures}/in-force-error.css (100%) rename test/{ => fixtures}/in-warning.css (100%) rename test/{ => fixtures}/in.css (100%) rename test/{ => fixtures}/invalid.css (100%) diff --git a/Makefile b/Makefile index b9a6612..40227ed 100644 --- a/Makefile +++ b/Makefile @@ -17,39 +17,39 @@ test-help: | test/build test-version: | test/build ./bin/postcss --version -test/build/opts.css: test/in.css | test/build +test/build/opts.css: test/fixtures/in.css | test/build ./bin/postcss -u postcss-url --postcss-url.url=rebase -o $@ $< @$(DIFF) $@ $(subst build,ref,$@) -test/build/source-maps.css: test/in.css | test/build +test/build/source-maps.css: test/fixtures/in.css | test/build ./bin/postcss -u postcss-url --postcss-url.url=rebase --map -o $@ $< @$(DIFF) $@ $(subst build,ref,$@) -test/build/source-maps-file.css: test/in.css | test/build +test/build/source-maps-file.css: test/fixtures/in.css | test/build ./bin/postcss -u postcss-url --postcss-url.url=rebase --map file -o $@ $< @$(DIFF) $@ $(subst build,ref,$@) @$(DIFF) ${@}.map $(subst build,ref,${@}.map) -test/build/invalid.css: test/in-force-error.css | test/build - ./bin/postcss --use ./test/dummy-plugin --dummy-plugin.fail=true -o $@ $< || echo Error is OK here.... +test/build/invalid.css: test/fixtures/in-force-error.css | test/build + ./bin/postcss --use ./test/fixtures/dummy-plugin --dummy-plugin.fail=true -o $@ $< || echo Error is OK here.... -test/build/warning.css: test/in-warning.css | test/build - ./bin/postcss --use ./test/dummy-plugin -o $@ $< && echo Warning is OK here.... +test/build/warning.css: test/fixtures/in-warning.css | test/build + ./bin/postcss --use ./test/fixtures/dummy-plugin -o $@ $< && echo Warning is OK here.... -test/build/config.css: test/in.css | test/build - ./bin/postcss -u postcss-url -c test/config.json -o $@ $< +test/build/config.css: test/fixtures/in.css | test/build + ./bin/postcss -u postcss-url -c test/fixtures/config.json -o $@ $< @$(DIFF) $@ $(subst build,ref,$@) -test/build/config-all.css: test/in.css | test/build - ./bin/postcss -c test/config-all.json test/in.css +test/build/config-all.css: test/fixtures/in.css | test/build + ./bin/postcss -c test/fixtures/config-all.json test/fixtures/in.css @$(DIFF) $@ $(subst build,ref,$@) -test/build/js-config.css: test/in.css | test/build - ./bin/postcss -u postcss-url -c test/config.js -o $@ $< +test/build/js-config.css: test/fixtures/in.css | test/build + ./bin/postcss -u postcss-url -c test/fixtures/config.js -o $@ $< @$(DIFF) $@ $(subst build,ref,$@) -test/build/js-config-all.css: test/in.css | test/build - ./bin/postcss -c test/config-all.js test/in.css +test/build/js-config-all.css: test/fixtures/in.css | test/build + ./bin/postcss -c test/fixtures/config-all.js test/fixtures/in.css @$(DIFF) $@ $(subst build,ref,$@) test/build: diff --git a/test/config-all.js b/test/fixtures/config-all.js similarity index 100% rename from test/config-all.js rename to test/fixtures/config-all.js diff --git a/test/config-all.json b/test/fixtures/config-all.json similarity index 100% rename from test/config-all.json rename to test/fixtures/config-all.json diff --git a/test/config.js b/test/fixtures/config.js similarity index 100% rename from test/config.js rename to test/fixtures/config.js diff --git a/test/config.json b/test/fixtures/config.json similarity index 100% rename from test/config.json rename to test/fixtures/config.json diff --git a/test/dummy-plugin.js b/test/fixtures/dummy-plugin.js similarity index 100% rename from test/dummy-plugin.js rename to test/fixtures/dummy-plugin.js diff --git a/test/image.png b/test/fixtures/image.png similarity index 100% rename from test/image.png rename to test/fixtures/image.png diff --git a/test/in-force-error.css b/test/fixtures/in-force-error.css similarity index 100% rename from test/in-force-error.css rename to test/fixtures/in-force-error.css diff --git a/test/in-warning.css b/test/fixtures/in-warning.css similarity index 100% rename from test/in-warning.css rename to test/fixtures/in-warning.css diff --git a/test/in.css b/test/fixtures/in.css similarity index 100% rename from test/in.css rename to test/fixtures/in.css diff --git a/test/invalid.css b/test/fixtures/invalid.css similarity index 100% rename from test/invalid.css rename to test/fixtures/invalid.css diff --git a/test/ref/opts.css b/test/ref/opts.css index 2dc689f..bf43068 100644 --- a/test/ref/opts.css +++ b/test/ref/opts.css @@ -1,4 +1,4 @@ body { - background: url(../image.png); + background: url(../fixtures/image.png); display: flex; } diff --git a/test/ref/source-maps-file.css b/test/ref/source-maps-file.css index 3f17c92..f82d959 100644 --- a/test/ref/source-maps-file.css +++ b/test/ref/source-maps-file.css @@ -1,5 +1,5 @@ body { - background: url(../image.png); + background: url(../fixtures/image.png); display: flex; } diff --git a/test/ref/source-maps-file.css.map b/test/ref/source-maps-file.css.map index 4967428..f16fbab 100644 --- a/test/ref/source-maps-file.css.map +++ b/test/ref/source-maps-file.css.map @@ -1 +1 @@ -{"version":3,"sources":["../in.css"],"names":[],"mappings":"AAAA;EACE,8BAA2B;EAC3B,cAAc;CACf","file":"source-maps-file.css","sourcesContent":["body {\n background: url(image.png);\n display: flex;\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../fixtures/in.css"],"names":[],"mappings":"AAAA;EACE,uCAA2B;EAC3B,cAAc;CACf","file":"source-maps-file.css","sourcesContent":["body {\n background: url(image.png);\n display: flex;\n}\n"]} \ No newline at end of file diff --git a/test/ref/source-maps.css b/test/ref/source-maps.css index a369c6b..16d7d59 100644 --- a/test/ref/source-maps.css +++ b/test/ref/source-maps.css @@ -1,6 +1,6 @@ body { - background: url(../image.png); + background: url(../fixtures/image.png); display: flex; } -/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2luLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLDhCQUEyQjtFQUMzQixjQUFjO0NBQ2YiLCJmaWxlIjoic291cmNlLW1hcHMuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiYm9keSB7XG4gIGJhY2tncm91bmQ6IHVybChpbWFnZS5wbmcpO1xuICBkaXNwbGF5OiBmbGV4O1xufVxuIl19 */ \ No newline at end of file +/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2ZpeHR1cmVzL2luLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLHVDQUEyQjtFQUMzQixjQUFjO0NBQ2YiLCJmaWxlIjoic291cmNlLW1hcHMuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiYm9keSB7XG4gIGJhY2tncm91bmQ6IHVybChpbWFnZS5wbmcpO1xuICBkaXNwbGF5OiBmbGV4O1xufVxuIl19 */ \ No newline at end of file From 83528b166568aa3549275aa0d379a7c587b03267 Mon Sep 17 00:00:00 2001 From: Damian Krzeminski Date: Thu, 27 Dec 2018 10:00:03 -0700 Subject: [PATCH 06/11] extract command line parsing to its own module add test for command line parsing --- .jshintrc | 3 +- Makefile | 7 +++- index.js | 51 +------------------------ lib/argv.js | 58 ++++++++++++++++++++++++++++ package.json | 6 ++- test/argv.js | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 177 insertions(+), 54 deletions(-) create mode 100644 lib/argv.js create mode 100644 test/argv.js diff --git a/.jshintrc b/.jshintrc index 0272a46..c2abaa5 100644 --- a/.jshintrc +++ b/.jshintrc @@ -4,5 +4,6 @@ "unused": true, "laxbreak": true, "laxcomma": true, - "proto": true + "proto": true, + "esversion": 6 } diff --git a/Makefile b/Makefile index 40227ed..f0ab43f 100644 --- a/Makefile +++ b/Makefile @@ -7,10 +7,15 @@ TESTS = opts source-maps source-maps-file config config-all js-config js-config- DIFF = diff -q -test: test-help \ +test: \ + test-unit \ + test-help \ test-version \ $(patsubst %,test/build/%.css,$(TESTS)) +test-unit: + ./node_modules/.bin/mocha --require should + test-help: | test/build ./bin/postcss --help diff --git a/index.js b/index.js index efc5717..9f6706f 100644 --- a/index.js +++ b/index.js @@ -1,53 +1,4 @@ -var yargs = require('yargs'); -var argv = yargs - .usage('Usage: $0 -use plugin [--config|-c config.json] [--output|-o output.css] [input.css]') - .example('postcss --use autoprefixer -c options.json -o screen.css screen.css', - 'Use autoprefixer as a postcss plugin') - .example('postcss --use autoprefixer --autoprefixer.browsers "> 5%" -o screen.css screen.css', - 'Pass plugin parameters in plugin.option notation') - .config('c') - .alias('c', 'config') - .describe('c', 'JSON file with plugin configuration') - .alias('u', 'use') - .describe('u', 'postcss plugin name (can be used multiple times)') - .alias('o', 'output') - .describe('o', 'Output file') - .alias('m', 'map') - .describe('m', 'Source map') - .alias('s', 'syntax') - .describe('s', 'Alternative input syntax parser') - .alias('p', 'parser') - .describe('p', 'Alternative CSS parser') - .alias('t', 'stringifier') - .describe('t', 'Alternative output stringifier') - .requiresArg(['u', 'c', 'o', 's', 'p', 't']) - .version(function() { - return [ - 'postcss version', - require('./node_modules/postcss/package.json').version - ].join(' '); - }, 'v') - .alias('v', 'version') - .help('h') - .alias('h', 'help') - .demand(1, 1, 'Please specify a single input file.') - .check(function(argv) { - if (!argv.use) { - throw 'Please specify at least one plugin name.'; - } - return true; - }) - .wrap(Math.max(yargs.terminalWidth() - 5, 60)) - .argv; - -if (!Array.isArray(argv.use)) { - argv.use = [argv.use]; -} - -if (argv.map === 'file') { - // treat `--map file` as `--no-map.inline` - argv.map = { inline: false }; -} +var argv = require('./lib/argv')(); // load and configure plugin array var plugins = argv.use.map(function(name) { diff --git a/lib/argv.js b/lib/argv.js new file mode 100644 index 0000000..4057f7b --- /dev/null +++ b/lib/argv.js @@ -0,0 +1,58 @@ +const yargs = require('yargs'); + +module.exports = parse; + +function parse(options = process.argv.slice(2)) { + let argv = yargs + .usage('Usage: $0 -use plugin [--config|-c config.json] [--output|-o output.css] [input.css]') + .example('postcss --use autoprefixer -c options.json -o screen.css screen.css', + 'Use autoprefixer as a postcss plugin') + .example('postcss --use autoprefixer --autoprefixer.browsers "> 5%" -o screen.css screen.css', + 'Pass plugin parameters in plugin.option notation') + .config('c') + .alias('c', 'config') + .describe('c', 'JSON file with plugin configuration') + .alias('u', 'use') + .describe('u', 'postcss plugin name (can be used multiple times)') + .alias('o', 'output') + .describe('o', 'Output file') + .alias('m', 'map') + .describe('m', 'Source map') + .alias('s', 'syntax') + .describe('s', 'Alternative input syntax parser') + .alias('p', 'parser') + .describe('p', 'Alternative CSS parser') + .alias('t', 'stringifier') + .describe('t', 'Alternative output stringifier') + .requiresArg(['u', 'c', 'o', 's', 'p', 't']) + .version(function() { + return [ + 'postcss version', + require('../node_modules/postcss/package.json').version + ].join(' '); + }, 'v') + .alias('v', 'version') + .help('h') + .alias('h', 'help') + .demand(1, 1, 'Please specify a single input file.') + .check(function(argv) { + if (!argv.use) { + throw 'Please specify at least one plugin name.'; + } + return true; + }) + .wrap(Math.max(yargs.terminalWidth() - 5, 60)) + .parse(options); + + if (!Array.isArray(argv.use)) { + argv.use = [argv.use]; + } + + if (argv.map === 'file') { + // treat `--map file` as `--no-map.inline` + argv.map = { inline: false }; + } + + return argv; +} + diff --git a/package.json b/package.json index d615361..d4375c9 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,10 @@ "yargs": "^3.8.0" }, "devDependencies": { - "jshint": "^2.6.3", - "postcss-url": "^8.0.0" + "jshint": "~2", + "mocha": "~5", + "postcss-url": "^8.0.0", + "should": "~13" }, "files": [ "index.js", diff --git a/test/argv.js b/test/argv.js new file mode 100644 index 0000000..cd03cd7 --- /dev/null +++ b/test/argv.js @@ -0,0 +1,106 @@ +const should = require('should'); +const argv = require('../lib/argv'); + + +// trim and split as a bad approximation of converting commang line into array of strings +function _(strings) { + return strings[0].trim().split(/\s+/); +} + +/* global describe, it, beforeEach */ + +describe('argv', function() { + + beforeEach(function() { + require('yargs').reset(); + }); + + it('single plugin', function() { + const opts = argv(_`--use autoprefixer -o out.css in.css`); + opts.should.have.property('use', [ 'autoprefixer' ]); + opts.should.have.property('output', 'out.css'); + opts.should.have.property('_', [ 'in.css' ]); + + should(opts.version).not.be.ok(); + should(opts.help).not.be.ok(); + }); + + it('syntax', function() { + const opts = argv(_` + --use autoprefixer + -s mysyntax + --output out.css + in.css + `); + + opts.should.have.property('syntax', 'mysyntax'); + }); + + it('parser', function() { + const opts = argv(_` + --use autoprefixer + -p myparser + --output out.css + in.css + `); + + opts.should.have.property('parser', 'myparser'); + }); + + it('stringifier', function() { + const opts = argv(_` + --use autoprefixer + --stringifier mystringifier + --output out.css + in.css + `); + + opts.should.have.property('stringifier', 'mystringifier'); + }); + + it('config .json', function() { + const opts = argv(_`--config test/fixtures/config-all.json in.css`); + opts.should.containEql({ + use: [ 'postcss-url' ], + output: 'test/build/config-all.css', + 'postcss-url': { + url: 'inline' + } + }); + }); + + it('config .js', function() { + const opts = argv(_` + --use postcss-url + --output out.css + --config test/fixtures/config.js + in.css + `); + opts.should.containEql({ + use: [ 'postcss-url' ], + output: 'out.css' + }); + opts.should + .have.property('postcss-url') + .with.property('url') + .Function(); + }); + + it('multiple plugins with options', function() { + const opts = argv(_` + --use postcss-url --postcss-url.url=rebase --postcss-url.assetPath /temp/example + --use autoprefixer --autoprefixer.browsers >5% + --use cssnano --no-cssnano.discardUnused + --output out.css in.css + `); + + opts.should.have.property('use', [ 'postcss-url', 'autoprefixer', 'cssnano' ]); + opts.should.have.property('output', 'out.css'); + opts.should.have.property('_', [ 'in.css' ]); + + opts.should.have.property('postcss-url', { url: 'rebase', assetPath: '/temp/example' }); + opts.should.have.property('autoprefixer', { browsers: '>5%' }); + opts.should.have.property('cssnano', { discardUnused: false }); + }); + +}); From 9a81138f741d991870330764889c59ba06bba3f4 Mon Sep 17 00:00:00 2001 From: Damian Krzeminski Date: Thu, 27 Dec 2018 17:34:30 -0700 Subject: [PATCH 07/11] replace yargs with yargs-parser we just need a simple options parsing module here --- index.js | 4 ++ lib/argv.js | 133 ++++++++++++++++++++++++++++++++------------------- package.json | 2 +- test/argv.js | 6 +-- 4 files changed, 91 insertions(+), 54 deletions(-) diff --git a/index.js b/index.js index 9f6706f..b3f81a3 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,9 @@ var argv = require('./lib/argv')(); +if (typeof argv === 'number') { + process.exit(argv); +} + // load and configure plugin array var plugins = argv.use.map(function(name) { var plugin = require(name); diff --git a/lib/argv.js b/lib/argv.js index 4057f7b..75cf877 100644 --- a/lib/argv.js +++ b/lib/argv.js @@ -1,56 +1,93 @@ -const yargs = require('yargs'); +const yargsParser = require('yargs-parser'); module.exports = parse; -function parse(options = process.argv.slice(2)) { - let argv = yargs - .usage('Usage: $0 -use plugin [--config|-c config.json] [--output|-o output.css] [input.css]') - .example('postcss --use autoprefixer -c options.json -o screen.css screen.css', - 'Use autoprefixer as a postcss plugin') - .example('postcss --use autoprefixer --autoprefixer.browsers "> 5%" -o screen.css screen.css', - 'Pass plugin parameters in plugin.option notation') - .config('c') - .alias('c', 'config') - .describe('c', 'JSON file with plugin configuration') - .alias('u', 'use') - .describe('u', 'postcss plugin name (can be used multiple times)') - .alias('o', 'output') - .describe('o', 'Output file') - .alias('m', 'map') - .describe('m', 'Source map') - .alias('s', 'syntax') - .describe('s', 'Alternative input syntax parser') - .alias('p', 'parser') - .describe('p', 'Alternative CSS parser') - .alias('t', 'stringifier') - .describe('t', 'Alternative output stringifier') - .requiresArg(['u', 'c', 'o', 's', 'p', 't']) - .version(function() { - return [ - 'postcss version', - require('../node_modules/postcss/package.json').version - ].join(' '); - }, 'v') - .alias('v', 'version') - .help('h') - .alias('h', 'help') - .demand(1, 1, 'Please specify a single input file.') - .check(function(argv) { - if (!argv.use) { - throw 'Please specify at least one plugin name.'; - } - return true; - }) - .wrap(Math.max(yargs.terminalWidth() - 5, 60)) - .parse(options); - - if (!Array.isArray(argv.use)) { - argv.use = [argv.use]; +const parserConfig = { + alias: { + config: 'c', + use: 'u', + output: 'o', + map: 'm', + syntax: 's', + parser: 'p', + stringifier: 't', + version: 'v', + help: 'h', + }, + array: [ 'use' ], + + config: 'config', + + nargs: { + config: 1, + use: 1, + output: 1, + syntax: 1, + parser: 1, + stringifier: 1, + }, + + boolean: ['version', 'help'], + + coerce: { + map: v => v === 'file' ? { inline: false } : v + } +}; + +function version() { + const { version } = require('postcss/package.json'); + return `postcss version: ${ version }`; +} + +function usage() { + return ` +Usage: + node_modules/.bin/postcss -use plugin [--config|-c config.json] [--output|-o output.css] input.css + +Options: + -c, --config JSON file with plugin configuration + -u, --use postcss plugin name (can be used multiple times) + -o, --output Output file + -m, --map Source map + -s, --syntax Alternative input syntax parser + -p, --parser Alternative CSS parser + -t, --stringifier Alternative output stringifier + -v, --version Show version number + -h, --help Show help + +Examples: + +# use autoprefixer as a postcss plugin: +postcss --use autoprefixer -c options.json -o screen.css screen.css + +# pass plugin parameters in plugin.option notation +postcss --use autoprefixer --autoprefixer.browsers "> 5%" -o screen.css screen.css +`; +} + +function parse(args = process.argv.slice(2)) { + let argv = yargsParser(args, parserConfig); + + if (argv.version) { + console.log(version()); + return 0; + } + + if (argv.help) { + console.log(usage()); + return 0; + } + + if (!argv.use) { + console.log(usage()); + console.error('Please specify at least one plugin name.'); + return 1; } - if (argv.map === 'file') { - // treat `--map file` as `--no-map.inline` - argv.map = { inline: false }; + if (argv._.length !== 1) { + console.log(usage()); + console.error('Please specify a single input file.'); + return 1; } return argv; diff --git a/package.json b/package.json index d4375c9..5840c4c 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "async": "~2", "postcss": "~5 || ~6 || ~7", - "yargs": "^3.8.0" + "yargs-parser": "~11" }, "devDependencies": { "jshint": "~2", diff --git a/test/argv.js b/test/argv.js index cd03cd7..b21732a 100644 --- a/test/argv.js +++ b/test/argv.js @@ -7,14 +7,10 @@ function _(strings) { return strings[0].trim().split(/\s+/); } -/* global describe, it, beforeEach */ +/* global describe, it */ describe('argv', function() { - beforeEach(function() { - require('yargs').reset(); - }); - it('single plugin', function() { const opts = argv(_`--use autoprefixer -o out.css in.css`); opts.should.have.property('use', [ 'autoprefixer' ]); From 9ff6cc3e93000a0bc9ac55ab3ed10a68837029c8 Mon Sep 17 00:00:00 2001 From: Damian Krzeminski Date: Thu, 27 Dec 2018 18:25:48 -0700 Subject: [PATCH 08/11] extract running postcss to a separate module --- Makefile | 4 +-- index.js | 92 +++++------------------------------------------------- lib/run.js | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 87 deletions(-) create mode 100644 lib/run.js diff --git a/Makefile b/Makefile index f0ab43f..393af77 100644 --- a/Makefile +++ b/Makefile @@ -36,10 +36,10 @@ test/build/source-maps-file.css: test/fixtures/in.css | test/build @$(DIFF) ${@}.map $(subst build,ref,${@}.map) test/build/invalid.css: test/fixtures/in-force-error.css | test/build - ./bin/postcss --use ./test/fixtures/dummy-plugin --dummy-plugin.fail=true -o $@ $< || echo Error is OK here.... + NODE_PATH=./test/fixtures ./bin/postcss --use dummy-plugin --dummy-plugin.fail=true -o $@ $< || echo Error is OK here.... test/build/warning.css: test/fixtures/in-warning.css | test/build - ./bin/postcss --use ./test/fixtures/dummy-plugin -o $@ $< && echo Warning is OK here.... + NODE_PATH=./test/fixtures ./bin/postcss --use dummy-plugin -o $@ $< && echo Warning is OK here.... test/build/config.css: test/fixtures/in.css | test/build ./bin/postcss -u postcss-url -c test/fixtures/config.json -o $@ $< diff --git a/index.js b/index.js index b3f81a3..f1298dd 100644 --- a/index.js +++ b/index.js @@ -1,88 +1,10 @@ -var argv = require('./lib/argv')(); +const argv = require('./lib/argv'); +const run = require('./lib/run'); -if (typeof argv === 'number') { - process.exit(argv); -} - -// load and configure plugin array -var plugins = argv.use.map(function(name) { - var plugin = require(name); - if (name in argv) { - plugin = plugin(argv[name]); - } else { - plugin = plugin.postcss || plugin(); - } - return plugin; -}); - -var commonOptions = ['syntax', 'parser', 'stringifier'] - .reduce(function(cso, opt) { - if (argv[opt]) { - cso[opt] = require(argv[opt]); - } - return cso; - }, Object.create(null)); - - -if ('map' in argv) { - commonOptions.map = argv.map; -} - -var async = require('async'); -var fs = require('fs'); -var postcss = require('postcss'); -var processor = postcss(plugins); - -// this is where magic happens -processCSS(processor, argv._[0], argv.output, dumpErrors); - -function processCSS(processor, input, output, fn) { - function doProcess(css, fn) { - var options = { - from: input, - to: output - }; - - Object.keys(commonOptions).forEach(function(opt) { - options[opt] = commonOptions[opt]; - }); - - processor - .process(css, options) - .then(function(result) { fn(null, result); }) - .catch(fn); - } - - async.waterfall([ - async.apply(fs.readFile, input), - doProcess, - async.apply(dumpWarnings), - async.apply(writeResult, output) - ], fn); -} - -function dumpWarnings(result, fn) { - result.warnings().forEach(function(w) { console.warn(w.toString()); }); - fn(null, result); -} - -function dumpErrors(err) { - if (!err) { - return; - } - if (err.message && typeof err.showSourceCode === 'function') { - console.error(err.message, err.showSourceCode()); - } else { - console.error(err); - } -} +const args = argv(); -function writeResult (name, content, fn) { - var funcs = [ - async.apply(fs.writeFile, name, content.css) - ]; - if (content.map) { - funcs.push(async.apply(fs.writeFile, name + '.map', content.map.toString())); - } - async.parallel(funcs, fn); +if (typeof args === 'number') { + process.exit(args); +} else { + run(args, exitCode => process.exit(exitCode)); } diff --git a/lib/run.js b/lib/run.js new file mode 100644 index 0000000..6378a2f --- /dev/null +++ b/lib/run.js @@ -0,0 +1,88 @@ +const { waterfall, parallel } = require('async'); +const { readFile, writeFile } = require('fs'); +const postcss = require('postcss'); + +module.exports = run; + +function run(argv, fn) { + + // load and configure plugin array + const plugins = argv.use.map(name => { + let plugin = require(name); + if (name in argv) { + plugin = plugin(argv[name]); + } else { + plugin = plugin.postcss || plugin(); + } + return plugin; + }); + + const commonOptions = [ + 'syntax', + 'parser', + 'stringifier' + ].reduce((cso, opt) => { + if (argv[opt]) { + cso[opt] = require(argv[opt]); + } + return cso; + }, Object.create(null)); + + if ('map' in argv) { + commonOptions.map = argv.map; + } + + const processor = postcss(plugins); + const from = argv._[0]; + const to = argv.output; + + // this is where magic happens + processCSS(processor, { from, to, commonOptions }, err => { + if (err) dumpErrors(err); + fn(err ? 1 : 0); + }); +} + +function processCSS(processor, { from, to, commonOptions }, fn) { + + function doProcess(css, fn) { + const options = Object.assign({ from, to }, commonOptions); + + processor + .process(css, options) + .then(result => fn(null, result)) + .catch(fn); + } + + waterfall([ + fn => readFile(from, fn), + doProcess, + (result, fn) => dumpWarnings(result, fn), + (result, fn) => writeResult(to, result, fn) + ], fn); +} + +function dumpWarnings(result, fn) { + result.warnings().forEach(w => console.warn(w.toString())); + fn(null, result); +} + +function dumpErrors(err) { + if (err.message && typeof err.showSourceCode === 'function') { + console.error(err.message, err.showSourceCode()); + } else { + console.error(err); + } +} + +function writeResult(name, { css, map }, fn) { + const funcs = [ + fn => writeFile(name, css, fn) + ]; + if (map) { + funcs.push( + fn => writeFile(`${name}.map`, map.toString(), fn) + ); + } + parallel(funcs, fn); +} From 24bfbcc285e6675bf76858d85e1e29309d95aa74 Mon Sep 17 00:00:00 2001 From: Damian Krzeminski Date: Thu, 27 Dec 2018 19:09:57 -0700 Subject: [PATCH 09/11] updated Travis CI config only test on stable and LTS version of node --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 41edd3f..15dc198 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ sudo: false language: node_js node_js: - - "stable" - - "4" + - "node" + - "lts/*" From 56be95e4cbe404d83874b3b7c3fbd66813166bfc Mon Sep 17 00:00:00 2001 From: Damian Krzeminski Date: Thu, 27 Dec 2018 19:36:11 -0700 Subject: [PATCH 10/11] update badges in Readme --- Readme.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 5d5fb74..524068e 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,7 @@ -[![Build Status](https://img.shields.io/travis/pirxpilot/postcss-cli.svg)](http://travis-ci.org/pirxpilot/postcss-cli) -[![Dependency Status](https://img.shields.io/gemnasium/pirxpilot/postcss-cli.svg)](https://gemnasium.com/pirxpilot/postcss-cli) -[![NPM version](https://img.shields.io/npm/v/postcss-cli-simple.svg)](http://badge.fury.io/js/postcss-cli-simple) +[![NPM version][npm-image]][npm-url] +[![Build Status][travis-image]][travis-url] +[![Dependency Status][deps-image]][deps-url] +[![Dev Dependency Status][deps-dev-image]][deps-dev-url] # postcss-cli-simple @@ -131,3 +132,16 @@ MIT [pattern rules]: https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html [yargs dot notation]: https://www.npmjs.com/package/yargs#dot-notation [yargs boolean negation]: https://www.npmjs.com/package/yargs#negate-fields + + +[npm-image]: https://img.shields.io/npm/v/postcss-cli-simple.svg +[npm-url]: https://npmjs.org/package/postcss-cli-simple + +[travis-url]: https://travis-ci.org/pirxpilot/postcss-cli +[travis-image]: https://img.shields.io/travis/pirxpilot/postcss-cli.svg + +[deps-image]: https://img.shields.io/david/pirxpilot/postcss-cli.svg +[deps-url]: https://david-dm.org/pirxpilot/postcss-cli + +[deps-dev-image]: https://img.shields.io/david/dev/pirxpilot/postcss-cli.svg +[deps-dev-url]: https://david-dm.org/pirxpilot/postcss-cli?type=dev From 93e8181d91c90866ae239306f87ff74641f6b57b Mon Sep 17 00:00:00 2001 From: Damian Krzeminski Date: Thu, 27 Dec 2018 19:41:39 -0700 Subject: [PATCH 11/11] Release 3.0.0 --- History.md | 8 ++++++++ package.json | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index c579e15..722233d 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,12 @@ +3.0.0 / 2018-12-27 +================== + + * rewrite in ES6 + * replace yargs with yargs-parser + * replace neo-async with async + * work with postcss ~5, ~6, and ~7 + 1.0.4 / 2017-02-19 ================== diff --git a/package.json b/package.json index 5840c4c..25f4725 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "postcss-cli-simple", - "version": "1.0.4", + "version": "3.0.0", "description": "simple CLI for postcss", "main": "index.js", "bin": { @@ -33,4 +33,4 @@ "bin", "lib" ] -} +} \ No newline at end of file