node_modules

This commit is contained in:
saeid
2019-07-15 13:07:31 +04:30
parent d3735c6d30
commit ce1a3ebf9c
35713 changed files with 3639219 additions and 1 deletions
+61
View File
@@ -0,0 +1,61 @@
# Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="2.0.0"></a>
# [2.0.0](https://github.com/michael-ciniawsky/postcss-load-config/compare/v1.2.0...v2.0.0) (2018-07-10)
### Bug Fixes
* **package:** `require-from-string` memory leak, updates `cosmiconfig` v2.1.0...4.0.0 (`dependencies`) ([17f9621](https://github.com/michael-ciniawsky/postcss-load-config/commit/17f9621))
* **src/index.js:** clone the config `{Object}` on assignment instead of mutating it ([8669a90](https://github.com/michael-ciniawsky/postcss-load-config/commit/8669a90))
### Features
* **src:** load plugins from the current working directory ([9745bf0](https://github.com/michael-ciniawsky/postcss-load-config/commit/9745bf0))
* **src:** show config file in `err.message` ([4baff47](https://github.com/michael-ciniawsky/postcss-load-config/commit/4baff47))
### BREAKING CHANGES
* **package:** requires `node >= v4.0.0`
* **package:** removes `argv` option (`options.argv`)
* **package:** removes `--config` parsing
<a name="1.2.0"></a>
# [1.2.0](https://github.com/michael-ciniawsky/postcss-load-config/compare/v1.1.0...v1.2.0) (2017-02-13)
### Features
* **index:** allow extensions for .postcssrc ([0d3bf35](https://github.com/michael-ciniawsky/postcss-load-config/commit/0d3bf35))
<a name="1.1.0"></a>
# [1.1.0](https://github.com/michael-ciniawsky/postcss-load-config/compare/v1.0.0...v1.1.0) (2017-01-11)
### Features
* **index:** config.file, improve error handling ([a6c32fd](https://github.com/michael-ciniawsky/postcss-load-config/commit/a6c32fd))
<a name="1.0.0"></a>
# [1.0.0]((https://github.com/michael-ciniawsky/postcss-load-config/compare/v1.0.0-rc...1.0.0)) (2016-10-27)
### Bug Fixes
* **index:** behavior when config loading fails ([b549bc6](https://github.com/michael-ciniawsky/postcss-load-config/commit/b549bc6)), closes [#26](https://github.com/michael-ciniawsky/postcss-load-config/issues/26)
* **index:** set NODE_ENV when undefined ([b24501c](https://github.com/michael-ciniawsky/postcss-load-config/commit/b24501c))
* **index:** support node v0.12 ([0bbfa94](https://github.com/michael-ciniawsky/postcss-load-config/commit/0bbfa94))
### Features
* **index:** function support, jsdoc, cleanups ([a78c580](https://github.com/michael-ciniawsky/postcss-load-config/commit/a78c580))
+21
View File
@@ -0,0 +1,21 @@
License (MIT)
Copyright (c) Michael Ciniawsky <michael.ciniawsky@gmail.com>
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.
+468
View File
@@ -0,0 +1,468 @@
[![npm][npm]][npm-url]
[![node][node]][node-url]
[![deps][deps]][deps-url]
[![test][test]][test-url]
[![coverage][cover]][cover-url]
[![code style][style]][style-url]
[![chat][chat]][chat-url]
<div align="center">
<img width="100" height="100" title="Load Options" src="http://michael-ciniawsky.github.io/postcss-load-options/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>
<img width="100" height="100" title="Load Plugins" src="http://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg">
<h1>Load Config</h1>
</div>
<h2 align="center">Install</h2>
```bash
npm i -D postcss-load-config
```
<h2 align="center">Usage</h2>
```bash
npm i -S|-D postcss-plugin
```
Install all required postcss plugins and save them to your **package.json** `dependencies`/`devDependencies`
Then create a postcss config file by choosing one of the following formats
### `package.json`
Create a **`postcss`** section in your projects **`package.json`**
```
Project (Root)
|– client
|– public
|
|- package.json
```
```json
{
"postcss": {
"parser": "sugarss",
"map": false,
"plugins": {
"postcss-plugin": {}
}
}
}
```
### `.postcssrc`
Create a **`.postcssrc`** file in JSON or YAML format
> ℹ️ It's recommended to use an extension (e.g **`.postcssrc.json`** or **`.postcssrc.yml`**) instead of `.postcssrc`
```
Project (Root)
|– client
|– public
|
|- (.postcssrc|.postcssrc.json|.postcssrc.yml)
|- package.json
```
**`.postcssrc.json`**
```json
{
"parser": "sugarss",
"map": false,
"plugins": {
"postcss-plugin": {}
}
}
```
**`.postcssrc.yml`**
```yaml
parser: sugarss
map: false
plugins:
postcss-plugin: {}
```
### `.postcssrc.js` or `postcss.config.js`
You may need some logic within your config. In this case create JS file named **`.postcssrc.js`** or **`postcss.config.js`**
```
Project (Root)
|– client
|– public
|
|- (.postcssrc.js|postcss.config.js)
|- package.json
```
You can export the config as an `{Object}`
**.postcssrc.js**
```js
module.exports = {
parser: 'sugarss',
map: false,
plugins: {
'postcss-plugin': {}
}
}
```
Or export a `{Function}` that returns the config (more about the `ctx` param below)
**.postcssrc.js**
```js
module.exports = (ctx) => ({
parser: ctx.parser ? 'sugarss' : false,
map: ctx.env === 'development' ? ctx.map : false,
plugins: {
'postcss-plugin': ctx.options.plugin
}
})
```
Plugins can be loaded either using an `{Object}` or an `{Array}`
#### `{Object}`
**.postcssrc.js**
```js
module.exports = ({ env }) => ({
...options
plugins: {
'postcss-plugin': env === 'production' ? {} : false
}
})
```
#### `{Array}`
**.postcssrc.js**
```js
module.exports = ({ env }) => ({
...options
plugins: [
env === 'production' ? require('postcss-plugin')() : false
]
})
```
> :warning: When using an `{Array}`, make sure to `require()` each plugin
<h2 align="center">Options</h2>
|Name|Type|Default|Description|
|:--:|:--:|:-----:|:----------|
|[**`to`**](#to)|`{String}`|`undefined`|Destination File Path|
|[**`map`**](#map)|`{String\|Object}`|`false`|Enable/Disable Source Maps|
|[**`from`**](#from)|`{String}`|`undefined`|Source File Path|
|[**`parser`**](#parser)|`{String\|Function}`|`false`|Custom PostCSS Parser|
|[**`syntax`**](#syntax)|`{String\|Function}`|`false`|Custom PostCSS Syntax|
|[**`stringifier`**](#stringifier)|`{String\|Function}`|`false`|Custom PostCSS Stringifier|
### `parser`
**.postcssrc.js**
```js
module.exports = {
parser: 'sugarss'
}
```
### `syntax`
**.postcssrc.js**
```js
module.exports = {
syntax: 'postcss-scss'
}
```
### `stringifier`
**.postcssrc.js**
```js
module.exports = {
stringifier: 'midas'
}
```
### [**`map`**](https://github.com/postcss/postcss/blob/master/docs/source-maps.md)
**.postcssrc.js**
```js
module.exports = {
map: 'inline'
}
```
> :warning: In most cases `options.from` && `options.to` are set by the third-party which integrates this package (CLI, gulp, webpack). It's unlikely one needs to set/use `options.from` && `options.to` within a config file. Unless you're a third-party plugin author using this module and its Node API directly **dont't set `options.from` && `options.to` yourself**
### `to`
```js
module.exports = {
to: 'path/to/dest.css'
}
```
### `from`
```js
module.exports = {
from: 'path/to/src.css'
}
```
<h2 align="center">Plugins</h2>
### `{} || null`
The plugin will be loaded with defaults
```js
'postcss-plugin': {} || null
```
**.postcssrc.js**
```js
module.exports = {
plugins: {
'postcss-plugin': {} || null
}
}
```
> :warning: `{}` must be an **empty** `{Object}` literal
### `{Object}`
The plugin will be loaded with given options
```js
'postcss-plugin': { option: '', option: '' }
```
**.postcssrc.js**
```js
module.exports = {
plugins: {
'postcss-plugin': { option: '', option: '' }
}
}
```
### `false`
The plugin will not be loaded
```js
'postcss-plugin': false
```
**.postcssrc.js**
```js
module.exports = {
plugins: {
'postcss-plugin': false
}
}
```
### `Ordering`
Plugin **execution order** is determined by declaration in the plugins section (**top-down**)
```js
{
plugins: {
'postcss-plugin': {}, // [0]
'postcss-plugin': {}, // [1]
'postcss-plugin': {} // [2]
}
}
```
<h2 align="center">Context</h2>
When using a `{Function}` (`postcss.config.js` or `.postcssrc.js`), it's possible to pass context to `postcss-load-config`, which will be evaluated while loading your config. By default `ctx.env (process.env.NODE_ENV)` and `ctx.cwd (process.cwd())` are available on the `ctx` `{Object}`
> ℹ️ Most third-party integrations add additional properties to the `ctx` (e.g `postcss-loader`). Check the specific module's README for more information about what is available on the respective `ctx`
<h2 align="center">Examples</h2>
**postcss.config.js**
```js
module.exports = (ctx) => ({
parser: ctx.parser ? 'sugarss' : false,
map: ctx.env === 'development' ? ctx.map : false,
plugins: {
'postcss-import': {},
'postcss-nested': {},
cssnano: ctx.env === 'production' ? {} : false
}
})
```
<div align="center">
<img width="80" height="80" src="https://worldvectorlogo.com/logos/nodejs-icon.svg">
</div>
```json
"scripts": {
"build": "NODE_ENV=production node postcss",
"start": "NODE_ENV=development node postcss"
}
```
```js
const { readFileSync } = require('fs')
const postcss = require('postcss')
const postcssrc = require('postcss-load-config')
const css = readFileSync('index.sss', 'utf8')
const ctx = { parser: true, map: 'inline' }
postcssrc(ctx).then(({ plugins, options }) => {
postcss(plugins)
.process(css, options)
.then((result) => console.log(result.css))
})
```
<div align="center">
<img width="80" height="80" halign="10" src="https://worldvectorlogo.com/logos/gulp.svg">
</div>
```json
"scripts": {
"build": "NODE_ENV=production gulp",
"start": "NODE_ENV=development gulp"
}
```
```js
const { task, src, dest, series, watch } = require('gulp')
const postcss = require('gulp-postcssrc')
const css = () => {
src('src/*.css')
.pipe(postcss())
.pipe(dest('dest'))
})
task('watch', () => {
watch(['src/*.css', 'postcss.config.js'], css)
})
task('default', series(css, 'watch'))
```
<div align="center">
<img width="80" height="80" src="https://cdn.rawgit.com/webpack/media/e7485eb2/logo/icon.svg">
</div>
```json
"scripts": {
"build": "NODE_ENV=production webpack",
"start": "NODE_ENV=development webpack-dev-server"
}
```
**webpack.config.js**
```js
module.exports = (env) => ({
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
}
]
}
})
```
<h2 align="center">Maintainers</h2>
<table>
<tbody>
<tr>
<td align="center">
<img width="150" height="150"
src="https://github.com/michael-ciniawsky.png?v=3&s=150">
<br />
<a href="https://github.com/michael-ciniawsky">Michael Ciniawsky</a>
</td>
<td align="center">
<img width="150" height="150"
src="https://github.com/ertrzyiks.png?v=3&s=150">
<br />
<a href="https://github.com/ertrzyiks">Mateusz Derks</a>
</td>
</tr>
<tbody>
</table>
<h2 align="center">Contributors</h2>
<table>
<tbody>
<tr>
<td align="center">
<img width="150" height="150"
src="https://github.com/sparty02.png?v=3&s=150">
<br />
<a href="https://github.com/sparty02">Ryan Dunckel</a>
</td>
<td align="center">
<img width="150" height="150"
src="https://github.com/pcgilday.png?v=3&s=150">
<br />
<a href="https://github.com/pcgilday">Patrick Gilday</a>
</td>
<td align="center">
<img width="150" height="150"
src="https://github.com/daltones.png?v=3&s=150">
<br />
<a href="https://github.com/daltones">Dalton Santos</a>
</td>
</tr>
<tbody>
</table>
[npm]: https://img.shields.io/npm/v/postcss-load-config.svg
[npm-url]: https://npmjs.com/package/postcss-load-config
[node]: https://img.shields.io/node/v/postcss-load-plugins.svg
[node-url]: https://nodejs.org/
[deps]: https://david-dm.org/michael-ciniawsky/postcss-load-config.svg
[deps-url]: https://david-dm.org/michael-ciniawsky/postcss-load-config
[test]: http://img.shields.io/travis/michael-ciniawsky/postcss-load-config.svg
[test-url]: https://travis-ci.org/michael-ciniawsky/postcss-load-config
[cover]: https://coveralls.io/repos/github/michael-ciniawsky/postcss-load-config/badge.svg
[cover-url]: https://coveralls.io/github/michael-ciniawsky/postcss-load-config
[style]: https://img.shields.io/badge/code%20style-standard-yellow.svg
[style-url]: http://standardjs.com/
[chat]: https://img.shields.io/gitter/room/postcss/postcss.svg
[chat-url]: https://gitter.im/postcss/postcss
+83
View File
@@ -0,0 +1,83 @@
# Changelog
## 4.0.0
- Licensing improvement: updated `parse-json` from `3.0.0` to `4.0.0`(see [sindresorhus/parse-json#12][parse-json-pr-12]).
- Changed: error message format for `JSON` parse errors(see [#101][pr-101]). If you were relying on the format of JSON-parsing error messages, this will be a breaking change for you.
- Changed: set default for `searchPath` as `process.cwd()` in `explorer.load`.
## 3.1.0
- Added: infer format based on filePath
## 3.0.1
- Fixed: memory leak due to bug in `require-from-string`.
- Added: for JSON files, append position to end of error message.
## 3.0.0
- Removed: support for loading config path using the `--config` flag. cosmiconfig will not parse command line arguments. Your application can parse command line arguments and pass them to cosmiconfig.
- Removed: `argv` config option.
- Removed: support for Node versions < 4.
- Added: `sync` option.
- Fixed: Throw a clear error on getting empty config file.
- Fixed: when a `options.configPath` is `package.json`, return the package prop, not the entire JSON file.
## 2.2.2
- Fixed: `options.configPath` and `--config` flag are respected.
## 2.2.0, 2.2.1
- 2.2.0 included a number of improvements but somehow broke stylelint. The changes were reverted in 2.2.1, to be restored later.
## 2.1.3
- Licensing improvement: switched from `json-parse-helpfulerror` to `parse-json`.
## 2.1.2
- Fixed: bug where an `ENOENT` error would be thrown is `searchPath` referenced a non-existent file.
- Fixed: JSON parsing errors in Node v7.
## 2.1.1
- Fixed: swapped `graceful-fs` for regular `fs`, fixing a garbage collection problem.
## 2.1.0
- Added: Node 0.12 support.
## 2.0.2
- Fixed: Node version specified in `package.json`.
## 2.0.1
- Fixed: no more infinite loop in Windows.
## 2.0.0
- Changed: module now creates cosmiconfig instances with `load` methods (see README).
- Added: caching (enabled by the change above).
- Removed: support for Node versions <4.
## 1.1.0
- Add `rcExtensions` option.
## 1.0.2
- Fix handling of `require()`'s within JS module configs.
## 1.0.1
- Switch Promise implementation to pinkie-promise.
## 1.0.0
- Initial release.
[parse-json-pr-12]: https://github.com/sindresorhus/parse-json/pull/12
[pr-101]: https://github.com/davidtheclark/cosmiconfig/pull/101
+22
View File
@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 David Clark
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.
+243
View File
@@ -0,0 +1,243 @@
# cosmiconfig
[![Build Status](https://img.shields.io/travis/davidtheclark/cosmiconfig/master.svg?label=unix%20build)](https://travis-ci.org/davidtheclark/cosmiconfig) [![Build status](https://img.shields.io/appveyor/ci/davidtheclark/cosmiconfig/master.svg?label=windows%20build)](https://ci.appveyor.com/project/davidtheclark/cosmiconfig/branch/master)
Find and load a configuration object from
- a `package.json` property (anywhere up the directory tree)
- a JSON or YAML "rc file" (anywhere up the directory tree)
- a `.config.js` CommonJS module (anywhere up the directory tree)
For example, if your module's name is "soursocks," cosmiconfig will search out configuration in the following places:
- a `soursocks` property in `package.json` (anywhere up the directory tree)
- a `.soursocksrc` file in JSON or YAML format (anywhere up the directory tree)
- a `soursocks.config.js` file exporting a JS object (anywhere up the directory tree)
cosmiconfig continues to search in these places all the way up the directory tree until it finds acceptable configuration (or hits the home directory).
Additionally, all of these search locations are configurable: you can customize filenames or turn off any location.
You can also look for rc files with extensions, e.g. `.soursocksrc.json` or `.soursocksrc.yaml`.
You may like extensions on your rc files because you'll get syntax highlighting and linting in text editors.
## Installation
```
npm install cosmiconfig
```
Tested in Node 4+.
## Usage
```js
var cosmiconfig = require('cosmiconfig');
var explorer = cosmiconfig(yourModuleName[, options]);
explorer.load()
.then((result) => {
// result.config is the parsed configuration object
// result.filepath is the path to the config file that was found
})
.catch((parsingError) => {
// do something constructive
});
```
The function `cosmiconfig()` searches for a configuration object and returns a Promise,
which resolves with an object containing the information you're looking for.
You can also pass option `sync: true` to load the config synchronously, returning the config itself.
So let's say `var yourModuleName = 'goldengrahams'` — here's how cosmiconfig will work:
- Starting from `process.cwd()` (or some other directory defined by the `searchPath` argument to `load()`), it looks for configuration objects in three places, in this order:
1. A `goldengrahams` property in a `package.json` file (or some other property defined by `options.packageProp`);
2. A `.goldengrahamsrc` file with JSON or YAML syntax (or some other filename defined by `options.rc`);
3. A `goldengrahams.config.js` JS file exporting the object (or some other filename defined by `options.js`).
- If none of those searches reveal a configuration object, it moves up one directory level and tries again. So the search continues in `./`, `../`, `../../`, `../../../`, etc., checking those three locations in each directory.
- It continues searching until it arrives at your home directory (or some other directory defined by `options.stopDir`).
- If at any point a parseable configuration is found, the `cosmiconfig()` Promise resolves with its result object.
- If no configuration object is found, the `cosmiconfig()` Promise resolves with `null`.
- If a configuration object is found *but is malformed* (causing a parsing error), the `cosmiconfig()` Promise rejects and shares that error (so you should `.catch()` it).
All this searching can be short-circuited by passing `options.configPath` to specify a file.
cosmiconfig will read that file and try parsing it as JSON, YAML, or JS.
## Caching
As of v2, cosmiconfig uses a few caches to reduce the need for repetitious reading of the filesystem. Every new cosmiconfig instance (created with `cosmiconfig()`) has its own caches.
To avoid or work around caching, you can
- create separate instances of cosmiconfig, or
- set `cache: false` in your options.
- use the cache clearing methods documented below.
## API
### `var explorer = cosmiconfig(moduleName[, options])`
Creates a cosmiconfig instance (i.e. explorer) configured according to the arguments, and initializes its caches.
#### moduleName
Type: `string`
You module name. This is used to create the default filenames that cosmiconfig will look for.
#### Options
##### packageProp
Type: `string` or `false`
Default: `'[moduleName]'`
Name of the property in `package.json` to look for.
If `false`, cosmiconfig will not look in `package.json` files.
##### rc
Type: `string` or `false`
Default: `'.[moduleName]rc'`
Name of the "rc file" to look for, which can be formatted as JSON or YAML.
If `false`, cosmiconfig will not look for an rc file.
If `rcExtensions: true`, the rc file can also have extensions that specify the syntax, e.g. `.[moduleName]rc.json`.
You may like extensions on your rc files because you'll get syntax highlighting and linting in text editors.
Also, with `rcExtensions: true`, you can use JS modules as rc files, e.g. `.[moduleName]rc.js`.
##### js
Type: `string` or `false`
Default: `'[moduleName].config.js'`
Name of a JS file to look for, which must export the configuration object.
If `false`, cosmiconfig will not look for a JS file.
##### rcStrictJson
Type: `boolean`
Default: `false`
If `true`, cosmiconfig will expect rc files to be strict JSON. No YAML permitted, and no sloppy JSON.
By default, rc files are parsed with [js-yaml](https://github.com/nodeca/js-yaml), which is
more permissive with punctuation than standard strict JSON.
##### rcExtensions
Type: `boolean`
Default: `false`
If `true`, cosmiconfig will look for rc files with extensions, in addition to rc files without.
This adds a few steps to the search process.
Instead of *just* looking for `.goldengrahamsrc` (no extension), it will also look for the following, in this order:
- `.goldengrahamsrc.json`
- `.goldengrahamsrc.yaml`
- `.goldengrahamsrc.yml`
- `.goldengrahamsrc.js`
##### stopDir
Type: `string`
Default: Absolute path to your home directory
Directory where the search will stop.
##### cache
Type: `boolean`
Default: `true`
If `false`, no caches will be used.
##### sync
Type: `boolean`
Default: `false`
If `true`, config will be loaded synchronously.
##### transform
Type: `Function`
A function that transforms the parsed configuration. Receives the result object with `config` and `filepath` properties.
If the option `sync` is `false` (default), the function must return a Promise that resolves with the transformed result.
If the option `sync` is `true`, though, `transform` should be a synchronous function which returns the transformed result.
The reason you might use this option instead of simply applying your transform function some other way is that *the transformed result will be cached*. If your transformation involves additional filesystem I/O or other potentially slow processing, you can use this option to avoid repeating those steps every time a given configuration is loaded.
##### configPath
Type: `string`
If provided, cosmiconfig will load and parse a config from this path, and will not perform its usual search.
##### format
Type: `'json' | 'yaml' | 'js'`
The expected file format for the config loaded from `configPath`.
If not specified, cosmiconfig will try to infer the format using the extension name (if it has one).
In the event that the file does not have an extension or the extension is unrecognized, cosmiconfig will try to parse it as a JSON, YAML, or JS file.
### Instance methods (on `explorer`)
#### `load([searchPath, configPath])`
Find and load a configuration file. Returns a Promise that resolves with `null`, if nothing is found, or an object with two properties:
- `config`: The loaded and parsed configuration.
- `filepath`: The filepath where this configuration was found.
You should provide *either* `searchPath` *or* `configPath`. Use `configPath` if you know the path of the configuration file you want to load. Note that `configPath` takes priority over `searchPath` if both parameters are specified.
```js
explorer.load()
explorer.load('start/search/here');
explorer.load('start/search/at/this/file.css');
explorer.load(null, 'load/this/file.json');
```
If you provide `searchPath`, cosmiconfig will start its search at `searchPath` and continue to search up the directory tree, as documented above.
By default, `searchPath` is set to `process.cwd()`.
If you provide `configPath` (i.e. you already know where the configuration is that you want to load), cosmiconfig will try to read and parse that file. Note that the [`format` option](#format) is applicable for this as well.
#### `clearFileCache()`
Clears the cache used when you provide a `configPath` argument to `load`.
#### `clearDirectoryCache()`
Clears the cache used when you provide a `searchPath` argument to `load`.
#### `clearCaches()`
Performs both `clearFileCache()` and `clearDirectoryCache()`.
## Differences from [rc](https://github.com/dominictarr/rc)
[rc](https://github.com/dominictarr/rc) serves its focused purpose well. cosmiconfig differs in a few key ways — making it more useful for some projects, less useful for others:
- Looks for configuration in some different places: in a `package.json` property, an rc file, a `.config.js` file, and rc files with extensions.
- Built-in support for JSON, YAML, and CommonJS formats.
- Stops at the first configuration found, instead of finding all that can be found up the directory tree and merging them automatically.
- Options.
- Asynchronous by default (though can be run synchronously).
## Contributing & Development
Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
And please do participate!
@@ -0,0 +1,159 @@
//
'use strict';
const path = require('path');
const loadPackageProp = require('./loadPackageProp');
const loadRc = require('./loadRc');
const loadJs = require('./loadJs');
const loadDefinedFile = require('./loadDefinedFile');
const funcRunner = require('./funcRunner');
const getDirectory = require('./getDirectory');
module.exports = function createExplorer(options
) {
// When `options.sync` is `false` (default),
// these cache Promises that resolve with results, not the results themselves.
const fileCache = options.cache ? new Map() : null;
const directoryCache = options.cache ? new Map() : null;
const transform = options.transform || identity;
const packageProp = options.packageProp;
function clearFileCache() {
if (fileCache) fileCache.clear();
}
function clearDirectoryCache() {
if (directoryCache) directoryCache.clear();
}
function clearCaches() {
clearFileCache();
clearDirectoryCache();
}
function throwError(error) {
if (options.sync) {
throw error;
} else {
return Promise.reject(error);
}
}
function load(
searchPath ,
configPath
) {
if (!searchPath) searchPath = process.cwd();
if (!configPath && options.configPath) configPath = options.configPath;
if (configPath) {
const absoluteConfigPath = path.resolve(process.cwd(), configPath);
if (fileCache && fileCache.has(absoluteConfigPath)) {
return fileCache.get(absoluteConfigPath);
}
let load;
if (path.basename(absoluteConfigPath) === 'package.json') {
if (!packageProp) {
return throwError(
new Error(
'Please specify the packageProp option. The configPath argument cannot point to a package.json file if packageProp is false.'
)
);
}
load = () =>
loadPackageProp(path.dirname(absoluteConfigPath), {
packageProp,
sync: options.sync,
});
} else {
load = () =>
loadDefinedFile(absoluteConfigPath, {
sync: options.sync,
format: options.format,
});
}
const loadResult = load();
const result =
loadResult instanceof Promise
? loadResult.then(transform)
: transform(loadResult);
if (fileCache) fileCache.set(absoluteConfigPath, result);
return result;
}
const absoluteSearchPath = path.resolve(process.cwd(), searchPath);
const searchPathDir = getDirectory(absoluteSearchPath, options.sync);
return searchPathDir instanceof Promise
? searchPathDir.then(searchDirectory)
: searchDirectory(searchPathDir);
}
function searchDirectory(
directory
) {
if (directoryCache && directoryCache.has(directory)) {
return directoryCache.get(directory);
}
const result = funcRunner(!options.sync ? Promise.resolve() : undefined, [
() => {
if (!packageProp) return;
return loadPackageProp(directory, {
packageProp,
sync: options.sync,
});
},
result => {
if (result || !options.rc) return result;
return loadRc(path.join(directory, options.rc), {
sync: options.sync,
rcStrictJson: options.rcStrictJson,
rcExtensions: options.rcExtensions,
});
},
result => {
if (result || !options.js) return result;
return loadJs(path.join(directory, options.js), { sync: options.sync });
},
result => {
if (result) return result;
const nextDirectory = path.dirname(directory);
if (nextDirectory === directory || directory === options.stopDir)
return null;
return searchDirectory(nextDirectory);
},
transform,
]);
if (directoryCache) directoryCache.set(directory, result);
return result;
}
return {
load,
clearFileCache,
clearDirectoryCache,
clearCaches,
};
};
function identity(x) {
return x;
}
@@ -0,0 +1,22 @@
//
'use strict';
const chainFuncsAsync = (result, func) => result.then(func);
const chainFuncsSync = (result, func) => func(result);
/**
* Runs the given functions sequentially. If the `init` param is a promise,
* functions are chained using `p.then()`. Otherwise, functions are chained by passing
* the result of each function to the next.
*/
module.exports = function funcRunner(
init ,
funcs
) {
const isAsync = init instanceof Promise;
return funcs.reduce(
isAsync === true ? chainFuncsAsync : chainFuncsSync,
init
);
};
@@ -0,0 +1,23 @@
//
'use strict';
const path = require('path');
const isDirectory = require('is-directory');
module.exports = function getDirectory(
filepath ,
sync
) {
if (sync === true) {
return isDirectory.sync(filepath) ? filepath : path.dirname(filepath);
}
return new Promise((resolve, reject) => {
return isDirectory(filepath, (err, filepathIsDirectory) => {
if (err) {
return reject(err);
}
return resolve(filepathIsDirectory ? filepath : path.dirname(filepath));
});
});
};
@@ -0,0 +1,40 @@
//
'use strict';
const os = require('os');
const createExplorer = require('./createExplorer');
const homedir = os.homedir();
module.exports = function cosmiconfig(
moduleName ,
options
) {
options = Object.assign(
{},
{
packageProp: moduleName,
rc: `.${moduleName}rc`,
js: `${moduleName}.config.js`,
rcStrictJson: false,
stopDir: homedir,
cache: true,
sync: false,
},
options
);
return createExplorer(options);
};
@@ -0,0 +1,98 @@
//
'use strict';
const yaml = require('js-yaml');
const requireFromString = require('require-from-string');
const readFile = require('./readFile');
const parseJson = require('./parseJson');
const path = require('path');
module.exports = function loadDefinedFile(
filepath ,
options
) {
function parseContent(content ) {
if (!content) {
throw new Error(`Config file is empty! Filepath - "${filepath}".`);
}
let parsedConfig;
switch (options.format || inferFormat(filepath)) {
case 'json':
parsedConfig = parseJson(content, filepath);
break;
case 'yaml':
parsedConfig = yaml.safeLoad(content, {
filename: filepath,
});
break;
case 'js':
parsedConfig = requireFromString(content, filepath);
break;
default:
parsedConfig = tryAllParsing(content, filepath);
}
if (!parsedConfig) {
throw new Error(`Failed to parse "${filepath}" as JSON, JS, or YAML.`);
}
return {
config: parsedConfig,
filepath,
};
}
return !options.sync
? readFile(filepath, { throwNotFound: true }).then(parseContent)
: parseContent(readFile.sync(filepath, { throwNotFound: true }));
};
function inferFormat(filepath ) {
switch (path.extname(filepath)) {
case '.js':
return 'js';
case '.json':
return 'json';
// istanbul ignore next
case '.yml':
case '.yaml':
return 'yaml';
default:
return undefined;
}
}
function tryAllParsing(content , filepath ) {
return tryYaml(content, filepath, () => {
return tryRequire(content, filepath, () => {
return null;
});
});
}
function tryYaml(content , filepath , cb ) {
try {
const result = yaml.safeLoad(content, {
filename: filepath,
});
if (typeof result === 'string') {
return cb();
}
return result;
} catch (e) {
return cb();
}
}
function tryRequire(content , filepath , cb ) {
try {
return requireFromString(content, filepath);
} catch (e) {
return cb();
}
}
@@ -0,0 +1,23 @@
//
'use strict';
const requireFromString = require('require-from-string');
const readFile = require('./readFile');
module.exports = function loadJs(
filepath ,
options
) {
function parseJsFile(content ) {
if (!content) return null;
return {
config: requireFromString(content, filepath),
filepath,
};
}
return !options.sync
? readFile(filepath).then(parseJsFile)
: parseJsFile(readFile.sync(filepath));
};
@@ -0,0 +1,32 @@
//
'use strict';
const path = require('path');
const readFile = require('./readFile');
const parseJson = require('./parseJson');
module.exports = function loadPackageProp(
packageDir ,
options
) {
const packagePath = path.join(packageDir, 'package.json');
function parseContent(content ) {
if (!content) return null;
const parsedContent = parseJson(content, packagePath);
const packagePropValue = parsedContent[options.packageProp];
if (!packagePropValue) return null;
return {
config: packagePropValue,
filepath: packagePath,
};
}
return !options.sync
? readFile(packagePath).then(parseContent)
: parseContent(readFile.sync(packagePath));
};
@@ -0,0 +1,110 @@
//
'use strict';
const yaml = require('js-yaml');
const requireFromString = require('require-from-string');
const readFile = require('./readFile');
const parseJson = require('./parseJson');
const funcRunner = require('./funcRunner');
module.exports = function loadRc(
filepath ,
options
) {
if (!options.sync) {
return readFile(filepath)
.then(parseExtensionlessRcFile)
.then(checkExtensionlessRcResult);
} else {
return checkExtensionlessRcResult(
parseExtensionlessRcFile(readFile.sync(filepath))
);
}
function checkExtensionlessRcResult(result) {
if (result) return result;
if (options.rcExtensions) return loadRcWithExtensions();
return null;
}
function parseExtensionlessRcFile(content ) {
if (!content) return null;
const pasedConfig = options.rcStrictJson
? parseJson(content, filepath)
: yaml.safeLoad(content, { filename: filepath });
return {
config: pasedConfig,
filepath,
};
}
function loadRcWithExtensions() {
let foundConfig = null;
return funcRunner(readRcFile('json'), [
(jsonContent ) => {
// Since this is the first try, config cannot have been found, so don't
// check `if (foundConfig)`.
if (jsonContent) {
const successFilepath = `${filepath}.json`;
foundConfig = {
config: parseJson(jsonContent, successFilepath),
filepath: successFilepath,
};
} else {
return readRcFile('yaml');
}
},
(yamlContent ) => {
if (foundConfig) {
return;
} else if (yamlContent) {
const successFilepath = `${filepath}.yaml`;
foundConfig = {
config: yaml.safeLoad(yamlContent, { filename: successFilepath }),
filepath: successFilepath,
};
} else {
return readRcFile('yml');
}
},
(ymlContent ) => {
if (foundConfig) {
return;
} else if (ymlContent) {
const successFilepath = `${filepath}.yml`;
foundConfig = {
config: yaml.safeLoad(ymlContent, { filename: successFilepath }),
filepath: successFilepath,
};
} else {
return readRcFile('js');
}
},
(jsContent ) => {
if (foundConfig) {
return;
} else if (jsContent) {
const successFilepath = `${filepath}.js`;
foundConfig = {
config: requireFromString(jsContent, successFilepath),
filepath: successFilepath,
};
} else {
return;
}
},
() => foundConfig,
]);
}
function readRcFile(extension ) {
const filepathWithExtension = `${filepath}.${extension}`;
return !options.sync
? readFile(filepathWithExtension)
: readFile.sync(filepathWithExtension);
}
};
@@ -0,0 +1,16 @@
//
'use strict';
const parseJson = require('parse-json');
module.exports = function parseJsonWrapper(
json ,
filepath
) {
try {
return parseJson(json);
} catch (err) {
err.message = `JSON Error in ${filepath}:\n${err.message}`;
throw err;
}
};
@@ -0,0 +1,42 @@
//
'use strict';
const fs = require('fs');
function readFile(filepath , options ) {
options = options || {};
const throwNotFound = options.throwNotFound || false;
return new Promise((resolve, reject) => {
fs.readFile(filepath, 'utf8', (err, content) => {
if (err && err.code === 'ENOENT' && !throwNotFound) {
return resolve(null);
}
if (err) return reject(err);
resolve(content);
});
});
}
readFile.sync = function readFileSync(
filepath ,
options
) {
options = options || {};
const throwNotFound = options.throwNotFound || false;
try {
return fs.readFileSync(filepath, 'utf8');
} catch (err) {
if (err.code === 'ENOENT' && !throwNotFound) {
return null;
}
throw err;
}
};
module.exports = readFile;
+130
View File
@@ -0,0 +1,130 @@
{
"_from": "cosmiconfig@^4.0.0",
"_id": "cosmiconfig@4.0.0",
"_inBundle": false,
"_integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==",
"_location": "/postcss-load-config/cosmiconfig",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "cosmiconfig@^4.0.0",
"name": "cosmiconfig",
"escapedName": "cosmiconfig",
"rawSpec": "^4.0.0",
"saveSpec": null,
"fetchSpec": "^4.0.0"
},
"_requiredBy": [
"/postcss-load-config"
],
"_resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz",
"_shasum": "760391549580bbd2df1e562bc177b13c290972dc",
"_spec": "cosmiconfig@^4.0.0",
"_where": "D:\\Atom\\Git\\Laravel_CSSd\\node_modules\\postcss-load-config",
"author": {
"name": "David Clark",
"email": "david.dave.clark@gmail.com"
},
"babel": {
"plugins": [
"transform-flow-strip-types"
]
},
"bugs": {
"url": "https://github.com/davidtheclark/cosmiconfig/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "Bogdan Chadkin",
"email": "trysound@yandex.ru"
},
{
"name": "Suhas Karanth",
"email": "sudo.suhas@gmail.com"
}
],
"dependencies": {
"is-directory": "^0.3.1",
"js-yaml": "^3.9.0",
"parse-json": "^4.0.0",
"require-from-string": "^2.0.1"
},
"deprecated": false,
"description": "Find and load configuration from a package.json property, rc file, or CommonJS module",
"devDependencies": {
"babel-eslint": "^8.0.3",
"babel-plugin-transform-flow-strip-types": "^6.22.0",
"eslint": "^4.12.1",
"eslint-config-davidtheclark-node": "^0.2.2",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-flowtype": "^2.39.1",
"eslint-plugin-node": "^5.2.1",
"flow-bin": "^0.54.1",
"flow-remove-types": "^1.2.3",
"husky": "^0.14.3",
"jest": "^21.2.1",
"lint-staged": "^6.0.0",
"prettier": "^1.8.2"
},
"engines": {
"node": ">=4"
},
"files": [
"dist"
],
"homepage": "https://github.com/davidtheclark/cosmiconfig#readme",
"jest": {
"testEnvironment": "node",
"collectCoverageFrom": [
"src/*.js"
],
"coverageThreshold": {
"global": {
"branches": 100,
"functions": 100,
"lines": 100,
"statements": 100
}
}
},
"keywords": [
"load",
"configuration",
"config"
],
"license": "MIT",
"lint-staged": {
"*.js": [
"eslint --fix",
"prettier --write",
"git add"
]
},
"main": "dist/index.js",
"name": "cosmiconfig",
"prettier": {
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 80,
"tabWidth": 2
},
"repository": {
"type": "git",
"url": "git+https://github.com/davidtheclark/cosmiconfig.git"
},
"scripts": {
"build": "flow-remove-types src --out-dir dist --quiet",
"coverage": "jest --coverage --coverageReporters=html --coverageReporters=text",
"format": "prettier --write \"{src/*.js,test/*.js}\"",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"precommit": "lint-staged && jest && flow check",
"prepublishOnly": "npm run build",
"pretest": "npm run lint && flow check",
"test": "jest --coverage",
"test:watch": "jest --watch"
},
"version": "4.0.0"
}
+97
View File
@@ -0,0 +1,97 @@
{
"_from": "postcss-load-config@^2.0.0",
"_id": "postcss-load-config@2.0.0",
"_inBundle": false,
"_integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==",
"_location": "/postcss-load-config",
"_phantomChildren": {
"is-directory": "0.3.1",
"js-yaml": "3.13.1",
"parse-json": "4.0.0",
"require-from-string": "2.0.2"
},
"_requested": {
"type": "range",
"registry": true,
"raw": "postcss-load-config@^2.0.0",
"name": "postcss-load-config",
"escapedName": "postcss-load-config",
"rawSpec": "^2.0.0",
"saveSpec": null,
"fetchSpec": "^2.0.0"
},
"_requiredBy": [
"/postcss-loader"
],
"_resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz",
"_shasum": "f1312ddbf5912cd747177083c5ef7a19d62ee484",
"_spec": "postcss-load-config@^2.0.0",
"_where": "D:\\Atom\\Git\\Laravel_CSSd\\node_modules\\postcss-loader",
"author": {
"name": "Michael Ciniawky",
"email": "michael.ciniawsky@gmail.com"
},
"bugs": {
"url": "https://github.com/michael-ciniawsky/postcss-load-config/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "Ryan Dunckel"
},
{
"name": "Mateusz Derks"
},
{
"name": "Dalton Santos"
},
{
"name": "Patrick Gilday"
}
],
"dependencies": {
"cosmiconfig": "^4.0.0",
"import-cwd": "^2.0.0"
},
"deprecated": false,
"description": "Autoload Config for PostCSS",
"devDependencies": {
"cssnano": "^4.0.0",
"del-cli": "^1.0.0",
"jest": "^22.0.0",
"jsdoc-to-markdown": "^4.0.0",
"postcss": "^6.0.0",
"postcss-import": "^11.0.0",
"postcss-nested": "^3.0.0",
"standard": "^11.0.0",
"standard-version": "4.0.0",
"sugarss": "^1.0.0"
},
"engines": {
"node": ">= 4"
},
"files": [
"src"
],
"homepage": "https://github.com/michael-ciniawsky/postcss-load-config#readme",
"keywords": [
"postcss",
"postcssrc",
"postcss.config.js"
],
"license": "MIT",
"main": "src/index.js",
"name": "postcss-load-config",
"repository": {
"type": "git",
"url": "git+https://github.com/michael-ciniawsky/postcss-load-config.git"
},
"scripts": {
"clean": "del-cli coverage",
"docs": "jsdoc2md src/*.js > DOCS.md",
"lint": "standard --env jest",
"release": "standard-version",
"test": "jest --verbose --coverage"
},
"version": "2.0.0"
}
+92
View File
@@ -0,0 +1,92 @@
'use strict'
const resolve = require('path').resolve
const config = require('cosmiconfig')
const loadOptions = require('./options.js')
const loadPlugins = require('./plugins.js')
/**
* Load Config
*
* @method rc
*
* @param {Object} ctx Config Context
* @param {String} path Config Path
* @param {Object} options Config Options
*
* @return {Promise} config PostCSS Config
*/
const rc = (ctx, path, options) => {
/**
* @type {Object}
*
* @prop {String} cwd=process.cwd() Config search start location
* @prop {String} env=process.env.NODE_ENV Config Enviroment, will be set to `development` by `postcss-load-config` if `process.env.NODE_ENV` is `undefined`
*/
ctx = Object.assign({
cwd: process.cwd(),
env: process.env.NODE_ENV
}, ctx)
/**
* @type {String} `process.cwd()`
*
*/
path = path ? resolve(path) : process.cwd()
/**
* @type {Object}
*
* @prop {Boolean} rcExtensions=true
*/
options = Object.assign({
rcExtensions: true
}, options)
if (!ctx.env) {
process.env.NODE_ENV = 'development'
}
return config('postcss', options)
.load(path)
.then((result) => {
if (!result) {
throw new Error(`No PostCSS Config found in: ${path}`)
}
let file = result.filepath || ''
let config = result.config || {}
if (typeof config === 'function') {
config = config(ctx)
} else {
config = Object.assign({}, config, ctx)
}
if (!config.plugins) {
config.plugins = []
}
return {
plugins: loadPlugins(config, file),
options: loadOptions(config, file),
file: file
}
})
}
/**
* Autoload Config for PostCSS
*
* @author Michael Ciniawsky @michael-ciniawsky <michael.ciniawsky@gmail.com>
* @license MIT
*
* @module postcss-load-config
* @version 2.0.0
*
* @requires comsiconfig
* @requires ./options
* @requires ./plugins
*/
module.exports = rc
+47
View File
@@ -0,0 +1,47 @@
'use strict'
const req = require('import-cwd')
/**
* Load Options
*
* @private
* @method options
*
* @param {Object} config PostCSS Config
*
* @return {Object} options PostCSS Options
*/
const options = (config, file) => {
if (config.parser && typeof config.parser === 'string') {
try {
config.parser = req(config.parser)
} catch (err) {
throw new Error(`Loading PostCSS Parser failed: ${err.message}\n\n(@${file})`)
}
}
if (config.syntax && typeof config.syntax === 'string') {
try {
config.syntax = req(config.syntax)
} catch (err) {
throw new Error(`Loading PostCSS Syntax failed: ${err.message}\n\n(@${file})`)
}
}
if (config.stringifier && typeof config.stringifier === 'string') {
try {
config.stringifier = req(config.stringifier)
} catch (err) {
throw new Error(`Loading PostCSS Stringifier failed: ${err.message}\n\n(@${file})`)
}
}
if (config.plugins) {
delete config.plugins
}
return config
}
module.exports = options
+80
View File
@@ -0,0 +1,80 @@
'use strict'
const req = require('import-cwd')
/**
* Plugin Loader
*
* @private
* @method load
*
* @param {String} plugin PostCSS Plugin Name
* @param {Object} options PostCSS Plugin Options
*
* @return {Function} PostCSS Plugin
*/
const load = (plugin, options, file) => {
if (options === null || Object.keys(options).length === 0) {
try {
return req(plugin)
} catch (err) {
throw new Error(`Loading PostCSS Plugin failed: ${err.message}\n\n(@${file})`)
}
} else {
try {
return req(plugin)(options)
} catch (err) {
throw new Error(`Loading PostCSS Plugin failed: ${err.message}\n\n(@${file})`)
}
}
}
/**
* Load Plugins
*
* @private
* @method plugins
*
* @param {Object} config PostCSS Config Plugins
*
* @return {Array} plugins PostCSS Plugins
*/
const plugins = (config, file) => {
let plugins = []
if (Array.isArray(config.plugins)) {
plugins = config.plugins.filter(Boolean)
} else {
plugins = Object.keys(config.plugins)
.filter((plugin) => {
return config.plugins[plugin] !== false ? plugin : ''
})
.map((plugin) => {
return load(plugin, config.plugins[plugin], file)
})
}
if (plugins.length && plugins.length > 0) {
plugins.forEach((plugin, i) => {
if (plugin.postcss) {
plugin = plugin.postcss
}
if (plugin.default) {
plugin = plugin.default
}
if (
// eslint-disable-next-line
!(typeof plugin === 'object' && Array.isArray(plugin.plugins) ||
typeof plugin === 'function')
) {
throw new TypeError(`Invalid PostCSS Plugin found at: plugins[${i}]\n\n(@${file})`)
}
})
}
return plugins
}
module.exports = plugins