pax_global_header 0000666 0000000 0000000 00000000064 14341470641 0014516 g ustar 00root root 0000000 0000000 52 comment=a3574b1f67e4d8c1a78b6b72b501354f545c34d2
postcss-cli-10.1.0/ 0000775 0000000 0000000 00000000000 14341470641 0014040 5 ustar 00root root 0000000 0000000 postcss-cli-10.1.0/.eslintrc.yaml 0000664 0000000 0000000 00000000141 14341470641 0016621 0 ustar 00root root 0000000 0000000 env:
node: true
parserOptions:
sourceType: module
extends: problems
rules:
no-console: off
postcss-cli-10.1.0/.github/ 0000775 0000000 0000000 00000000000 14341470641 0015400 5 ustar 00root root 0000000 0000000 postcss-cli-10.1.0/.github/workflows/ 0000775 0000000 0000000 00000000000 14341470641 0017435 5 ustar 00root root 0000000 0000000 postcss-cli-10.1.0/.github/workflows/ci.yml 0000664 0000000 0000000 00000000737 14341470641 0020562 0 ustar 00root root 0000000 0000000 name: Node.js CI
on:
push:
branches: master
pull_request:
jobs:
test:
strategy:
matrix:
node: [14, 16, 18]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- run: git config --global core.autocrlf input
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}
- run: npm install
- run: npm run ci
postcss-cli-10.1.0/.gitignore 0000664 0000000 0000000 00000001317 14341470641 0016032 0 ustar 00root root 0000000 0000000 # Test artifacts
.tmp
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
postcss-cli-10.1.0/.npmrc 0000664 0000000 0000000 00000000023 14341470641 0015153 0 ustar 00root root 0000000 0000000 package-lock=false
postcss-cli-10.1.0/.prettierignore 0000664 0000000 0000000 00000000006 14341470641 0017077 0 ustar 00root root 0000000 0000000 .tmp/
postcss-cli-10.1.0/CHANGELOG.md 0000664 0000000 0000000 00000027445 14341470641 0015665 0 ustar 00root root 0000000 0000000 # 10.1.0 / 2022-11-29
- Allow running `--watch` mode in non-TTY contexts, like Docker ([#448](https://github.com/postcss/postcss-cli/pull/448))
- Update dependencies
# 10.0.0 / 2022-06-29
- **BREAKING:** Drop Node 12 support ([#438](https://github.com/postcss/postcss-cli/pull/438))
- Add support for ESM config files ([#437](https://github.com/postcss/postcss-cli/pull/437))
# 9.1.0 / 2021-12-10
- Don't write to files if they're unchanged ([#320](https://github.com/postcss/postcss-cli/issues/320), [#417](https://github.com/postcss/postcss-cli/pull/417))
# 9.0.2 / 2021-11-04
- Switch to picocolors ([#409](https://github.com/postcss/postcss-cli/pull/409))
- Remove test files from npm package
# 9.0.1 / 2021-09-28
- Actually exit with error when attempting to stdout in watch mode
- Remove `bin/` from `files` in package.json
# 9.0.0 / 2021-09-24
- **BREAKING:** Require Node.js v12+
- **BREAKING:** Must specify full file path, including `.js` extension, when loading local plugins with `--use` ([#401](https://github.com/postcss/postcss-cli/pull/401))
- **BREAKING:** Officially remove support for watching postcss config (was already broken in previous releases)
- Add support for `dir-dependency` messages ([#383](https://github.com/postcss/postcss-cli/pull/383), [#391](https://github.com/postcss/postcss-cli/pull/391))
- Update deps
# 8.3.1 / 2020-12-12
- Ensure paths are not interpreted as numbers ([#360](https://github.com/postcss/postcss-cli/issues/360))
- Better errors for incorrect postcss version ([#361](https://github.com/postcss/postcss-cli/issues/361), [#362](https://github.com/postcss/postcss-cli/pull/362))
# 8.3.0 / 2020-11-17
- Exit on EOF/`^D` ([#358](https://github.com/postcss/postcss-cli/pull/358))
# 8.2.0 / 2020-10-29
- Allow backslashes in paths for better Windows experence ([#355](https://github.com/postcss/postcss-cli/pull/355))
# 8.1.0 / 2020-10-08
- Add support for `postcss.config.cjs` files ([#351](https://github.com/postcss/postcss-cli/pull/351))
# 8.0.0 / 2020-09-21
- **BREAKING:** Support postcss v8 ([#344](https://github.com/postcss/postcss-cli/issues/344), [#349](https://github.com/postcss/postcss-cli/pull/349))
- **BREAKING:** postcss is now a `peerDependency`, you must install it seperately ([#344](https://github.com/postcss/postcss-cli/issues/344), [#349](https://github.com/postcss/postcss-cli/pull/349))
- Upgrade dependencies ([#340](https://github.com/postcss/postcss-cli/pull/340))
# 7.1.2 / 2020-08-31
- Make `--version` machine-readable ([#334](https://github.com/postcss/postcss-cli/issues/334), [#335](https://github.com/postcss/postcss-cli/pull/335))
- Organize and clarify `--help` text ([#336](https://github.com/postcss/postcss-cli/pull/336))
- Update dependencies
# 7.1.1 / 2020-04-27
- Fix bug where external source maps were not properly generated ([#324](https://github.com/postcss/postcss-cli/pull/324))
- Update dependencies
# 7.1.0 / 2020-01-09
- Respect `map.annotation` option when set to a string ([#307](https://github.com/postcss/postcss-cli/pull/307))
# 7.0.0 / 2020-01-07
- **BREAKING:** Drop support for Node 6 & 8
- Update `globby`, which may be a breaking change for a small number of users using certain glob patterns, see https://github.com/mrmlnc/fast-glob#pattern-syntax for details ([#303](https://github.com/postcss/postcss-cli/pull/303))
- Update dependencies
# 6.1.3 / 2019-07-08
- Fix external sorcemap filenames when the directory name contains `.css` ([#283](https://github.com/postcss/postcss-cli/issues/283), [#286](https://github.com/postcss/postcss-cli/pull/286))
# 6.1.2 / 2019-02-22
- Upgrade dependency globby to fix bug in sub-dependency ([#265](https://github.com/postcss/postcss-cli/issues/265), [#270](https://github.com/postcss/postcss-cli/pull/270))
# 6.1.1 / 2019-01-04
- Fix empty lines being printed in some cases ([#256](https://github.com/postcss/postcss-cli/issues/256), [#257](https://github.com/postcss/postcss-cli/pull/257))
# 6.1.0 / 2018-12-19
- Add `--include-dotfiles` flag to allow globs to match dotfiles. ([#254](https://github.com/postcss/postcss-cli/pull/254))
- Only log warning messages. This has always been intended behavior, but it wasn't working as expected. ([#244](https://github.com/postcss/postcss-cli/pull/244))
# 6.0.1 / 2018-10-17
- Better error handling for errors thrown by plugins ([#242](https://github.com/postcss/postcss-cli/issues/242), [#243](https://github.com/postcss/postcss-cli/pull/243))
- Update dependencies
- Clarify docs ([#233](https://github.com/postcss/postcss-cli/issues/233))
# 6.0.0 / 2018-07-18
- Drop support for Node 4
- Upgrade to postcss v7 ([release notes](https://github.com/postcss/postcss/blob/master/CHANGELOG.md#70-president-amy))
- Upgrade to postcss-load-config v2 ([release notes](https://github.com/michael-ciniawsky/postcss-load-config/blob/master/CHANGELOG.md#200-2018-07-10))
# 5.0.1 / 2018-06-18
- Shallow copy options object; fixes a few edge cases
- Adjust options for file watching to play better with some editors
# 5.0.0 / 2018-02-06
- Now allows passing a directory as the input (all files in the directory will be processed)
- The CLI is now silent by default; added `--verbose` flag for if you want noisy logs
- Doesn't exit watch mode when there's an error in the plugin chain
- Removed non-obvious shorthand arguments (`-x`, `-p`, `-s`, `-t`, `-e`, `-b`, & `-c`). Also removed `-v` as an alias for `--version`.
- Prevent stupid option combinations like `--dir` & `-o`, and `--watch` & `--replace`
- Doesn't allow `--watch` when writing to STDOUT
# 4.1.1 / 2017-08-17
- Fixed bug with `--config`
- Upgraded dependencies
# 4.1.0 / 2017-06-10
- Can now pass a number to `--poll` to set poll interval
- Updated `postcss-reporter` dependency to v4.0.0
# 4.0.0 / 2017-05-09
- **BREAKING:** Upgrade postcss to v6.x
# 3.2.0 / 2017-04-21
- Added `--base` CLI option for keeping directory structure
# 3.1.1 / 2017-04-04
- Fixed `files` property in `package.json`; `lib/` folder wasn't included in v3.1.0
# 3.1.0 / 2017-04-04
- Improved incremental rebuilds for better performance in watch mode.
- Switched to `read-cache` for file reading for better performance.
- Set a dummy filename when reading from stdin to help plugins like autoprefixer find config files.
- Updated `fs-promise` dependency.
# 3.0.0 / 2017-03-15
## Changes since 3.0.0-beta
### Breaking Changes
- Don't exit on `CssSyntaxError` in watch mode. v2 behaved this way, but v3.0.0-beta didn't.
- Error out if `from` or `to` options are set in the config file. Use command line arguments instead.
### New Features
- Add `--poll` option. v2 had this, however, this new implementation removes the capability to set the interval, which was supported in v2.
### Bugfixes
- Set `from` option for correct sourcemaps
- Fix `--watch`'s glob handling
- Fix error handling
## Changes since v2.6.0
### Breaking Changes
- Uses https://github.com/michael-ciniawsky/postcss-load-config for config files. Dropped support for the v2 config file format.
- Can't set input files in config file; pass input files on the command line instead.
- `--use` accepts a list of plugins. This may cause issues if you have your list of css files at the end of your command.
- Can't pass options to plugins via `--plugin.key=value` anymore, use a config file.
- Changed usage of the `--map` option; use `--map` for external sourcemaps, `--no-map` to disable all maps. Inline sourcemaps are default.
- Removed `--log` flag; this behavior is now default.
- Removed the `--local-plugins` flag; same result can be achieved with `postcss.config.js`.
- Removed the global `watchCSS` handler, plugins that import/rely on other files should use a `dependency` message instead.
- Changed behavior of the `--poll` option; no longer accepts an integer `interval`.
### New Features
- `--ext` (`-x`) option allows you to set the file extensions for your output files when using `--dir`.
- `--env` allows you to set `NODE_ENV` in a cross-platform manner.
Migration guide for upgrading from v2: https://github.com/postcss/postcss-cli/wiki/Migrating-from-v2-to-v3
# 3.0.0-beta / 2017-03-17
## Breaking Changes
- Uses https://github.com/michael-ciniawsky/postcss-load-config for config files. Dropped support for the v2 config file format.
- Can't set input files in config file; pass input files on the command line instead.
- `--use` accepts a list of plugins. This may cause issues if you have your list of css files at the end of your command.
- Can't pass options to plugins via `--plugin.key=value` anymore, use a config file.
- Changed usage of the `--map` option; use `--map` for external sourcemaps, `--no-map` to disable all maps. Inline sourcemaps are default.
- Removed `--log` flag; this behavior is now default.
- Removed the `--local-plugins` flag; same result can be achieved with `postcss.config.js`.
- Removed the global `watchCSS` handler, plugins that import/rely on other files should use a `dependency` message instead.
## New Features
- `--ext` (`-x`) option allows you to set the file extensions for your output files when using `--dir`.
- `--env` allows you to set `NODE_ENV` in a cross-platform manner.
Migration guide: https://github.com/postcss/postcss-cli/wiki/Migrating-from-v2-to-v3
# 2.6.0 / 2016-08-30
- Add log option
- Update postcss-import to v8.1.2 from v7.1.0
- Update globby to v4.1.0 from v3.0.1
- Update postcss-url to v5.1.2 from v4.0.0
- Update jshint to v2.9.2 from v2.6.3
- Update chokidar to v1.5.1 from v1.0.3
- Update yargs to v4.7.1 from v3.32.0
- Support es6 export
- Allow running without plugins
- Add test for --poll
- Add --poll flag
# 2.5.2 / 2016-04-18
- Fix typo in help message: -use => [--use|-u]
- npm install --save mkdirp
- Support mkdirp to create dest path if it doesn't exists
- Fix booleans in config file
# 2.5.1 / 2016-02-11
- fix `input` argument
# 2.5.0 / 2016-01-30
- move to postcss/postcss-cli repository
- Update Readme.md
# 2.4.1 / 2016-01-27
- improve warning disply format
# 2.4.0 / 2016-01-15
- add support for source maps
# 2.3.3 / 2015-12-28
- add usage example for `local-plugins` option in config file
# 2.3.2 / 2015-10-27
- auto-configure postcss-import support
- add support for watching multiple entry points
# 2.3.1 / 2015-10-25
- update Travis config
- upgrade postcss-import dependency - fix deprecation warnings during make test-watch
# 2.3.0 / 2015-10-24
- add --local-plugins option that lets postcss-cli to look for plugins in current directory
# 2.2.0 / 2015-10-09
- add support for --replace|-r - if used input files are replaced with generated output
- refactor support for custom syntax options
# 2.1.1 / 2015-10-08
- add globby to support wildcards in Windows
- remove obsolete note on postcss-import compatibility
# 2.1.0 / 2015-09-01
- add support for PostCSS 5.0 custom syntax options
# 2.0.0 / 2015-08-24
- remove support for --safe option
- switch to using postcss 5.x
# 1.5.0 / 2015-07-20
- add watch mode (-w|--watch) in which postcss-cli observes and recompiles inputs whenever they change
- update neo-async dependency to released version
- update postcss-url dependency (used in tests only)
# 1.4.0 / 2015-07-12
- allow specifying input file via config file
- allow specifying -u|--use via config file
# 1.3.1 / 2015-05-03
- update npm keyword: postcssrunner -> postcss-runner
# 1.3.0 / 2015-04-28
- add support for stdin/stdout if no input/output file specified
# 1.2.1 / 2015-04-20
- fix typo in readme
# 1.2.0 / 2015-04-02
- display warnings and errors
- stop testing on node 0.10
# 1.1.0 / 2015-03-28
- prefer postcss async API if available
# 1.0.0 / 2015-03-22
- use official yargs version
- add support for multiple input files
# 0.3.0 / 2015-03-19
- support JS format as plugins config
# 0.2.0 / 2015-03-13
- use autoprefixer instead of autoprefixer-core
- change short options for --use from `p` to `u`
- add -v|--version support
- add --safe option to enable postcss safe mode
# 0.1.0 / 2015-03-11
- initial implementaion
postcss-cli-10.1.0/LICENSE 0000664 0000000 0000000 00000002064 14341470641 0015047 0 ustar 00root root 0000000 0000000 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.
postcss-cli-10.1.0/README.md 0000664 0000000 0000000 00000013446 14341470641 0015327 0 ustar 00root root 0000000 0000000 [![npm][npm]][npm-url]
[![node][node]][node-url]
[![tests][tests]][tests-url]
[![cover][cover]][cover-url]
[![chat][chat]][chat-url]
PostCSS CLI
Install
```bash
npm i -D postcss postcss-cli
```
Usage
```
Usage:
postcss [input.css] [OPTIONS] [-o|--output output.css] [--watch|-w]
postcss ... [OPTIONS] --dir [--watch|-w]
postcss [OPTIONS] --dir [--watch|-w]
postcss [OPTIONS] --dir [--watch|-w]
postcss ... [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
postcss-cli-10.1.0/index.js 0000775 0000000 0000000 00000022105 14341470641 0015510 0 ustar 00root root 0000000 0000000 #!/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)]
}
postcss-cli-10.1.0/lib/ 0000775 0000000 0000000 00000000000 14341470641 0014606 5 ustar 00root root 0000000 0000000 postcss-cli-10.1.0/lib/DependencyGraph.js 0000664 0000000 0000000 00000001442 14341470641 0020205 0 ustar 00root root 0000000 0000000 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 []
},
}
}
postcss-cli-10.1.0/lib/DependencyGraph.test.js 0000664 0000000 0000000 00000001227 14341470641 0021164 0 ustar 00root root 0000000 0000000 import test from 'ava'
import path from 'path'
import createDependencyGraph from './DependencyGraph.js'
function resolveArray(arr) {
return arr.map((p) => path.resolve(p))
}
test('tracks dependencies', (t) => {
const graph = createDependencyGraph()
graph.add({ file: 'aa', parent: 'a' })
graph.add({ file: 'bb', parent: 'b' })
graph.add({ file: 'ab', parent: 'a' })
graph.add({ file: 'ab', parent: 'b' })
t.deepEqual(graph.dependantsOf('aa'), resolveArray(['a']))
t.deepEqual(graph.dependantsOf('bb'), resolveArray(['b']))
t.deepEqual(graph.dependantsOf('ab'), resolveArray(['a', 'b']))
t.deepEqual(graph.dependantsOf('nonexistent'), [])
})
postcss-cli-10.1.0/lib/args.js 0000664 0000000 0000000 00000006577 14341470641 0016117 0 ustar 00root root 0000000 0000000 import yargs from 'yargs'
const { argv } = yargs(process.argv.slice(2))
.usage(
`Usage:
$0 [input.css] [OPTIONS] [-o|--output output.css] [--watch|-w]
$0 ... [OPTIONS] --dir [--watch|-w]
$0 [OPTIONS] --dir [--watch|-w]
$0 [OPTIONS] --dir [--watch|-w]
$0 ... [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
postcss-cli-10.1.0/lib/getMapfile.js 0000664 0000000 0000000 00000000357 14341470641 0017226 0 ustar 00root root 0000000 0000000 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`
}
postcss-cli-10.1.0/lib/getMapfile.test.js 0000664 0000000 0000000 00000001245 14341470641 0020201 0 ustar 00root root 0000000 0000000 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)
}
})
postcss-cli-10.1.0/logo.svg 0000664 0000000 0000000 00000001674 14341470641 0015531 0 ustar 00root root 0000000 0000000
postcss-cli-10.1.0/package.json 0000664 0000000 0000000 00000003453 14341470641 0016333 0 ustar 00root root 0000000 0000000 {
"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"
}
postcss-cli-10.1.0/renovate.json 0000664 0000000 0000000 00000000132 14341470641 0016552 0 ustar 00root root 0000000 0000000 {
"extends": [
"config:base",
":preserveSemverRanges",
":label(deps)"
]
}
postcss-cli-10.1.0/test/ 0000775 0000000 0000000 00000000000 14341470641 0015017 5 ustar 00root root 0000000 0000000 postcss-cli-10.1.0/test/base.js 0000664 0000000 0000000 00000001212 14341470641 0016263 0 ustar 00root root 0000000 0000000 import test from 'ava'
import path from 'path'
import cli from './helpers/cli.js'
import tmp from './helpers/tmp.js'
import read from './helpers/read.js'
test('--base --dir works', async (t) => {
const dir = tmp()
const { error, stderr } = await cli([
'"test/fixtures/base/**/*.css"',
'--dir',
dir,
'--base',
'test/fixtures/base',
'--no-map',
])
t.falsy(error, stderr)
t.is(
await read(path.join(dir, 'level-1/level-2/a.css')),
await read('test/fixtures/base/level-1/level-2/a.css')
)
t.is(
await read(path.join(dir, 'level-1/b.css')),
await read('test/fixtures/base/level-1/b.css')
)
})
postcss-cli-10.1.0/test/cli.js 0000664 0000000 0000000 00000000635 14341470641 0016130 0 ustar 00root root 0000000 0000000 import test from 'ava'
import cli from './helpers/cli.js'
import tmp from './helpers/tmp.js'
import read from './helpers/read.js'
test('works with defaults', async (t) => {
const output = tmp('output.css')
const { error, stderr } = await cli([
'test/fixtures/a.css',
'-o',
output,
'--no-map',
])
t.falsy(error, stderr)
t.is(await read(output), await read('test/fixtures/a.css'))
})
postcss-cli-10.1.0/test/config.js 0000664 0000000 0000000 00000004061 14341470641 0016623 0 ustar 00root root 0000000 0000000 import test from 'ava'
import path from 'path'
import ENV from './helpers/env.js'
import cli from './helpers/cli.js'
import read from './helpers/read.js'
test('supports common config', async (t) => {
const env = `module.exports = {
plugins: [
require('postcss-import')()
]
}`
const dir = await ENV(env, ['a.css'])
const { error, stderr } = await cli(
['a.css', '-o', 'output.css', '--no-map'],
dir
)
t.falsy(error, stderr)
t.is(
await read(path.join(dir, 'output.css')),
await read('test/fixtures/a.css')
)
})
test('supports ESM config', async (t) => {
const env = `import postcssImport from 'postcss-import'
export default function () {
return {
plugins: [
postcssImport()
]
}
}`
const dir = await ENV(env, ['a.css'], 'mjs')
const { error, stderr } = await cli(
['a.css', '-o', 'output.css', '--no-map'],
dir
)
t.falsy(error, stderr)
t.is(
await read(path.join(dir, 'output.css')),
await read('test/fixtures/a.css')
)
})
test("doesn't error on empty config", async (t) => {
const env = `module.exports = {}`
const dir = await ENV(env, ['a.css'])
const { error, stderr } = await cli(
['a.css', '-o', 'output.css', '--no-map'],
dir
)
t.falsy(error, stderr)
t.is(
await read(path.join(dir, 'output.css')),
await read('test/fixtures/a.css')
)
})
test('errors if `to` is set', async (t) => {
const env = `module.exports = {
to: 'out.css'
}`
const dir = await ENV(env, ['a.css'])
const { stderr } = await cli(['a.css', '-o', 'output.css', '--no-map'], dir)
t.regex(
stderr,
/Config Error: Can not set from or to options in config file, use CLI arguments instead/
)
})
test('errors if `from` is set', async (t) => {
const env = `module.exports = {
from: 'in.css'
}`
const dir = await ENV(env, ['a.css'])
const { stderr } = await cli(['a.css', '-o', 'output.css', '--no-map'], dir)
t.regex(
stderr,
/Config Error: Can not set from or to options in config file, use CLI arguments instead/
)
})
postcss-cli-10.1.0/test/dir.js 0000664 0000000 0000000 00000001032 14341470641 0016127 0 ustar 00root root 0000000 0000000 import test from 'ava'
import path from 'path'
import cli from './helpers/cli.js'
import tmp from './helpers/tmp.js'
import read from './helpers/read.js'
test('--dir works', async (t) => {
const dir = tmp()
const { error, stderr } = await cli([
'test/fixtures/a.css',
'test/fixtures/b.css',
'--dir',
dir,
'--no-map',
])
t.falsy(error, stderr)
t.is(await read(path.join(dir, 'a.css')), await read('test/fixtures/a.css'))
t.is(await read(path.join(dir, 'b.css')), await read('test/fixtures/b.css'))
})
postcss-cli-10.1.0/test/error.js 0000664 0000000 0000000 00000003522 14341470641 0016510 0 ustar 00root root 0000000 0000000 import test from 'ava'
import tmp from './helpers/tmp.js'
import cli from './helpers/cli.js'
test('multiple input files && --output', (t) => {
return cli(['test/fixtures/*.css', '-o', tmp()]).then(({ error, code }) => {
t.is(code, 1, 'expected non-zero error code')
t.regex(error.toString(), /Input Error: Must use --dir or --replace/)
})
})
test('multiple input files && writing to stdout', (t) => {
return cli(['test/fixtures/*.css']).then(({ error, code }) => {
t.is(code, 1, 'expected non-zero error code')
t.regex(error.toString(), /Input Error: Must use --dir or --replace/)
})
})
test('--map && writing to stdout', (t) => {
return cli(['test/fixtures/a.css', '--map']).then(({ error, code }) => {
t.is(code, 1, 'expected non-zero error code')
t.regex(
error.toString(),
/Output Error: Cannot output external sourcemaps when writing to STDOUT/
)
})
})
test('plugin not found', (t) => {
return cli(['test/fixtures/a.css', '-u', 'postcss-plugin', '-o', tmp()]).then(
({ error, code }) => {
t.is(code, 1, 'expected non-zero error code')
t.regex(
error.toString(),
/Plugin Error: Cannot find package 'postcss-plugin'/
)
}
)
})
test('plugin throws on require', (t) => {
return cli([
'test/fixtures/a.css',
'-u',
'./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.js\): This fails/)
})
})
test('CssSyntaxError', (t) => {
return cli(['test/fixtures/a.css', '--parser', 'sugarss', '-o', tmp()]).then(
({ error, code }) => {
t.is(code, 1, 'expected non-zero error code')
t.regex(
error.toString(),
/CssSyntaxError: .*a.css:1:4: Unnecessary curly bracket/
)
}
)
})
postcss-cli-10.1.0/test/ext.js 0000664 0000000 0000000 00000001350 14341470641 0016154 0 ustar 00root root 0000000 0000000 import test from 'ava'
import fs from 'fs-extra'
import path from 'path'
import cli from './helpers/cli.js'
import tmp from './helpers/tmp.js'
test('--ext works', async (t) => {
const dir = tmp()
const { error, stderr } = await cli([
'test/fixtures/a.sss',
'--parser',
'sugarss',
'-d',
dir,
'--ext',
'.css',
])
t.falsy(error, stderr)
t.truthy(await fs.pathExists(path.join(dir, 'a.css')))
})
test('--ext works with no leading dot', async (t) => {
const dir = tmp()
const { error, stderr } = await cli([
'test/fixtures/a.sss',
'--parser',
'sugarss',
'-d',
dir,
'--ext',
'css',
])
t.falsy(error, stderr)
t.truthy(await fs.pathExists(path.join(dir, 'a.css')))
})
postcss-cli-10.1.0/test/fixtures/ 0000775 0000000 0000000 00000000000 14341470641 0016670 5 ustar 00root root 0000000 0000000 postcss-cli-10.1.0/test/fixtures/_bad-plugin.js 0000664 0000000 0000000 00000000036 14341470641 0021406 0 ustar 00root root 0000000 0000000 throw new Error('This fails')
postcss-cli-10.1.0/test/fixtures/a.css 0000664 0000000 0000000 00000000025 14341470641 0017617 0 ustar 00root root 0000000 0000000 .a {
color: red;
}
postcss-cli-10.1.0/test/fixtures/a.sss 0000664 0000000 0000000 00000000020 14341470641 0017632 0 ustar 00root root 0000000 0000000 .a
color: red
postcss-cli-10.1.0/test/fixtures/b.css 0000664 0000000 0000000 00000000026 14341470641 0017621 0 ustar 00root root 0000000 0000000 .b {
color: blue;
}
postcss-cli-10.1.0/test/fixtures/b.sss 0000664 0000000 0000000 00000000021 14341470641 0017634 0 ustar 00root root 0000000 0000000 .b
color: blue
postcss-cli-10.1.0/test/fixtures/base/ 0000775 0000000 0000000 00000000000 14341470641 0017602 5 ustar 00root root 0000000 0000000 postcss-cli-10.1.0/test/fixtures/base/level-1/ 0000775 0000000 0000000 00000000000 14341470641 0021047 5 ustar 00root root 0000000 0000000 postcss-cli-10.1.0/test/fixtures/base/level-1/b.css 0000664 0000000 0000000 00000000026 14341470641 0022000 0 ustar 00root root 0000000 0000000 .b {
color: blue;
}
postcss-cli-10.1.0/test/fixtures/base/level-1/level-2/ 0000775 0000000 0000000 00000000000 14341470641 0022315 5 ustar 00root root 0000000 0000000 postcss-cli-10.1.0/test/fixtures/base/level-1/level-2/a.css 0000664 0000000 0000000 00000000025 14341470641 0023244 0 ustar 00root root 0000000 0000000 .a {
color: red;
}
postcss-cli-10.1.0/test/fixtures/base/level-1/level-2/unrelated.md 0000664 0000000 0000000 00000000060 14341470641 0024616 0 ustar 00root root 0000000 0000000 Editing this file should not trigger a rebuild.
postcss-cli-10.1.0/test/fixtures/glob/ 0000775 0000000 0000000 00000000000 14341470641 0017613 5 ustar 00root root 0000000 0000000 postcss-cli-10.1.0/test/fixtures/glob/a.css 0000664 0000000 0000000 00000000025 14341470641 0020542 0 ustar 00root root 0000000 0000000 .a {
color: red;
}
postcss-cli-10.1.0/test/fixtures/glob/b.css 0000664 0000000 0000000 00000000026 14341470641 0020544 0 ustar 00root root 0000000 0000000 .b {
color: blue;
}
postcss-cli-10.1.0/test/fixtures/glob/s.css 0000664 0000000 0000000 00000000024 14341470641 0020563 0 ustar 00root root 0000000 0000000 .a {
color: red
}
postcss-cli-10.1.0/test/fixtures/import.css 0000664 0000000 0000000 00000000023 14341470641 0020707 0 ustar 00root root 0000000 0000000 @import "./a.css";
postcss-cli-10.1.0/test/fixtures/import.sss 0000664 0000000 0000000 00000000020 14341470641 0020724 0 ustar 00root root 0000000 0000000 @import 'a.sss'
postcss-cli-10.1.0/test/fixtures/s.css 0000664 0000000 0000000 00000000024 14341470641 0017640 0 ustar 00root root 0000000 0000000 .a {
color: red
}
postcss-cli-10.1.0/test/fixtures/unchanged-input.css 0000664 0000000 0000000 00000000027 14341470641 0022472 0 ustar 00root root 0000000 0000000 body {
color: red;
}
postcss-cli-10.1.0/test/fixtures/unchanged-output.css 0000664 0000000 0000000 00000000435 14341470641 0022676 0 ustar 00root root 0000000 0000000 body {
color: red;
}
/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInVuY2hhbmdlZC1pbnB1dC5jc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEiLCJmaWxlIjoidW5jaGFuZ2VkLW91dHB1dC5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyJib2R5IHtcbiAgY29sb3I6IHJlZDtcbn1cbiJdfQ== */ postcss-cli-10.1.0/test/glob.js 0000664 0000000 0000000 00000001236 14341470641 0016302 0 ustar 00root root 0000000 0000000 import test from 'ava'
import path from 'path'
import cli from './helpers/cli.js'
import tmp from './helpers/tmp.js'
import read from './helpers/read.js'
test('works with glob patterns', async (t) => {
const output = tmp()
const { error, stderr } = await cli([
'test/fixtures/glob/*.css',
'-d',
output,
'--no-map',
])
t.falsy(error, stderr)
t.is(
await read(path.join(output, 'a.css')),
await read('test/fixtures/glob/a.css')
)
t.is(
await read(path.join(output, 'b.css')),
await read('test/fixtures/glob/b.css')
)
t.is(
await read(path.join(output, 's.css')),
await read('test/fixtures/glob/s.css')
)
})
postcss-cli-10.1.0/test/helpers/ 0000775 0000000 0000000 00000000000 14341470641 0016461 5 ustar 00root root 0000000 0000000 postcss-cli-10.1.0/test/helpers/clean.js 0000664 0000000 0000000 00000000252 14341470641 0020100 0 ustar 00root root 0000000 0000000 import fs from 'fs-extra'
Promise.all([
fs.emptyDir('./test/fixtures/.tmp/'),
fs.remove('./coverage'),
]).catch((err) => {
console.error(err)
process.exit(1)
})
postcss-cli-10.1.0/test/helpers/cli.js 0000664 0000000 0000000 00000000635 14341470641 0017572 0 ustar 00root root 0000000 0000000 import path from 'path'
import { exec } from 'child_process'
export default function (args, cwd) {
return new Promise((resolve) => {
exec(
`node ${path.resolve('index.js')} ${args.join(' ')}`,
{ cwd },
(error, stdout, stderr) => {
resolve({
code: error && error.code ? error.code : 0,
error,
stdout,
stderr,
})
}
)
})
}
postcss-cli-10.1.0/test/helpers/env.js 0000664 0000000 0000000 00000001007 14341470641 0017605 0 ustar 00root root 0000000 0000000 import fs from 'fs-extra'
import path from 'path'
import { globby } from 'globby'
import tmp from './tmp.js'
export default function (config, fixtures = '**/*', extension = 'cjs') {
const dir = tmp()
return Promise.all([
globby(fixtures, { cwd: 'test/fixtures' }).then((list) => {
return list.map((item) => {
return fs.copy(path.join('test/fixtures', item), path.join(dir, item))
})
}),
fs.outputFile(path.join(dir, `postcss.config.${extension}`), config),
]).then(() => dir)
}
postcss-cli-10.1.0/test/helpers/read.js 0000664 0000000 0000000 00000000300 14341470641 0017723 0 ustar 00root root 0000000 0000000 import fs from 'fs-extra'
export default function (path) {
return fs.readFile(path, 'utf8').then(
(content) => content.replace(/\r\n/g, '\n') // normalize line endings on Windows
)
}
postcss-cli-10.1.0/test/helpers/tmp.js 0000664 0000000 0000000 00000000246 14341470641 0017621 0 ustar 00root root 0000000 0000000 import path from 'path'
import { v4 as uuid } from 'uuid'
export default function (ext) {
ext = ext || ''
return path.join('test/fixtures/.tmp', uuid(), ext)
}
postcss-cli-10.1.0/test/map.js 0000664 0000000 0000000 00000002166 14341470641 0016137 0 ustar 00root root 0000000 0000000 import test from 'ava'
import fs from 'fs-extra'
import cli from './helpers/cli.js'
import tmp from './helpers/tmp.js'
import read from './helpers/read.js'
test('inline maps are generated by default', async (t) => {
const output = tmp('output.css')
const { error, stderr } = await cli([
'test/fixtures/import.css',
'-u',
'postcss-import',
'-o',
output,
])
t.falsy(error, stderr)
t.regex(await read(output), /\/*# sourceMappingURL=/)
})
test('--map generates external sourcemaps', async (t) => {
const output = tmp('output.css')
const { error, stderr } = await cli([
'test/fixtures/import.css',
'-u',
'postcss-import',
'-o',
output,
'--map',
])
t.falsy(error, stderr)
t.truthy(await fs.pathExists(output.replace('.css', '.css.map')))
})
test('--no-map disables internal sourcemaps', async (t) => {
const output = tmp('output.css')
const { error, stderr } = await cli([
'test/fixtures/import.css',
'-u',
'postcss-import',
'-o',
output,
'--no-map',
])
t.falsy(error, stderr)
t.notRegex(await read(output), /\/*# sourceMappingURL=/)
})
postcss-cli-10.1.0/test/misc.js 0000664 0000000 0000000 00000000664 14341470641 0016316 0 ustar 00root root 0000000 0000000 import test from 'ava'
import cli from './helpers/cli.js'
test('--help', async (t) => {
const help = await cli(['--help'])
t.falsy(help.error)
t.truthy(help.stdout.length > 10, 'expected --help to output a help message')
})
test('--version', async (t) => {
const version = await cli(['--version'])
t.falsy(version.error)
t.truthy(
version.stdout.length > 5,
'expected --version to output version info'
)
})
postcss-cli-10.1.0/test/parser.js 0000664 0000000 0000000 00000000667 14341470641 0016662 0 ustar 00root root 0000000 0000000 import test from 'ava'
import cli from './helpers/cli.js'
import tmp from './helpers/tmp.js'
import read from './helpers/read.js'
test('--parser works', async (t) => {
const output = tmp('output.css')
const { error, stderr } = await cli([
'test/fixtures/a.sss',
'--parser',
'sugarss',
'-o',
output,
'--no-map',
])
t.falsy(error, stderr)
t.is(await read(output), await read('test/fixtures/s.css'))
})
postcss-cli-10.1.0/test/replace.js 0000664 0000000 0000000 00000001274 14341470641 0016774 0 ustar 00root root 0000000 0000000 import test from 'ava'
import fs from 'fs-extra'
import path from 'path'
import cli from './helpers/cli.js'
import tmp from './helpers/tmp.js'
import read from './helpers/read.js'
test('--replace works', async (t) => {
const dir = tmp()
const output = path.join(dir, 'output.css')
await Promise.all([
fs.copy('test/fixtures/import.css', output),
fs.copy('test/fixtures/a.css', path.join(dir, 'a.css')),
])
const { error, stderr } = await cli([
output.replace(/\\/g, '/'), // gotta keep globby happy on Windows
'--replace',
'-u',
'postcss-import',
'--no-map',
])
t.falsy(error, stderr)
t.is(await read(output), await read('test/fixtures/a.css'))
})
postcss-cli-10.1.0/test/stdin.js 0000664 0000000 0000000 00000001210 14341470641 0016470 0 ustar 00root root 0000000 0000000 import test from 'ava'
import fs from 'fs-extra'
import path from 'path'
import { exec } from 'child_process'
import tmp from './helpers/tmp.js'
import read from './helpers/read.js'
test.cb('reads from stdin', (t) => {
const output = tmp('output.css')
const cp = exec(
`node ${path.resolve('index.js')} -o ${output} --no-map`,
(error, stdout, stderr) => {
if (error) t.end(error, stderr)
Promise.all([read(output), read('test/fixtures/a.css')])
.then(([a, e]) => {
t.is(a, e)
t.end()
})
.catch(t.end)
}
)
fs.createReadStream('test/fixtures/a.css').pipe(cp.stdin)
})
postcss-cli-10.1.0/test/stdout.js 0000664 0000000 0000000 00000001166 14341470641 0016703 0 ustar 00root root 0000000 0000000 import test from 'ava'
import fs from 'fs-extra'
import path from 'path'
import { exec } from 'child_process'
import read from './helpers/read.js'
test.cb('writes to stdout', (t) => {
const cp = exec(
`node ${path.resolve(
'index.js'
)} --parser sugarss -u postcss-import --no-map`,
(error, stdout, stderr) => {
if (error) t.end(error, stderr)
Promise.all([stdout.replace(/\r\n/g, '\n'), read('test/fixtures/s.css')])
.then(([a, e]) => {
t.is(a, e)
t.end()
})
.catch(t.end)
}
)
fs.createReadStream('./test/fixtures/a.sss').pipe(cp.stdin)
})
postcss-cli-10.1.0/test/stringifier.js 0000664 0000000 0000000 00000000701 14341470641 0017700 0 ustar 00root root 0000000 0000000 import test from 'ava'
import cli from './helpers/cli.js'
import tmp from './helpers/tmp.js'
import read from './helpers/read.js'
test('--stringifier works', async (t) => {
const output = tmp('output.sss')
const { error, stderr } = await cli([
'test/fixtures/a.css',
'--stringifier',
'sugarss',
'-o',
output,
'--no-map',
])
t.falsy(error, stderr)
t.is(await read(output), await read('test/fixtures/a.sss'))
})
postcss-cli-10.1.0/test/syntax.js 0000664 0000000 0000000 00000000667 14341470641 0016714 0 ustar 00root root 0000000 0000000 import test from 'ava'
import cli from './helpers/cli.js'
import tmp from './helpers/tmp.js'
import read from './helpers/read.js'
test('--syntax works', async (t) => {
const output = tmp('output.sss')
const { error, stderr } = await cli([
'test/fixtures/a.sss',
'--syntax',
'sugarss',
'-o',
output,
'--no-map',
])
t.falsy(error, stderr)
t.is(await read(output), await read('test/fixtures/a.sss'))
})
postcss-cli-10.1.0/test/unchanged.js 0000664 0000000 0000000 00000000747 14341470641 0017321 0 ustar 00root root 0000000 0000000 import fs from 'fs-extra'
import test from 'ava'
import cli from './helpers/cli.js'
test('files are not saved if the contents are the same', async (t) => {
const input = 'test/fixtures/unchanged-input.css'
const output = 'test/fixtures/unchanged-output.css'
const intialStat = await fs.stat(output)
const { error, stderr } = await cli([input, '-o', output])
t.falsy(error, stderr)
const finalStat = await fs.stat(output)
t.is(finalStat.mtimeMs, intialStat.mtimeMs)
})
postcss-cli-10.1.0/test/use.js 0000664 0000000 0000000 00000000665 14341470641 0016160 0 ustar 00root root 0000000 0000000 import test from 'ava'
import cli from './helpers/cli.js'
import tmp from './helpers/tmp.js'
import read from './helpers/read.js'
test('--use works', async (t) => {
const output = tmp('i.css')
const { error, stderr } = await cli([
'test/fixtures/import.css',
'-u',
'postcss-import',
'-o',
output,
'--no-map',
])
t.falsy(error, stderr)
t.is(await read(output), await read('test/fixtures/a.css'))
})
postcss-cli-10.1.0/test/watch.js 0000664 0000000 0000000 00000032425 14341470641 0016471 0 ustar 00root root 0000000 0000000 import test from 'ava'
import fs from 'fs-extra'
import path from 'path'
import { exec, spawn } from 'child_process'
import chokidar from 'chokidar'
import ENV from './helpers/env.js'
import read from './helpers/read.js'
import tmp from './helpers/tmp.js'
// XXX: All the tests in this file are skipped on the Windows CI; too flacky there
const testCb =
process.env.CI && process.platform === 'win32' ? test.cb.skip : test.cb
testCb('--watch works', (t) => {
let cp
t.plan(2)
ENV('', ['a.css'])
.then((dir) => {
// Init watcher:
const watcher = chokidar.watch('.', {
cwd: dir,
ignoreInitial: true,
awaitWriteFinish: true,
})
// On the first output:
watcher.on('add', (p) => {
// Assert, then change the source file
if (p === 'output.css') {
isEqual(p, 'test/fixtures/a.css')
.then(() => read('test/fixtures/b.css'))
.then((css) => fs.writeFile(path.join(dir, 'a.css'), css))
.catch(done)
}
})
// When the change is picked up:
watcher.on('change', (p) => {
if (p === 'output.css') {
isEqual(p, 'test/fixtures/b.css')
.then(() => done())
.catch(done)
}
})
// Start postcss-cli:
watcher.on('ready', () => {
// Using exec() and quoting "*.css" to test watch's glob handling:
cp = exec(
`node ${path.resolve('index.js')} "*.css" -o output.css --no-map -w`,
{ cwd: dir }
)
cp.on('error', t.end)
cp.on('exit', (code) => {
if (code) t.end(code)
})
})
// Helper functions:
function isEqual(p, expected) {
return Promise.all([read(path.join(dir, p)), read(expected)]).then(
([a, e]) => t.is(a, e)
)
}
function done(err) {
try {
cp.kill()
} catch {}
t.end(err)
}
})
.catch(t.end)
})
testCb('--watch dependencies', (t) => {
let cp
t.plan(2)
ENV('', ['import.css', 'a.css'])
.then((dir) => {
// Init watcher:
const watcher = chokidar.watch('.', {
cwd: dir,
ignoreInitial: true,
awaitWriteFinish: true,
})
// On the first output:
watcher.on('add', (p) => {
// Assert, then change the source file
if (p === 'output.css') {
isEqual(p, 'test/fixtures/a.css')
.then(() => read('test/fixtures/b.css'))
.then((css) => fs.writeFile(path.join(dir, 'a.css'), css))
.catch(done)
}
})
// When the change is picked up:
watcher.on('change', (p) => {
if (p === 'output.css') {
isEqual(p, 'test/fixtures/b.css')
.then(() => done())
.catch(done)
}
})
// Start postcss-cli:
watcher.on('ready', () => {
cp = exec(
`node ${path.resolve(
'index.js'
)} import.css -o output.css -u postcss-import -w --no-map`,
{ cwd: dir }
)
cp.on('error', t.end)
cp.on('exit', (code) => {
if (code) t.end(code)
})
})
// Helper functions:
function isEqual(p, expected) {
return Promise.all([read(path.join(dir, p)), read(expected)]).then(
([a, e]) => t.is(a, e)
)
}
function done(err) {
try {
cp.kill()
} catch {}
t.end(err)
}
})
.catch(t.end)
})
// Doesn't work on CI for some reason
;(process.env.CI ? test.cb.skip : test.cb)(
"--watch doesn't exit on CssSyntaxError",
(t) => {
t.plan(0)
ENV('', ['a.css'])
.then((dir) => {
// Init watcher:
const watcher = chokidar.watch('.', {
cwd: dir,
ignoreInitial: true,
awaitWriteFinish: true,
})
watcher.on('add', (p) => {
if (p === 'output.css') {
// Change to invalid CSS
fs.writeFile(path.join(dir, 'a.css'), '.a { color: red').catch(done)
}
})
let killed = false
const cp = exec(
`node ${path.resolve(
'index.js'
)} a.css -o output.css -u postcss-import -w --no-map`,
{ cwd: dir }
)
cp.on('error', t.end)
cp.stderr.on('data', (chunk) => {
// When error message is printed, kill the process after a timeout
if (~chunk.indexOf('Unclosed block')) {
setTimeout(() => {
killed = true
cp.kill()
}, 1000)
}
})
cp.on('exit', (code) => {
if (!killed)
return t.end(`Should not exit (exited with code ${code})`)
done()
})
function done(err) {
try {
cp.kill()
} catch {}
t.end(err)
}
})
.catch(t.end)
}
)
testCb('--watch does exit on closing stdin (Ctrl-D/EOF)', (t) => {
t.plan(1)
const cp = spawn(`./index.js test/fixtures/a.css -o ${tmp()} -w --no-map`, {
shell: true,
env: {
...process.env,
FORCE_IS_TTY: true,
},
})
cp.on('error', t.end)
cp.on('exit', (code) => {
t.is(code, 0)
t.end()
})
cp.stdin.end()
})
testCb('--watch watches dependencies', (t) => {
let cp
t.plan(2)
ENV('', ['s.css', 'a.css', 'b.css']).then((dir) => {
fs.writeFile(
path.join(dir, 'postcss.config.cjs'),
`
const fs = require('fs')
module.exports = {
plugins: [
(root, result) => {
const file = '${path.resolve(dir, 'a.css')}'
result.messages.push({
plugin: 'test',
type: 'dependency',
file,
parent: result.opts.from,
})
root.nodes = []
root.append(fs.readFileSync(file, 'utf8'))
return root
}
]
}
`
)
.then(() => {
// Init watcher:
const watcher = chokidar.watch('.', {
cwd: dir,
ignoreInitial: true,
awaitWriteFinish: true,
})
// On the first output:
watcher.on('add', (p) => {
// Assert, then change the source file
if (p === 'output.css') {
isEqual(p, 'test/fixtures/a.css')
.then(() => read('test/fixtures/b.css'))
.then((css) => fs.writeFile(path.join(dir, 'a.css'), css))
.catch(done)
}
})
// When the change is picked up:
watcher.on('change', (p) => {
if (p === 'output.css') {
isEqual(p, 'test/fixtures/b.css')
.then(() => done())
.catch(done)
}
})
// Start postcss-cli:
watcher.on('ready', () => {
// Using exec() and quoting "*.css" to test watch's glob handling:
cp = exec(
`node ${path.resolve(
'index.js'
)} "s.css" -o output.css --no-map -w`,
{ cwd: dir }
)
cp.on('error', t.end)
cp.on('exit', (code) => {
if (code) t.end(code)
})
})
// Helper functions:
function isEqual(p, expected) {
return Promise.all([read(path.join(dir, p)), read(expected)]).then(
([a, e]) => t.is(a, e)
)
}
function done(err) {
try {
cp.kill()
} catch {}
t.end(err)
}
})
.catch(t.end)
})
})
testCb('--watch watches directory dependencies', (t) => {
let cp
t.plan(2)
ENV('', ['s.css', 'base/level-1/b.css', 'base/level-1/level-2/a.css']).then(
(dir) => {
fs.writeFile(
path.join(dir, 'postcss.config.cjs'),
`
const fs = require('fs')
module.exports = {
plugins: [
(root, result) => {
result.messages.push({
plugin: 'test',
type: 'dir-dependency',
dir: '${path.resolve(dir, 'base')}',
parent: result.opts.from,
})
root.nodes = []
root.append(fs.readFileSync('${path.resolve(
dir,
'base/level-1/level-2/a.css'
)}', 'utf8'))
return root
}
]
}
`
)
.then(() => {
// Init watcher:
const watcher = chokidar.watch('.', {
cwd: dir,
ignoreInitial: true,
awaitWriteFinish: true,
})
// On the first output:
watcher.on('add', (p) => {
// Assert, then change the source file
if (p === 'output.css') {
isEqual(p, 'test/fixtures/base/level-1/level-2/a.css')
.then(() => read('test/fixtures/base/level-1/b.css'))
.then((css) =>
fs.writeFile(
path.join(dir, 'base/level-1/level-2/a.css'),
css
)
)
.catch(done)
}
})
// When the change is picked up:
watcher.on('change', (p) => {
if (p === 'output.css') {
isEqual(p, 'test/fixtures/base/level-1/b.css')
.then(() => done())
.catch(done)
}
})
// Start postcss-cli:
watcher.on('ready', () => {
// Using exec() and quoting "*.css" to test watch's glob handling:
cp = exec(
`node ${path.resolve(
'index.js'
)} "s.css" -o output.css --no-map -w`,
{ cwd: dir }
)
cp.on('error', t.end)
cp.on('exit', (code) => {
if (code) t.end(code)
})
})
// Helper functions:
function isEqual(p, expected) {
return Promise.all([read(path.join(dir, p)), read(expected)]).then(
([a, e]) => t.is(a, e)
)
}
function done(err) {
try {
cp.kill()
} catch {}
t.end(err)
}
})
.catch(t.end)
}
)
})
testCb(
'--watch applies glob on dir-dependency (and excludes non matching files)',
(t) => {
let cp
let modifying = null // one of "unrelated.md", "a.css"
t.plan(1)
ENV('', [
's.css',
'base/level-1/b.css',
'base/level-1/level-2/a.css',
'base/level-1/level-2/unrelated.md',
]).then((dir) => {
fs.writeFile(
path.join(dir, 'postcss.config.cjs'),
`
const fs = require('fs')
module.exports = {
plugins: [
(root, result) => {
result.messages.push({
plugin: 'test',
type: 'dir-dependency',
dir: '${path.resolve(dir, 'base')}',
glob: '**/*.css',
parent: result.opts.from,
})
root.nodes = []
root.append(fs.readFileSync('${path.resolve(
dir,
'base/level-1/level-2/a.css'
)}', 'utf8'))
return root
}
]
}
`
)
.then(() => {
// Init watcher:
const watcher = chokidar.watch('.', {
cwd: dir,
ignoreInitial: true,
awaitWriteFinish: true,
})
// On the first output:
watcher.on('add', (p) => {
if (p === 'output.css') {
// Modify unwatched file, shouldn't trigger output
modifyUnwatched()
}
})
// When the change is picked up:
watcher.on('change', (p) => {
if (p === 'output.css') {
// Assert that change to output.css happened only after modifying the watched a.css
t.is(
modifying,
'a.css',
`Unexpected change to ${p} after modifying ${modifying}`
)
done()
} else if (p === 'base/level-1/level-2/unrelated.md') {
// Modify watched file next, should trigger output
setTimeout(modifyWatched, 250)
}
})
// Start postcss-cli:
watcher.on('ready', () => {
cp = exec(
`node ${path.resolve(
'index.js'
)} "s.css" -o output.css --no-map -w`,
{ cwd: dir }
)
cp.on('error', t.end)
cp.on('exit', (code) => {
if (code) t.end(code)
})
})
function modifyUnwatched() {
modifying = 'unrelated.md'
fs.writeFile(
path.join(dir, 'base/level-1/level-2/unrelated.md'),
'Some modification'
).catch(done)
}
function modifyWatched() {
modifying = 'a.css'
fs.writeFile(
path.join(dir, 'base/level-1/level-2/a.css'),
'a { color: hotpink }'
).catch(done)
}
function done(err) {
try {
cp.kill()
} catch {}
t.end(err)
}
})
.catch(t.end)
})
}
)