diff options
Diffstat (limited to 'node_modules/postcss-cli')
| -rw-r--r-- | node_modules/postcss-cli/LICENSE | 21 | ||||
| -rw-r--r-- | node_modules/postcss-cli/README.md | 149 | ||||
| -rwxr-xr-x | node_modules/postcss-cli/index.js | 354 | ||||
| -rw-r--r-- | node_modules/postcss-cli/lib/DependencyGraph.js | 30 | ||||
| -rw-r--r-- | node_modules/postcss-cli/lib/args.js | 115 | ||||
| -rw-r--r-- | node_modules/postcss-cli/lib/getMapfile.js | 7 | ||||
| -rw-r--r-- | node_modules/postcss-cli/package.json | 78 |
7 files changed, 754 insertions, 0 deletions
diff --git a/node_modules/postcss-cli/LICENSE b/node_modules/postcss-cli/LICENSE new file mode 100644 index 0000000..e4d2d4a --- /dev/null +++ b/node_modules/postcss-cli/LICENSE @@ -0,0 +1,21 @@ +License (MIT) + +Copyright (c) 2016 Michael Ciniawsky + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/postcss-cli/README.md b/node_modules/postcss-cli/README.md new file mode 100644 index 0000000..9dc9a2d --- /dev/null +++ b/node_modules/postcss-cli/README.md @@ -0,0 +1,149 @@ +[![npm][npm]][npm-url] +[![node][node]][node-url] +[![tests][tests]][tests-url] +[![cover][cover]][cover-url] +[![chat][chat]][chat-url] + +<div align="center"> + <img width="100" height="100" title="CLI" src="https://raw.githubusercontent.com/postcss/postcss-cli/HEAD/logo.svg"> + <a href="https://github.com/postcss/postcss"> + <img width="110" height="110" title="PostCSS" src="http://postcss.github.io/postcss/logo.svg" hspace="10"> + </a> + <h1>PostCSS CLI</h1> +</div> + +<h2 align="center">Install</h2> + +```bash +npm i -D postcss postcss-cli +``` + +<h2 align="center">Usage</h2> + +``` +Usage: + postcss [input.css] [OPTIONS] [-o|--output output.css] [--watch|-w] + postcss <input.css>... [OPTIONS] --dir <output-directory> [--watch|-w] + postcss <input-directory> [OPTIONS] --dir <output-directory> [--watch|-w] + postcss <input-glob-pattern> [OPTIONS] --dir <output-directory> [--watch|-w] + postcss <input.css>... [OPTIONS] --replace + +Basic options: + -o, --output Output file [string] + -d, --dir Output directory [string] + -r, --replace Replace (overwrite) the input file [boolean] + -m, --map Create an external sourcemap + --no-map Disable the default inline sourcemaps + -w, --watch Watch files for changes and recompile as needed [boolean] + --verbose Be verbose [boolean] + --env A shortcut for setting NODE_ENV [string] + +Options for use without a config file: + -u, --use List of postcss plugins to use [array] + --parser Custom postcss parser [string] + --stringifier Custom postcss stringifier [string] + --syntax Custom postcss syntax [string] + +Options for use with --dir: + --ext Override the output file extension; for use with --dir [string] + --base Mirror the directory structure relative to this path in the output + directory, for use with --dir [string] + +Advanced options: + --include-dotfiles Enable glob to match files/dirs that begin with "." + [boolean] + --poll Use polling for file watching. Can optionally pass polling + interval; default 100 ms + --config Set a custom directory to look for a config file [string] + +Options: + --version Show version number [boolean] + -h, --help Show help [boolean] + +Examples: + postcss input.css -o output.css Basic usage + postcss src/**/*.css --base src --dir build Glob Pattern & output + cat input.css | postcss -u autoprefixer > output.css Piping input & output + +If no input files are passed, it reads from stdin. If neither -o, --dir, or +--replace is passed, it writes to stdout. + +If there are multiple input files, the --dir or --replace option must be passed. + +Input files may contain globs (e.g. src/**/*.css). If you pass an input +directory, it will process all files in the directory and any subdirectories, +respecting the glob pattern. +``` + +> ℹ️ More details on custom parsers, stringifiers and syntaxes, can be found [here](https://github.com/postcss/postcss#syntaxes). + +### [Config](https://github.com/michael-ciniawsky/postcss-load-config) + +If you need to pass options to your plugins, or have a long plugin chain, you'll want to use a configuration file. + +**postcss.config.js** + +```js +module.exports = { + parser: 'sugarss', + plugins: [ + require('postcss-import')({ ...options }), + require('postcss-url')({ url: 'copy', useHash: true }), + ], +} +``` + +Note that you **can not** set the `from` or `to` options for postcss in the config file. They are set automatically based on the CLI arguments. + +### Context + +For more advanced usage, it's recommended to use a function in `postcss.config.js`; this gives you access to the CLI context to dynamically apply options and plugins **per file** + +| Name | Type | Default | Description | +| :-------: | :--------: | :--------------------------------: | :------------------- | +| `env` | `{String}` | `'development'` | process.env.NODE_ENV | +| `file` | `{Object}` | `dirname, basename, extname` | File | +| `options` | `{Object}` | `map, parser, syntax, stringifier` | PostCSS Options | + +**postcss.config.js** + +```js +module.exports = (ctx) => ({ + map: ctx.options.map, + parser: ctx.file.extname === '.sss' ? 'sugarss' : false, + plugins: { + 'postcss-import': { root: ctx.file.dirname }, + cssnano: ctx.env === 'production' ? {} : false, + }, +}) +``` + +> ⚠️ If you want to set options via CLI, it's mandatory to reference `ctx.options` in `postcss.config.js` + +```bash +postcss input.sss -p sugarss -o output.css -m +``` + +**postcss.config.js** + +```js +module.exports = (ctx) => ({ + map: ctx.options.map, + parser: ctx.options.parser, + plugins: { + 'postcss-import': { root: ctx.file.dirname }, + cssnano: ctx.env === 'production' ? {} : false, + }, +}) +``` + +[npm]: https://img.shields.io/npm/v/postcss-cli.svg +[npm-url]: https://npmjs.com/package/postcss-cli +[node]: https://img.shields.io/node/v/postcss-cli.svg +[node-url]: https://nodejs.org/ +[tests]: https://img.shields.io/github/workflow/status/postcss/postcss-cli/Node.js%20CI/master +[tests-url]: https://github.com/postcss/postcss-cli/actions?query=branch%3Amaster +[cover]: https://img.shields.io/coveralls/postcss/postcss-cli/master.svg +[cover-url]: https://coveralls.io/github/postcss/postcss-cli +[chat]: https://img.shields.io/gitter/room/postcss/postcss.svg +[chat-url]: https://gitter.im/postcss/postcss diff --git a/node_modules/postcss-cli/index.js b/node_modules/postcss-cli/index.js new file mode 100755 index 0000000..da052ce --- /dev/null +++ b/node_modules/postcss-cli/index.js @@ -0,0 +1,354 @@ +#!/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 pc from 'picocolors' +import { globby } 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._ +const { dir, output } = argv + +if (argv.map) argv.map = { inline: false } + +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 + +if (argv.env) process.env.NODE_ENV = argv.env +if (argv.config) argv.config = path.resolve(argv.config) + +let { isTTY } = process.stdin + +if (process.env.FORCE_IS_TTY === 'true') { + isTTY = true +} + +if (argv.watch && isTTY) { + process.stdin.on('end', () => process.exit(0)) + process.stdin.resume() +} + +/* istanbul ignore next */ +if (parseInt(postcss().version) < 8) { + error('Please install PostCSS 8 or above') +} + +buildCliConfig() + .then(() => { + if (argv.watch && !(argv.output || argv.replace || argv.dir)) { + error('Cannot write to stdout in watch mode') + // Need to explicitly exit here, since error() doesn't exit in watch mode + process.exit(1) + } + + if (input && input.length) { + return globby( + input.map((i) => slash(String(i))), + { dot: argv.includeDotfiles } + ) + } + + if (argv.replace || argv.dir) { + error( + 'Input Error: Cannot use --dir or --replace when reading from stdin' + ) + } + + if (argv.watch) { + error('Input Error: Cannot run in watch mode when reading from stdin') + } + + return ['stdin'] + }) + .then((i) => { + if (!i || !i.length) { + error('Input Error: You must pass a valid list of files to parse') + } + + if (i.length > 1 && !argv.dir && !argv.replace) { + error( + 'Input Error: Must use --dir or --replace with multiple input files' + ) + } + + if (i[0] !== 'stdin') i = i.map((i) => path.resolve(i)) + + input = i + + return files(input) + }) + .then((results) => { + if (argv.watch) { + const printMessage = () => + printVerbose(pc.dim('\nWaiting for file changes...')) + const watcher = chokidar.watch(input.concat(dependencies(results)), { + usePolling: argv.poll, + interval: argv.poll && typeof argv.poll === 'number' ? argv.poll : 100, + awaitWriteFinish: { + stabilityThreshold: 50, + pollInterval: 10, + }, + }) + + if (configFile) watcher.add(configFile) + + watcher.on('ready', printMessage).on('change', (file) => { + let recompile = [] + + if (input.includes(file)) recompile.push(file) + + const dependants = depGraph + .dependantsOf(file) + .concat(getAncestorDirs(file).flatMap(depGraph.dependantsOf)) + + recompile = recompile.concat( + dependants.filter((file) => input.includes(file)) + ) + + if (!recompile.length) recompile = input + + return files([...new Set(recompile)]) + .then((results) => watcher.add(dependencies(results))) + .then(printMessage) + .catch(error) + }) + } + }) + .catch((err) => { + error(err) + + process.exit(1) + }) + +function rc(ctx, path) { + if (argv.use) return Promise.resolve(cliConfig) + + return postcssrc(ctx, path) + .then((rc) => { + if (rc.options.from || rc.options.to) { + error( + 'Config Error: Can not set from or to options in config file, use CLI arguments instead' + ) + } + configFile = rc.file + return rc + }) + .catch((err) => { + if (!err.message.includes('No PostCSS Config found')) throw err + }) +} + +function files(files) { + if (typeof files === 'string') files = [files] + + return Promise.all( + files.map((file) => { + if (file === 'stdin') { + return stdin().then((content) => { + if (!content) return error('Input Error: Did not receive any STDIN') + return css(content, 'stdin') + }) + } + + return read(file).then((content) => css(content, file)) + }) + ) +} + +function css(css, file) { + const ctx = { options: cliConfig.options } + + if (file !== 'stdin') { + ctx.file = { + dirname: path.dirname(file), + basename: path.basename(file), + extname: path.extname(file), + } + + if (!argv.config) argv.config = path.dirname(file) + } + + const relativePath = + file !== 'stdin' ? path.relative(path.resolve(), file) : file + + if (!argv.config) argv.config = process.cwd() + + const time = process.hrtime() + + printVerbose(pc.cyan(`Processing ${pc.bold(relativePath)}...`)) + + return rc(ctx, argv.config) + .then((config) => { + config = config || cliConfig + const options = { ...config.options } + + if (file === 'stdin' && output) file = output + + // TODO: Unit test this + options.from = file === 'stdin' ? path.join(process.cwd(), 'stdin') : file + + if (output || dir || argv.replace) { + const base = argv.base + ? file.replace(path.resolve(argv.base), '') + : path.basename(file) + options.to = output || (argv.replace ? file : path.join(dir, base)) + + if (argv.ext) { + options.to = options.to.replace(path.extname(options.to), argv.ext) + } + + options.to = path.resolve(options.to) + } + + if (!options.to && config.options.map && !config.options.map.inline) { + error( + 'Output Error: Cannot output external sourcemaps when writing to STDOUT' + ) + } + + return postcss(config.plugins) + .process(css, options) + .then((result) => { + const tasks = [] + + if (options.to) { + tasks.push(outputFile(options.to, result.css)) + + if (result.map) { + const mapfile = getMapfile(options) + tasks.push(outputFile(mapfile, result.map.toString())) + } + } else process.stdout.write(result.css, 'utf8') + + return Promise.all(tasks).then(() => { + const prettyTime = prettyHrtime(process.hrtime(time)) + printVerbose( + pc.green( + `Finished ${pc.bold(relativePath)} in ${pc.bold(prettyTime)}` + ) + ) + + const messages = result.warnings() + if (messages.length) { + console.warn(reporter({ ...result, messages })) + } + + return result + }) + }) + }) + .catch((err) => { + throw err + }) + + async function outputFile(file, string) { + const fileExists = await fs.pathExists(file) + const currentValue = fileExists ? await fs.readFile(file, 'utf8') : null + if (currentValue === string) return + return fs.outputFile(file, string) + } +} + +function dependencies(results) { + if (!Array.isArray(results)) results = [results] + + const messages = [] + + results.forEach((result) => { + if (result.messages <= 0) return + + result.messages + .filter((msg) => + msg.type === 'dependency' || msg.type === 'dir-dependency' ? msg : '' + ) + .map(depGraph.add) + .forEach((dependency) => { + if (dependency.type === 'dir-dependency') { + messages.push( + dependency.glob + ? path.join(dependency.dir, dependency.glob) + : dependency.dir + ) + } else { + messages.push(dependency.file) + } + }) + }) + + return messages +} + +function printVerbose(message) { + if (argv.verbose) console.warn(message) +} + +function error(err) { + // Seperate error from logging output + if (argv.verbose) console.error() + + if (typeof err === 'string') { + console.error(pc.red(err)) + } else if (err.name === 'CssSyntaxError') { + console.error(err.toString()) + } else { + console.error(err) + } + // Watch mode shouldn't exit on error + if (argv.watch) return + process.exit(1) +} + +// Input: '/imports/components/button.css' +// Output: ['/imports/components', '/imports', '/'] +function getAncestorDirs(fileOrDir) { + const { root } = path.parse(fileOrDir) + if (fileOrDir === root) { + return [] + } + const parentDir = path.dirname(fileOrDir) + return [parentDir, ...getAncestorDirs(parentDir)] +} diff --git a/node_modules/postcss-cli/lib/DependencyGraph.js b/node_modules/postcss-cli/lib/DependencyGraph.js new file mode 100644 index 0000000..efb7ac3 --- /dev/null +++ b/node_modules/postcss-cli/lib/DependencyGraph.js @@ -0,0 +1,30 @@ +import path from 'path' +import { DepGraph } from 'dependency-graph' + +export default function createDependencyGraph() { + const graph = new DepGraph() + return { + add(message) { + message.parent = path.resolve(message.parent) + graph.addNode(message.parent) + + if (message.type === 'dir-dependency') { + message.dir = path.resolve(message.dir) + graph.addNode(message.dir) + graph.addDependency(message.parent, message.dir) + } else { + message.file = path.resolve(message.file) + graph.addNode(message.file) + graph.addDependency(message.parent, message.file) + } + + return message + }, + dependantsOf(node) { + node = path.resolve(node) + + if (graph.hasNode(node)) return graph.dependantsOf(node) + return [] + }, + } +} diff --git a/node_modules/postcss-cli/lib/args.js b/node_modules/postcss-cli/lib/args.js new file mode 100644 index 0000000..35f0e83 --- /dev/null +++ b/node_modules/postcss-cli/lib/args.js @@ -0,0 +1,115 @@ +import yargs from 'yargs' + +const { argv } = yargs(process.argv.slice(2)) + .usage( + `Usage: + $0 [input.css] [OPTIONS] [-o|--output output.css] [--watch|-w] + $0 <input.css>... [OPTIONS] --dir <output-directory> [--watch|-w] + $0 <input-directory> [OPTIONS] --dir <output-directory> [--watch|-w] + $0 <input-glob-pattern> [OPTIONS] --dir <output-directory> [--watch|-w] + $0 <input.css>... [OPTIONS] --replace` + ) + .group( + ['o', 'd', 'r', 'map', 'no-map', 'watch', 'verbose', 'env'], + 'Basic options:' + ) + .option('o', { + alias: 'output', + desc: 'Output file', + type: 'string', + conflicts: ['dir', 'replace'], + }) + .option('d', { + alias: 'dir', + desc: 'Output directory', + type: 'string', + conflicts: ['output', 'replace'], + }) + .option('r', { + alias: 'replace', + desc: 'Replace (overwrite) the input file', + type: 'boolean', + conflicts: ['output', 'dir'], + }) + .alias('m', 'map') + .describe('map', 'Create an external sourcemap') + .describe('no-map', 'Disable the default inline sourcemaps') + .option('w', { + alias: 'watch', + desc: 'Watch files for changes and recompile as needed', + type: 'boolean', + conflicts: 'replace', + }) + .option('verbose', { + desc: 'Be verbose', + type: 'boolean', + }) + .option('env', { + desc: 'A shortcut for setting NODE_ENV', + type: 'string', + }) + .group( + ['u', 'parser', 'stringifier', 'syntax'], + 'Options for use without a config file:' + ) + .option('u', { + alias: 'use', + desc: 'List of postcss plugins to use', + type: 'array', + }) + .option('parser', { + desc: 'Custom postcss parser', + type: 'string', + }) + .option('stringifier', { + desc: 'Custom postcss stringifier', + type: 'string', + }) + .option('syntax', { + desc: 'Custom postcss syntax', + type: 'string', + }) + .group(['ext', 'base'], 'Options for use with --dir:') + .option('ext', { + desc: 'Override the output file extension; for use with --dir', + type: 'string', + implies: 'dir', + }) + .option('base', { + desc: 'Mirror the directory structure relative to this path in the output directory, for use with --dir', + type: 'string', + implies: 'dir', + }) + .group(['include-dotfiles', 'poll', 'config'], 'Advanced options:') + .option('include-dotfiles', { + desc: 'Enable glob to match files/dirs that begin with "."', + type: 'boolean', + }) + .option('poll', { + desc: 'Use polling for file watching. Can optionally pass polling interval; default 100 ms', + implies: 'watch', + }) + .option('config', { + desc: 'Set a custom directory to look for a config file', + type: 'string', + }) + .alias('h', 'help') + .example('$0 input.css -o output.css', 'Basic usage') + .example('$0 src/**/*.css --base src --dir build', 'Glob Pattern & output') + .example( + 'cat input.css | $0 -u autoprefixer > output.css', + 'Piping input & output' + ) + .epilog( + `If no input files are passed, it reads from stdin. If neither -o, --dir, or --replace is passed, it writes to stdout. + +If there are multiple input files, the --dir or --replace option must be passed. + +Input files may contain globs (e.g. src/**/*.css). If you pass an input directory, it will process all files in the directory and any subdirectories, respecting the glob pattern. + +For more details, please see https://github.com/postcss/postcss-cli` + ) + +if (argv.ext && argv.ext.indexOf('.') !== 0) argv.ext = `.${argv.ext}` + +export default argv diff --git a/node_modules/postcss-cli/lib/getMapfile.js b/node_modules/postcss-cli/lib/getMapfile.js new file mode 100644 index 0000000..e4d0c93 --- /dev/null +++ b/node_modules/postcss-cli/lib/getMapfile.js @@ -0,0 +1,7 @@ +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}` + } + return `${options.to}.map` +} diff --git a/node_modules/postcss-cli/package.json b/node_modules/postcss-cli/package.json new file mode 100644 index 0000000..1fc3037 --- /dev/null +++ b/node_modules/postcss-cli/package.json @@ -0,0 +1,78 @@ +{ + "name": "postcss-cli", + "version": "10.1.0", + "description": "CLI for PostCSS", + "type": "module", + "engines": { + "node": ">=14" + }, + "bin": { + "postcss": "./index.js" + }, + "scripts": { + "ci": "eslint . && c8 ava -v && npm run prettier -- --list-different", + "clean": "node test/helpers/clean.js", + "prettier": "prettier --single-quote --no-semi \"**/*.{js,md}\"", + "format": "npm run prettier -- --write && eslint . --fix", + "pretest": "npm run clean && npm run format", + "test": "c8 ava -v" + }, + "dependencies": { + "chokidar": "^3.3.0", + "dependency-graph": "^0.11.0", + "fs-extra": "^11.0.0", + "get-stdin": "^9.0.0", + "globby": "^13.0.0", + "picocolors": "^1.0.0", + "postcss-load-config": "^4.0.0", + "postcss-reporter": "^7.0.0", + "pretty-hrtime": "^1.0.3", + "read-cache": "^1.0.0", + "slash": "^5.0.0", + "yargs": "^17.0.0" + }, + "devDependencies": { + "ava": "^3.1.0", + "c8": "^7.9.0", + "coveralls": "^3.0.0", + "eslint": "^8.2.0", + "eslint-config-problems": "7.0.1", + "postcss": "^8.0.4", + "postcss-import": "^15.0.0", + "prettier": "~2.8.0", + "sugarss": "^4.0.0", + "uuid": "^9.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + }, + "files": [ + "index.js", + "lib", + "!**/*.test.js" + ], + "keywords": [ + "cli", + "postcss", + "postcss-runner" + ], + "contributors": [ + { + "name": "Michael Ciniawky", + "email": "michael.ciniawsky@gmail.com" + }, + { + "name": "Ryan Zimmermann", + "email": "opensrc@ryanzim.com" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/postcss/postcss-cli.git" + }, + "bugs": { + "url": "https://github.com/postcss/postcss-cli/issues" + }, + "homepage": "https://github.com/postcss/postcss-cli#readme", + "license": "MIT" +} |