From f947959e1acd3de9c69764e97109e30b1087c1ac Mon Sep 17 00:00:00 2001 From: Ryan Zimmerman Date: Thu, 23 Sep 2021 21:00:32 -0400 Subject: [PATCH] Port to ESM --- .eslintrc.yaml | 2 + bin/postcss | 3 -- index.js | 90 ++++++++++++++++++++----------------- lib/DependencyGraph.js | 7 ++- lib/DependencyGraph.test.js | 7 ++- lib/args.js | 8 ++-- lib/getMapfile.js | 5 +-- lib/getMapfile.test.js | 27 +++++++++++ package.json | 8 ++-- test/error.js | 6 +-- test/helpers/cli.js | 2 +- test/map.js | 27 ----------- test/stdin.js | 2 +- test/stdout.js | 2 +- test/watch.js | 21 ++++----- 15 files changed, 110 insertions(+), 107 deletions(-) delete mode 100755 bin/postcss mode change 100644 => 100755 index.js create mode 100644 lib/getMapfile.test.js diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 0473b0f..d838ba7 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -1,5 +1,7 @@ env: node: true +parserOptions: + sourceType: module extends: problems rules: no-console: off diff --git a/bin/postcss b/bin/postcss deleted file mode 100755 index d40abef..0000000 --- a/bin/postcss +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env node - -require('../') diff --git a/index.js b/index.js old mode 100644 new mode 100755 index 21704bb..da83943 --- a/index.js +++ b/index.js @@ -1,23 +1,25 @@ -'use strict' - -const fs = require('fs-extra') -const path = require('path') - -const prettyHrtime = require('pretty-hrtime') -const stdin = require('get-stdin') -const read = require('read-cache') -const { bold, dim, red, cyan, green } = require('colorette') -const globber = require('globby') -const slash = require('slash') -const chokidar = require('chokidar') - -const postcss = require('postcss') -const postcssrc = require('postcss-load-config') -const reporter = require('postcss-reporter/lib/formatter')() - -const argv = require('./lib/args') -const createDependencyGraph = require('./lib/DependencyGraph') -const getMapfile = require('./lib/getMapfile') +#!/usr/bin/env node + +import fs from 'fs-extra' +import path from 'path' + +import prettyHrtime from 'pretty-hrtime' +import stdin from 'get-stdin' +import read from 'read-cache' +import { bold, dim, red, cyan, green } from 'colorette' +import globber from 'globby' +import slash from 'slash' +import chokidar from 'chokidar' + +import postcss from 'postcss' +import postcssrc from 'postcss-load-config' +import postcssReporter from 'postcss-reporter/lib/formatter.js' + +import argv from './lib/args.js' +import createDependencyGraph from './lib/DependencyGraph.js' +import getMapfile from './lib/getMapfile.js' + +const reporter = postcssReporter() const depGraph = createDependencyGraph() let input = argv._ @@ -25,25 +27,33 @@ const { dir, output } = argv if (argv.map) argv.map = { inline: false } -const cliConfig = { - options: { - map: argv.map !== undefined ? argv.map : { inline: true }, - parser: argv.parser ? require(argv.parser) : undefined, - syntax: argv.syntax ? require(argv.syntax) : undefined, - stringifier: argv.stringifier ? require(argv.stringifier) : undefined, - }, - plugins: argv.use - ? argv.use.map((plugin) => { - try { - return require(plugin)() - } catch (e) { - const msg = e.message || `Cannot find module '${plugin}'` - let prefix = msg.includes(plugin) ? '' : ` (${plugin})` - if (e.name && e.name !== 'Error') prefix += `: ${e.name}` - return error(`Plugin Error${prefix}: ${msg}'`) - } - }) - : [], +let cliConfig + +async function buildCliConfig() { + cliConfig = { + options: { + map: argv.map !== undefined ? argv.map : { inline: true }, + parser: argv.parser ? await import(argv.parser) : undefined, + syntax: argv.syntax ? await import(argv.syntax) : undefined, + stringifier: argv.stringifier + ? await import(argv.stringifier) + : undefined, + }, + plugins: argv.use + ? await Promise.all( + argv.use.map(async (plugin) => { + try { + return (await import(plugin)).default() + } catch (e) { + const msg = e.message || `Cannot find module '${plugin}'` + let prefix = msg.includes(plugin) ? '' : ` (${plugin})` + if (e.name && e.name !== 'Error') prefix += `: ${e.name}` + return error(`Plugin Error${prefix}: ${msg}'`) + } + }) + ) + : [], + } } let configFile @@ -61,7 +71,7 @@ if (parseInt(postcss().version) < 8) { error('Please install PostCSS 8 or above') } -Promise.resolve() +buildCliConfig() .then(() => { if (argv.watch && !(argv.output || argv.replace || argv.dir)) { error('Cannot write to stdout in watch mode') diff --git a/lib/DependencyGraph.js b/lib/DependencyGraph.js index c293cda..efb7ac3 100644 --- a/lib/DependencyGraph.js +++ b/lib/DependencyGraph.js @@ -1,8 +1,7 @@ -'use strict' -const path = require('path') -const { DepGraph } = require('dependency-graph') +import path from 'path' +import { DepGraph } from 'dependency-graph' -module.exports = function () { +export default function createDependencyGraph() { const graph = new DepGraph() return { add(message) { diff --git a/lib/DependencyGraph.test.js b/lib/DependencyGraph.test.js index a0235ba..d54393c 100644 --- a/lib/DependencyGraph.test.js +++ b/lib/DependencyGraph.test.js @@ -1,7 +1,6 @@ -'use strict' -const test = require('ava') -const path = require('path') -const createDependencyGraph = require('./DependencyGraph.js') +import test from 'ava' +import path from 'path' +import createDependencyGraph from './DependencyGraph.js' function resolveArray(arr) { return arr.map((p) => path.resolve(p)) diff --git a/lib/args.js b/lib/args.js index e25dd0d..fb38937 100644 --- a/lib/args.js +++ b/lib/args.js @@ -1,5 +1,5 @@ -'use strict' -const { bold, red } = require('colorette') +import yargs from 'yargs' +import { bold, red } from 'colorette' const logo = ` /|\\ @@ -13,7 +13,7 @@ const logo = ` //_____||___*_________*___||_____// ` -const { argv } = require('yargs') +const { argv } = yargs(process.argv.slice(2)) .usage( `${bold(red(logo))} Usage: @@ -126,4 +126,4 @@ For more details, please see https://github.com/postcss/postcss-cli` if (argv.ext && argv.ext.indexOf('.') !== 0) argv.ext = `.${argv.ext}` -module.exports = argv +export default argv diff --git a/lib/getMapfile.js b/lib/getMapfile.js index 346fea7..e4d0c93 100644 --- a/lib/getMapfile.js +++ b/lib/getMapfile.js @@ -1,6 +1,5 @@ -'use strict' -const path = require('path') -module.exports = function getMapfile(options) { +import path from 'path' +export default function getMapfile(options) { if (options.map && typeof options.map.annotation === 'string') { return `${path.dirname(options.to)}/${options.map.annotation}` } diff --git a/lib/getMapfile.test.js b/lib/getMapfile.test.js new file mode 100644 index 0000000..becc460 --- /dev/null +++ b/lib/getMapfile.test.js @@ -0,0 +1,27 @@ +import test from 'ava' +import getMapfile from './getMapfile.js' + +test('mapFile path is properly resolved', async (t) => { + const paths = [ + { + input: { to: '/foo/bar.css/baz/index.css' }, + want: '/foo/bar.css/baz/index.css.map', + }, + { + input: { to: '/foo/bar.sss/baz/index.sss' }, + want: '/foo/bar.sss/baz/index.sss.map', + }, + { + input: { to: '/foo/bar.css/baz/bar.css' }, + want: '/foo/bar.css/baz/bar.css.map', + }, + { + input: { map: { annotation: 'foo.map' }, to: '/foo/bar.css/baz/bar.css' }, + want: '/foo/bar.css/baz/foo.map', + }, + ] + + for (const p of paths) { + t.is(getMapfile(p.input), p.want) + } +}) diff --git a/package.json b/package.json index a235e25..60350bd 100644 --- a/package.json +++ b/package.json @@ -2,12 +2,12 @@ "name": "postcss-cli", "version": "8.3.1", "description": "CLI for PostCSS", - "main": "index.js", + "type": "module", "engines": { "node": ">=12" }, "bin": { - "postcss": "./bin/postcss" + "postcss": "./index.js" }, "scripts": { "ci": "eslint . && nyc ava -v && npm run prettier -- --list-different", @@ -15,7 +15,7 @@ "prettier": "prettier --single-quote --no-semi \"**/*.{js,md}\"", "format": "npm run prettier -- --write && eslint . --fix", "pretest": "npm run clean && npm run format", - "test": "nyc ava -v" + "test": "c8 ava -v" }, "dependencies": { "chokidar": "^3.3.0", @@ -33,10 +33,10 @@ }, "devDependencies": { "ava": "^3.1.0", + "c8": "^7.9.0", "coveralls": "^3.0.0", "eslint": "^7.8.0", "eslint-config-problems": "5.0.0", - "nyc": "^15.0.0", "postcss": "^8.0.4", "postcss-import": "^14.0.0", "prettier": "~2.4.0", diff --git a/test/error.js b/test/error.js index 38b972b..4309023 100644 --- a/test/error.js +++ b/test/error.js @@ -34,7 +34,7 @@ test('plugin not found', (t) => { t.is(code, 1, 'expected non-zero error code') t.regex( error.toString(), - /Plugin Error: Cannot find module 'postcss-plugin'/ + /Plugin Error: Cannot find package 'postcss-plugin'/ ) } ) @@ -44,12 +44,12 @@ test('plugin throws on require', (t) => { return cli([ 'test/fixtures/a.css', '-u', - './test/fixtures/_bad-plugin', + './test/fixtures/_bad-plugin.js', '-o', tmp(), ]).then(({ error, code }) => { t.is(code, 1, 'expected non-zero error code') - t.regex(error.toString(), /Plugin Error \(.*bad-plugin\): This fails/) + t.regex(error.toString(), /Plugin Error \(.*bad-plugin.js\): This fails/) }) }) diff --git a/test/helpers/cli.js b/test/helpers/cli.js index 64b9154..c189e00 100644 --- a/test/helpers/cli.js +++ b/test/helpers/cli.js @@ -5,7 +5,7 @@ const { exec } = require('child_process') module.exports = function (args, cwd) { return new Promise((resolve) => { exec( - `node ${path.resolve('bin/postcss')} ${args.join(' ')}`, + `node ${path.resolve('index.js')} ${args.join(' ')}`, { cwd }, (error, stdout, stderr) => { resolve({ diff --git a/test/map.js b/test/map.js index 04f90fd..8e98b61 100644 --- a/test/map.js +++ b/test/map.js @@ -6,8 +6,6 @@ const cli = require('./helpers/cli.js') const tmp = require('./helpers/tmp.js') const read = require('./helpers/read.js') -const getMapfile = require('../lib/getMapfile') - test('inline maps are generated by default', async (t) => { const output = tmp('output.css') @@ -56,28 +54,3 @@ test('--no-map disables internal sourcemaps', async (t) => { t.notRegex(await read(output), /\/*# sourceMappingURL=/) }) - -test('mapFile path is property resolved', async (t) => { - const paths = [ - { - input: { to: '/foo/bar.css/baz/index.css' }, - want: '/foo/bar.css/baz/index.css.map', - }, - { - input: { to: '/foo/bar.sss/baz/index.sss' }, - want: '/foo/bar.sss/baz/index.sss.map', - }, - { - input: { to: '/foo/bar.css/baz/bar.css' }, - want: '/foo/bar.css/baz/bar.css.map', - }, - { - input: { map: { annotation: 'foo.map' }, to: '/foo/bar.css/baz/bar.css' }, - want: '/foo/bar.css/baz/foo.map', - }, - ] - - for (const p of paths) { - t.is(getMapfile(p.input), p.want) - } -}) diff --git a/test/stdin.js b/test/stdin.js index 8709a94..962e678 100644 --- a/test/stdin.js +++ b/test/stdin.js @@ -12,7 +12,7 @@ test.cb('reads from stdin', (t) => { const output = tmp('output.css') const cp = exec( - `node ${path.resolve('bin/postcss')} -o ${output} --no-map`, + `node ${path.resolve('index.js')} -o ${output} --no-map`, (error, stdout, stderr) => { if (error) t.end(error, stderr) diff --git a/test/stdout.js b/test/stdout.js index 8bd5d7b..1a14270 100644 --- a/test/stdout.js +++ b/test/stdout.js @@ -10,7 +10,7 @@ const read = require('./helpers/read.js') test.cb('writes to stdout', (t) => { const cp = exec( `node ${path.resolve( - 'bin/postcss' + 'index.js' )} --parser sugarss -u postcss-import --no-map`, (error, stdout, stderr) => { if (error) t.end(error, stderr) diff --git a/test/watch.js b/test/watch.js index 3bc8368..8c490eb 100644 --- a/test/watch.js +++ b/test/watch.js @@ -51,9 +51,7 @@ testCb('--watch works', (t) => { watcher.on('ready', () => { // Using exec() and quoting "*.css" to test watch's glob handling: cp = exec( - `node ${path.resolve( - 'bin/postcss' - )} "*.css" -o output.css --no-map -w`, + `node ${path.resolve('index.js')} "*.css" -o output.css --no-map -w`, { cwd: dir } ) cp.on('error', t.end) @@ -121,7 +119,7 @@ testCb('--watch dependencies', (t) => { watcher.on('ready', () => { cp = exec( `node ${path.resolve( - 'bin/postcss' + 'index.js' )} import.css -o output.css -u postcss-import -w --no-map`, { cwd: dir } ) @@ -172,7 +170,7 @@ testCb("--watch doesn't exit on CssSyntaxError", (t) => { let killed = false const cp = exec( - `node ${path.resolve('bin/postcss')} a.css -o output.css -w --no-map`, + `node ${path.resolve('index.js')} a.css -o output.css -w --no-map`, { cwd: dir } ) cp.on('error', t.end) @@ -207,10 +205,9 @@ testCb("--watch doesn't exit on CssSyntaxError", (t) => { testCb('--watch does exit on closing stdin (Ctrl-D/EOF)', (t) => { t.plan(1) - const cp = spawn( - `./bin/postcss test/fixtures/a.css -o ${tmp()} -w --no-map`, - { shell: true } - ) + const cp = spawn(`./index.js test/fixtures/a.css -o ${tmp()} -w --no-map`, { + shell: true, + }) cp.on('error', t.end) cp.on('exit', (code) => { @@ -281,7 +278,7 @@ testCb('--watch watches dependencies', (t) => { // Using exec() and quoting "*.css" to test watch's glob handling: cp = exec( `node ${path.resolve( - 'bin/postcss' + 'index.js' )} "s.css" -o output.css --no-map -w`, { cwd: dir } ) @@ -382,7 +379,7 @@ testCb('--watch watches directory dependencies', (t) => { // Using exec() and quoting "*.css" to test watch's glob handling: cp = exec( `node ${path.resolve( - 'bin/postcss' + 'index.js' )} "s.css" -o output.css --no-map -w`, { cwd: dir } ) @@ -490,7 +487,7 @@ testCb( watcher.on('ready', () => { cp = exec( `node ${path.resolve( - 'bin/postcss' + 'index.js' )} "s.css" -o output.css --no-map -w`, { cwd: dir } )